diff --git a/.github/actions/ccip-e2e-setup/action.yml b/.github/actions/ccip-e2e-setup/action.yml new file mode 100644 index 000000000..658fcda6a --- /dev/null +++ b/.github/actions/ccip-e2e-setup/action.yml @@ -0,0 +1,92 @@ +name: 'CCIP E2E Setup' +description: 'Common setup for CCIP E2E tests - caches, dependencies, and environment' + +inputs: + contract_version: + description: 'Contract version to test against (local or commit SHA)' + required: true + default: 'local' + build_contracts: + description: 'Whether to build contracts locally' + required: false + default: 'true' + +runs: + using: 'composite' + steps: + - name: Free Disk Space + uses: smartcontractkit/.github/actions/free-disk-space@free-disk-space/v1 + + - name: Relocate Nix store to /mnt + shell: bash + run: | + sudo mkdir -p /mnt/nix + sudo mkdir -p /nix + sudo mount --bind /mnt/nix /nix + df -h /nix /mnt + + - name: Restore cached docker images + uses: actions/cache@v4 + id: docker-cache-restore + with: + path: ${{ github.workspace }}/.cache/ccip-e2e-docker-images.tar + key: ccip-e2e-images-v2 + + - name: Load docker images + if: steps.docker-cache-restore.outputs.cache-hit == 'true' + shell: bash + run: | + echo "Cache hit. Loading images from tarball..." + docker load -i ${{ github.workspace }}/.cache/ccip-e2e-docker-images.tar + + - name: Install Nix + uses: cachix/install-nix-action@02a151ada4993995686f9ed4f1be7cfbb229e56f # v31 + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: Cache Go modules + uses: actions/cache@v4 + with: + path: | + /home/runner/.cache/go-build + /home/runner/go/pkg/mod + key: go-${{ hashFiles('**/go.sum', 'chainlink/**/go.sum') }} + + - name: Read Chainlink Core Ref + id: read_core_ref + shell: bash + run: | + CORE_REF=$(cat ./scripts/.core_version | tr -d '[:space:]') + # Validate it's a 40-char hex SHA (not a branch name) + if [[ ! "$CORE_REF" =~ ^[0-9a-f]{40}$ ]]; then + echo "ERROR: .core_version must be a full commit SHA, got: $CORE_REF" + exit 1 + fi + echo "CORE_REF=$CORE_REF" >> $GITHUB_OUTPUT + + - name: Cache Chainlink Core repo + uses: actions/cache@v4 + id: core-cache + with: + path: chainlink + key: core-${{ steps.read_core_ref.outputs.CORE_REF }} + + - name: Checkout Chainlink Core repo + if: steps.core-cache.outputs.cache-hit != 'true' + uses: actions/checkout@v5 + with: + repository: smartcontractkit/chainlink + ref: ${{ steps.read_core_ref.outputs.CORE_REF }} + path: chainlink + persist-credentials: false + + - name: Build contracts + if: inputs.build_contracts == 'true' + shell: bash + run: | + cd contracts + nix develop .#contracts -c yarn && yarn build + + - name: Set contract version environment + shell: bash + run: echo "CCIP_CONTRACTS_TON_VERSION=${{ inputs.contract_version }}" >> $GITHUB_ENV diff --git a/.github/ccip-ton-tests.yml b/.github/ccip-ton-tests.yml new file mode 100644 index 000000000..c910422d0 --- /dev/null +++ b/.github/ccip-ton-tests.yml @@ -0,0 +1,16 @@ +# CCIP TON E2E Test Definitions +# This file is the single source of truth for CCIP TON integration tests. +# Both ccip-integration-test.yml and ccip-staging-compat.yml workflows read from this file. +# +# To add a new test: +# 1. Add an entry to the 'tests' list below +# 2. The test will automatically run in both local and staging compatibility checks + +tests: + - id: ccip_messaging_ton2evm + name: "TON2EVM Messaging Test" + cmd: "cd integration-tests && go test ./smoke/ccip -run Test_CCIPMessaging_TON2EVM -timeout 20m -test.parallel=1 -count=1 -json" + + - id: ccip_messaging_evm2ton + name: "EVM2TON Messaging Test" + cmd: "cd integration-tests && go test ./smoke/ccip -run Test_CCIPMessaging_EVM2TON -timeout 20m -test.parallel=1 -count=1 -json" diff --git a/.github/workflows/ccip-integration-test.yml b/.github/workflows/ccip-integration-test.yml index 71034493c..f2db1287b 100644 --- a/.github/workflows/ccip-integration-test.yml +++ b/.github/workflows/ccip-integration-test.yml @@ -14,10 +14,10 @@ env: DOCKER_CACHE_KEY: ccip-e2e-images-v2 DOCKER_CACHE_DIR: ${{ github.workspace }}/.cache DOCKER_CACHE_TAR_NAME: ccip-e2e-docker-images.tar - # mylocalton docker image / CCIP E2E test database image DOCKER_IMAGES: >- ghcr.io/neodix42/mylocalton-docker:v3.7 postgres:16-alpine + jobs: prepare-images: name: Prepare and Cache Docker Images @@ -44,116 +44,66 @@ jobs: docker save ${{ env.DOCKER_IMAGES }} \ -o ${{ env.DOCKER_CACHE_DIR }}/${{ env.DOCKER_CACHE_TAR_NAME }} - integration-test-matrix: - needs: prepare-images - strategy: - fail-fast: false - matrix: - type: - # Note: list of tests, add more tests here - - name: "TON2EVM Messaging Test" - cmd: "cd integration-tests && go test ./smoke/ccip -run Test_CCIPMessaging_TON2EVM -timeout 20m -test.parallel=1 -count=1 -json" - - name: "EVM2TON Messaging Test" - cmd: "cd integration-tests && go test ./smoke/ccip -run Test_CCIPMessaging_EVM2TON -timeout 20m -test.parallel=1 -count=1 -json" - - name: ${{ matrix.type.name }} + load-tests: + name: Load Test Matrix runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} steps: - - name: Free Disk Space - uses: smartcontractkit/.github/actions/free-disk-space@free-disk-space/v1 - - name: Checkout Repository uses: actions/checkout@v5 - - name: Restore cached docker images - id: docker-cache-restore - uses: actions/cache@v4 - with: - path: ${{ env.DOCKER_CACHE_DIR }}/${{ env.DOCKER_CACHE_TAR_NAME }} - key: ${{ env.DOCKER_CACHE_KEY }} - - - name: Load docker images - if: steps.docker-cache-restore.outputs.cache-hit == 'true' + - name: Load test definitions + id: set-matrix run: | - echo "Cache hit for key '${{ env.DOCKER_CACHE_KEY }}'. Loading images from tarball..." - docker load -i ${{ env.DOCKER_CACHE_DIR }}/${{ env.DOCKER_CACHE_TAR_NAME }} - - - name: Relocate Nix store to /mnt - run: | - sudo mkdir -p /mnt/nix - sudo mkdir -p /nix - sudo mount --bind /mnt/nix /nix - df -h /nix /mnt - - - name: Install Nix - uses: cachix/install-nix-action@02a151ada4993995686f9ed4f1be7cfbb229e56f # v31 - with: - nix_path: nixpkgs=channel:nixos-unstable + MATRIX=$(yq -o=json -I=0 '.tests' .github/ccip-ton-tests.yml) + echo "matrix=$MATRIX" >> $GITHUB_OUTPUT - # cache Go build artifacts and modules to speed up subsequent runs - # key includes go.sum files from both chainlink-ton and chainlink core repos - # paths are standard Go cache locations on GitHub Actions runners - - name: Cache Go modules - uses: actions/cache@v4 - with: - path: | - /home/runner/.cache/go-build - /home/runner/go/pkg/mod - key: go-${{ hashFiles('**/go.sum', 'chainlink/**/go.sum') }} - - - name: Read Chainlink Core Ref from .core_version - id: read_core_ref - run: echo "CORE_REF=$(cat ./scripts/.core_version | tr -d '[:space:]')" >> $GITHUB_OUTPUT - - # cache the entire Chainlink Core repository to avoid re-cloning - # key is based on the exact commit SHA from .core_version file - # only checkout if cache miss occurs - - name: Cache Chainlink Core repo - uses: actions/cache@v4 - id: core-cache - with: - path: chainlink - key: core-${{ steps.read_core_ref.outputs.CORE_REF }} - - - name: Checkout Chainlink Core repo - if: steps.core-cache.outputs.cache-hit != 'true' + integration-test: + name: ${{ matrix.test.name }} + needs: [prepare-images, load-tests] + runs-on: ubuntu-latest-4cores-16GB + strategy: + fail-fast: false + matrix: + test: ${{ fromJson(needs.load-tests.outputs.matrix) }} + steps: + - name: Checkout Repository uses: actions/checkout@v5 - with: - repository: smartcontractkit/chainlink - ref: ${{ steps.read_core_ref.outputs.CORE_REF }} - path: chainlink - - name: Build contracts - run: | - cd contracts - nix develop .#contracts -c yarn && yarn build + - name: Setup E2E Environment + uses: ./.github/actions/ccip-e2e-setup + with: + contract_version: 'local' + build_contracts: 'true' - - name: Setup Environment and Run Tests + - name: Run Tests run: | + echo "Testing with contract version: $CCIP_CONTRACTS_TON_VERSION" nix develop .#ccip-e2e -c scripts/e2e/setup-env.sh --core-dir "${GITHUB_WORKSPACE}/chainlink" - nix develop .#ccip-e2e -c scripts/e2e/run-test.sh --core-dir "${GITHUB_WORKSPACE}/chainlink" --test-command "${{ matrix.type.cmd }}" --clean-logs + nix develop .#ccip-e2e -c scripts/e2e/run-test.sh --core-dir "${GITHUB_WORKSPACE}/chainlink" --test-command "${{ matrix.test.cmd }}" --clean-logs - - name: Upload e2e test logs on success + - name: Upload test logs on success if: success() uses: actions/upload-artifact@v4 with: - name: ccip-test-logs-${{ matrix.type.name }} + name: ccip-test-logs-${{ matrix.test.id }} path: chainlink/integration-tests/smoke/ccip/logs/ retention-days: 3 - - name: Upload e2e test logs on failure + - name: Upload test logs on failure if: failure() uses: actions/upload-artifact@v4 with: - name: ccip-test-logs-${{ matrix.type.name }} + name: ccip-test-logs-${{ matrix.test.id }} path: chainlink/integration-tests/smoke/ccip/logs/ retention-days: 7 integration-test-ccip: if: always() runs-on: ubuntu-latest - needs: [integration-test-matrix] + needs: [integration-test] steps: - - name: Fail if any CCIP test failed - if: always() && needs.integration-test-matrix.result == 'failure' + - name: Check test results + if: needs.integration-test.result == 'failure' run: exit 1 diff --git a/.github/workflows/ccip-staging-compat.yml b/.github/workflows/ccip-staging-compat.yml new file mode 100644 index 000000000..69264d42c --- /dev/null +++ b/.github/workflows/ccip-staging-compat.yml @@ -0,0 +1,101 @@ +name: "TON - CCIP Staging Compatibility" + +# This workflow tests plugin compatibility with staging-deployed contracts. +# It serves as an early warning system - failures indicate that merging this PR +# will break staging until contracts are also updated. +# +# This workflow is INFORMATIONAL and should NOT be required for merge. +# Configure branch protection to only require "TON - CCIP Integration Tests". + +on: + pull_request: + push: + branches: + - "main" + +permissions: + contents: read + actions: read + +env: + DOCKER_CACHE_KEY: ccip-e2e-images-v2 + DOCKER_CACHE_DIR: ${{ github.workspace }}/.cache + DOCKER_CACHE_TAR_NAME: ccip-e2e-docker-images.tar + +jobs: + load-tests: + name: Load Test Matrix + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + staging_version: ${{ steps.read-staging.outputs.version }} + steps: + - name: Checkout Repository + uses: actions/checkout@v5 + + - name: Load test definitions + id: set-matrix + run: | + MATRIX=$(yq -o=json -I=0 '.tests' .github/ccip-ton-tests.yml) + echo "matrix=$MATRIX" >> $GITHUB_OUTPUT + + - name: Read staging contract version + id: read-staging + run: | + VERSION=$(cat ./scripts/.staging_contract_version | tr -d '[:space:]') + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Staging contract version: $VERSION" + + staging-compat-test: + name: "${{ matrix.test.name }} (Staging)" + needs: [load-tests] + runs-on: ubuntu-latest-4cores-16GB + strategy: + fail-fast: false + matrix: + test: ${{ fromJson(needs.load-tests.outputs.matrix) }} + steps: + - name: Checkout Repository + uses: actions/checkout@v5 + + - name: Setup E2E Environment + uses: ./.github/actions/ccip-e2e-setup + with: + contract_version: ${{ needs.load-tests.outputs.staging_version }} + build_contracts: 'false' + + - name: Run Tests + run: | + echo "Testing staging compatibility with contract version: $CCIP_CONTRACTS_TON_VERSION" + nix develop .#ccip-e2e -c scripts/e2e/setup-env.sh --core-dir "${GITHUB_WORKSPACE}/chainlink" + nix develop .#ccip-e2e -c scripts/e2e/run-test.sh --core-dir "${GITHUB_WORKSPACE}/chainlink" --test-command "${{ matrix.test.cmd }}" --clean-logs + + - name: Upload test logs on success + if: success() + uses: actions/upload-artifact@v4 + with: + name: ccip-staging-compat-logs-${{ matrix.test.id }} + path: chainlink/integration-tests/smoke/ccip/logs/ + retention-days: 3 + + - name: Upload test logs on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: ccip-staging-compat-logs-${{ matrix.test.id }} + path: chainlink/integration-tests/smoke/ccip/logs/ + retention-days: 7 + + staging-compat-status: + name: Staging Compatibility Status + if: always() + runs-on: ubuntu-latest + needs: [staging-compat-test] + steps: + - name: Report staging compatibility + run: | + if [ "${{ needs.staging-compat-test.result }}" == "failure" ]; then + echo "::warning::Staging compatibility tests failed. After merging, staging contracts must be updated." + exit 1 + fi + echo "Staging compatibility tests passed." diff --git a/scripts/.staging_contract_version b/scripts/.staging_contract_version new file mode 100644 index 000000000..805496400 --- /dev/null +++ b/scripts/.staging_contract_version @@ -0,0 +1 @@ +43d7a93089fe diff --git a/scripts/e2e/lib.sh b/scripts/e2e/lib.sh index 5d90b52de..cecb12451 100644 --- a/scripts/e2e/lib.sh +++ b/scripts/e2e/lib.sh @@ -166,6 +166,8 @@ setup_contracts() { log_info "Linking contracts to chainlink core (no copy, direct reference via symlink)..." ln -sfn "$ROOT_DIR/contracts" "$chainlink_core_dir/contracts" - export CCIP_CONTRACTS_TON_VERSION="local" + # Default to "local" if not already set externally + export CCIP_CONTRACTS_TON_VERSION="${CCIP_CONTRACTS_TON_VERSION:-local}" + log_info "Contracts version: $CCIP_CONTRACTS_TON_VERSION" log_info "Contracts ready at $chainlink_core_dir/contracts -> $ROOT_DIR/contracts" }