Deployment Tests #4727
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deployment Tests | |
| run-name: Deployment Tests | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name | |
| }}-deployments-tests | |
| cancel-in-progress: true | |
| # Run on key branches to make sure integration is good, otherwise run on all PR's | |
| on: | |
| push: | |
| branches: | |
| - develop | |
| - "release/*" | |
| merge_group: | |
| pull_request: | |
| schedule: | |
| - cron: "0 0,1,2,3,4,5,6,20,21,22,23 * * *" # Run regularly at night to get better flaky test data | |
| workflow_dispatch: | |
| jobs: | |
| filter: | |
| name: Detect Changes | |
| permissions: | |
| pull-requests: read | |
| outputs: | |
| # Runs on workflow changes, any deployment change, or any (non-ignored) core change | |
| should-run: >- | |
| ${{ | |
| steps.match-some.outputs.workflow == 'true' || | |
| steps.match-some.outputs.deployment == 'true' || | |
| steps.match-every.outputs.core-non-ignored == 'true' || | |
| github.event_name == 'schedule' || | |
| github.event_name == 'workflow_dispatch' | |
| }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout the repo | |
| uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| repository: smartcontractkit/chainlink | |
| - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 | |
| id: match-some | |
| with: | |
| # "if any changed file matches one or more of the conditions" (https://github.com/dorny/paths-filter/issues/225) | |
| predicate-quantifier: some | |
| # deployment - any changes in the deployment module | |
| # workflow - any changes that could affect this workflow definition | |
| # - Assume any repository action changes affect this workflow | |
| filters: | | |
| deployment: | |
| - 'deployment/**' | |
| workflow: | |
| - '.github/workflows/ci-deployments.yml' | |
| - '.github/actions/**' | |
| - uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1 | |
| id: match-every | |
| with: | |
| # "if any changed file match all of the conditions" (https://github.com/dorny/paths-filter/issues/225) | |
| # - Enables listing of files matching each filter. | |
| # - Paths to files will be available in `${FILTER_NAME}_files` output variable. | |
| # - Paths will be formatted as JSON array | |
| predicate-quantifier: every | |
| # core-non-ignored - all changes except for paths which do not affect core module | |
| # - This is opt-in on purpose. To be safe, new files are assumed to have an affect on core unless listed here specifically. | |
| # - For example: core module does not depend on deployment or integration-tests module. | |
| # all - changes in any directory | |
| # - This is used resolve all affected modules based on changed files | |
| list-files: json | |
| filters: | | |
| core-non-ignored: | |
| - '**' | |
| - '!deployment/**' | |
| - '!integration-tests/**' | |
| - '!tools/secrets/**' | |
| - '!tools/docker/**' | |
| - '!tools/benchmark/**' | |
| - '!**/README.md' | |
| - '!**/CHANGELOG.md' | |
| - '!*.nix' | |
| - '!sonar-project.properties' | |
| - '!nix.conf' | |
| - '!nix-darwin-shell-hook.sh' | |
| - '!LICENSE' | |
| - '!.github/**' | |
| - '!core/scripts/cre/environment/examples/workflows/**' | |
| all: | |
| - '**' | |
| - name: Decide which tests to run (rollout-only) | |
| # To validate that this properly tests, we will run this beside the dorny/paths-filter actions | |
| # before using its output to actually gate any jobs. | |
| id: triggers | |
| uses: smartcontractkit/.github/actions/advanced-triggers@advanced-triggers/v1 | |
| continue-on-error: true | |
| with: | |
| file-sets: | | |
| included-files: | |
| - "**/*.go" | |
| - "**/go.mod" | |
| - "**/go.sum" | |
| - "core/**" | |
| - "deployment/**" | |
| - ".github/workflows/ci-deployments.yml" | |
| - ".github/actions/**" | |
| - "tools/bin/go_deployment_tests" | |
| excluded-files: | |
| - "testdata/**" | |
| - "core/**/testdata/**" | |
| - "core/**/*_test.go" | |
| - "system-tests/**" | |
| - "integration-tests/**" | |
| - "core/scripts/cre/environment/examples/workflows/**" | |
| # Note: | |
| # - for pull_request, merge_group, and push events, a trigger will resolve to true if any changed files match the path/glob patterns | |
| # - exclusion-sets/negations are applied first, and therefore filter all changed files before inclusion sets are applied | |
| # - by default these will resolve to true for schedule, and workflow_dispatch events | |
| triggers: | | |
| deployment-tests: | |
| exclusion-sets: [ excluded-files ] | |
| inclusion-sets: [ included-files ] | |
| deployment-tests: | |
| env: | |
| # We explicitly have this env var not be "CL_DATABASE_URL" to avoid having it be used by core related tests | |
| # when they should not be using it, while still allowing us to DRY up the setup | |
| DB_URL: postgresql://postgres:postgres@localhost:5432/chainlink_test?sslmode=disable | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| shard-id: [1, 2, 3, 4, 5, 6, 7] | |
| name: Deployment Tests (go_deployment_tests shard ${{ matrix.shard-id }}/${{ strategy.job-total }}) | |
| if: ${{ github.actor != 'dependabot[bot]' && needs.filter.outputs.should-run == 'true' }} | |
| needs: [filter] | |
| timeout-minutes: 35 | |
| runs-on: "runs-on=${{ github.run_id }}-deployment-${{ matrix.shard-id }}/cpu=8/ram=32/family=m6id+m6idn/spot=false/image=ubuntu24-full-x64/extras=s3-cache" | |
| outputs: | |
| shard-count: ${{ strategy.job-total }} | |
| permissions: | |
| id-token: write | |
| contents: read | |
| actions: read | |
| steps: | |
| - name: Enable S3 Cache for Self-Hosted Runners | |
| uses: runs-on/action@d141ef83eb66d096ce8afc767e09115a65c63b60 # v2.1.2 | |
| - name: Checkout the repo | |
| uses: actions/checkout@v6 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Go | |
| uses: ./.github/actions/setup-go | |
| with: | |
| restore-build-cache-only: false | |
| build-cache-version: go_deployment_tests-${{ matrix.shard-id }} | |
| go-version-file: deployment/go.mod | |
| go-module-file: deployment/go.sum | |
| - name: Setup Solana | |
| uses: ./.github/actions/setup-solana | |
| - name: Setup Aptos | |
| uses: aptos-labs/actions/install-aptos-cli@fdd3a3a628c840d5c35086a87e9cc3141b635505 # 2026-05-20 | |
| with: | |
| CLI_VERSION: 8.1.0 | |
| - name: Setup Sui CLI v1.72.2 | |
| uses: ./.github/actions/setup-sui | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| version: mainnet-v1.72.2 | |
| - name: Setup Postgres | |
| uses: smartcontractkit/.github/actions/setup-postgres@setup-postgres/v1 | |
| with: | |
| tmpfs: "true" | |
| image-tag: "16-alpine" | |
| postgres-options: "-c max_connections=1000 -c shared_buffers=2GB -c fsync=off -c synchronous_commit=off -c full_page_writes=off -c client_min_messages=warning" # Turn off some prod-protections to make postgres go brrr. https://github.com/peterldowns/pgtestdb#how-do-i-make-it-go-faster | |
| - name: Download Go vendor packages | |
| run: go mod download | |
| - name: Setup DB | |
| run: go run ./core/store/cmd/preparetest | |
| env: | |
| CL_DATABASE_URL: ${{ env.DB_URL }} | |
| - name: Install LOOP Plugins | |
| run: make install-plugins | |
| - name: Run tests | |
| timeout-minutes: 25 | |
| continue-on-error: true | |
| id: run-tests | |
| shell: bash | |
| env: | |
| CL_DATABASE_URL: ${{ env.DB_URL }} | |
| OUTPUT_FILE: ./output.txt | |
| PRODUCE_JUNIT_XML: "true" | |
| TRUNK_AUTO_QUARANTINE: "true" | |
| RUN_QUARANTINED_TESTS: "true" | |
| JUNIT_FILE: ${{ github.workspace }}/junit.xml | |
| GO_TEST_SHARD_COUNT: ${{ strategy.job-total }} | |
| GO_TEST_SHARD_INDEX: ${{ strategy.job-index }} | |
| run: | | |
| GODEBUG=goindex=0 "./tools/bin/go_deployment_tests" ./... | |
| # See: https://github.com/golang/go/issues/69179 | |
| - name: Analyze and upload test results | |
| if: ${{ !cancelled() }} | |
| uses: smartcontractkit/.github/actions/branch-out-upload@branch-out-upload/v1 | |
| with: | |
| junit-file-path: "./junit.xml" | |
| trunk-org-slug: chainlink | |
| trunk-token: ${{ secrets.TRUNK_API_KEY }} | |
| trunk-previous-step-outcome: ${{ steps.run-tests.outcome }} | |
| trunk-upload-only: false | |
| artifact-name: "go_deployment_tests_logs_shard_${{ matrix.shard-id }}" | |
| - name: Print postgres logs | |
| if: ${{ always() }} | |
| uses: smartcontractkit/.github/actions/setup-postgres@setup-postgres/v1 | |
| with: | |
| print-logs: "true" | |
| - name: Store logs artifacts | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: "go_deployment_tests_logs_shard_${{ matrix.shard-id }}_always" | |
| path: | | |
| ./deployment/coverage.txt | |
| ./postgres_logs.txt | |
| ./junit.xml | |
| ./deployment/output.txt | |
| ./deployment/output-short.txt | |
| retention-days: 7 | |
| deployment-tests-result: | |
| # Do not modify this job name, it is used by branch protection rules | |
| name: Core Tests (go_core_deployment_tests) | |
| if: ${{ always() && github.actor != 'dependabot[bot]' && needs.filter.outputs.should-run == 'true' }} | |
| needs: [filter, deployment-tests] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| actions: read | |
| contents: read | |
| steps: | |
| - name: Check deployment shard results | |
| env: | |
| EXPECTED_ROWS: ${{ needs.deployment-tests.outputs.shard-count }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| JOB_NAME_PREFIX: "Deployment Tests (go_deployment_tests shard " | |
| run: | | |
| gh api \ | |
| --paginate \ | |
| --jq '.jobs[] | {name, conclusion} | @json' \ | |
| "/repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}/jobs?per_page=100" \ | |
| > jobs.jsonl | |
| python - <<'PY' | |
| import json | |
| import os | |
| import sys | |
| prefix = os.environ["JOB_NAME_PREFIX"] | |
| expected = int(os.environ["EXPECTED_ROWS"]) | |
| rows = [] | |
| with open("jobs.jsonl", encoding="utf-8") as f: | |
| for line in f: | |
| row = json.loads(line) | |
| if row["name"].startswith(prefix): | |
| rows.append(row) | |
| if len(rows) != expected: | |
| print(f"Expected {expected} rows for {prefix}, got {len(rows)}") | |
| sys.exit(1) | |
| conclusions = [row["conclusion"] for row in rows] | |
| if any(conclusion not in {"success", "skipped"} for conclusion in conclusions): | |
| print(f"Deployment shard group failed with conclusions: {conclusions}") | |
| sys.exit(1) | |
| print("All deployment shards succeeded.") | |
| PY |