Skip to content

Deployment Tests

Deployment Tests #4727

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