perf(params): validate ConsensusParams once per change set (CON-312) #16056
Workflow file for this run
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
| # This workflow will build a golang project | |
| # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go | |
| name: Docker Integration Test | |
| on: | |
| push: | |
| branches: | |
| - main | |
| - release/** | |
| pull_request: | |
| branches: | |
| - main | |
| - release/** | |
| merge_group: | |
| branches: | |
| - main | |
| - release/** | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event_name == 'push' && github.sha || github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| defaults: | |
| run: | |
| shell: bash | |
| jobs: | |
| # Generate the integration-test matrix from integration-test-matrix.json. | |
| # Runs the full matrix on every event (pull_request, push, merge_group) — all | |
| # Autobahn coverage runs on every PR. The matrix is built here, in a job | |
| # output, because the `matrix` context is NOT available to a job-level `if:`. | |
| set-matrix: | |
| name: Resolve integration test matrix | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| outputs: | |
| tests: ${{ steps.build.outputs.tests }} | |
| steps: | |
| # See: https://github.com/actions/checkout/releases/tag/v7.0.0 | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| - name: Build matrix | |
| id: build | |
| run: | | |
| set -euo pipefail | |
| matrix_file=.github/workflows/integration-test-matrix.json | |
| tests=$(jq -c '.' "$matrix_file") | |
| echo "tests=$tests" >> "$GITHUB_OUTPUT" | |
| echo "Selected $(echo "$tests" | jq 'length') matrix entries." | |
| # Build localnode/rpcnode images and seid once; matrix jobs pull the images | |
| # from GHCR (tagged with the run id) and download seid as a small artifact. | |
| prepare-cluster: | |
| name: Prepare integration test cluster | |
| runs-on: ubuntu-large | |
| timeout-minutes: 45 | |
| # packages:write required to push images and buildx cache to GHCR. Fork PRs | |
| # cannot publish org packages, so integration tests cannot run from forks; a | |
| # maintainer must push external contributions to a branch on this repo. | |
| # cache-to is restricted to push events to avoid cache thrashing on PRs. | |
| permissions: | |
| packages: write | |
| contents: read | |
| env: | |
| GHCR_LOCALNODE: ghcr.io/sei-protocol/sei-chain-integration-test-localnode | |
| GHCR_RPCNODE: ghcr.io/sei-protocol/sei-chain-integration-test-rpcnode | |
| steps: | |
| # See: https://github.com/actions/checkout/releases/tag/v7.0.0 | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| # Reclaim disk and push Docker + Go caches onto /mnt before the | |
| # image builds so the runner's small root filesystem does not fill up and | |
| # crash the runner mid-job. | |
| - name: Reclaim runner disk | |
| run: bash .github/scripts/ci-free-disk.sh | |
| - name: Relocate Docker data-root to /mnt | |
| run: bash .github/scripts/ci-relocate-docker-data-root.sh | |
| - name: Relocate Go caches to /mnt | |
| run: bash .github/scripts/ci-relocate-go-cache.sh | |
| - name: Login to Docker Hub | |
| # See: https://github.com/docker/login-action/releases/tag/v4.2.0 | |
| uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee | |
| if: env.DOCKERHUB_USERNAME != '' | |
| env: | |
| DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Login to GitHub Container Registry | |
| # See: https://github.com/docker/login-action/releases/tag/v4.2.0 | |
| uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Docker Buildx | |
| # See: https://github.com/docker/setup-buildx-action/releases/tag/v4.1.0 | |
| uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 | |
| - name: Build localnode image (cached) | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: docker/localnode | |
| file: docker/localnode/Dockerfile | |
| platforms: linux/amd64 | |
| push: false | |
| load: true | |
| tags: sei-chain/localnode | |
| # Run-id label makes each run's image digest unique (config-only | |
| # change, layer cache unaffected) so old run tags can be pruned without | |
| # touching digests other runs still reference. | |
| labels: sei-chain.ci-run-id=${{ github.run_id }} | |
| cache-from: type=registry,ref=${{ env.GHCR_LOCALNODE }}:cache | |
| cache-to: ${{ github.event_name == 'push' && format('type=registry,ref={0}:cache,mode=max', env.GHCR_LOCALNODE) || '' }} | |
| - name: Build rpcnode image (cached) | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: docker/rpcnode | |
| file: docker/rpcnode/Dockerfile | |
| platforms: linux/amd64 | |
| push: false | |
| load: true | |
| tags: sei-chain/rpcnode | |
| labels: sei-chain.ci-run-id=${{ github.run_id }} | |
| cache-from: type=registry,ref=${{ env.GHCR_RPCNODE }}:cache | |
| cache-to: ${{ github.event_name == 'push' && format('type=registry,ref={0}:cache,mode=max', env.GHCR_RPCNODE) || '' }} | |
| # rpcnode is independent of the seid build, so push it now: push failures | |
| # (retried below) surface before the expensive seid build rather than after. | |
| - name: Push rpcnode image to GHCR for test jobs | |
| run: | | |
| source .github/scripts/docker-registry-retry.sh | |
| docker tag sei-chain/rpcnode "${GHCR_RPCNODE}:${{ github.run_id }}" | |
| push_with_retry "${GHCR_RPCNODE}:${{ github.run_id }}" | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.25.6' | |
| - name: Build seid binary in localnode container | |
| env: | |
| DOCKER_PLATFORM: linux/amd64 | |
| run: make build-seid-in-localnode-ci | |
| - name: Push localnode image to GHCR for test jobs | |
| run: | | |
| source .github/scripts/docker-registry-retry.sh | |
| docker tag sei-chain/localnode "${GHCR_LOCALNODE}:${{ github.run_id }}" | |
| push_with_retry "${GHCR_LOCALNODE}:${{ github.run_id }}" | |
| - name: Package CI artifacts | |
| run: tar -czf integration-build.tar.gz build/seid | |
| - name: Upload integration CI artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: integration-ci-artifacts | |
| path: integration-build.tar.gz | |
| retention-days: 1 | |
| integration-tests: | |
| name: Integration Test (${{ matrix.test.name }}) | |
| needs: [ set-matrix, prepare-cluster ] | |
| runs-on: ubuntu-large | |
| timeout-minutes: 30 | |
| permissions: | |
| packages: read | |
| contents: read | |
| env: | |
| JOB_TIMEOUT: 28m | |
| GHCR_LOCALNODE: ghcr.io/sei-protocol/sei-chain-integration-test-localnode | |
| GHCR_RPCNODE: ghcr.io/sei-protocol/sei-chain-integration-test-rpcnode | |
| AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} | |
| AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | |
| DAPP_TESTS_MNEMONIC: ${{ secrets.DAPP_TESTS_MNEMONIC }} | |
| strategy: | |
| # other jobs should run even if one integration test fails | |
| fail-fast: false | |
| # Matrix is resolved by the set-matrix job from | |
| # integration-test-matrix.json. | |
| matrix: | |
| test: ${{ fromJSON(needs.set-matrix.outputs.tests) }} | |
| steps: | |
| # See: https://github.com/actions/checkout/releases/tag/v7.0.0 | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| - name: Reclaim runner disk | |
| run: bash .github/scripts/ci-free-disk.sh | |
| - name: Relocate Docker data-root to /mnt | |
| run: bash .github/scripts/ci-relocate-docker-data-root.sh | |
| - name: Relocate Go caches to /mnt | |
| run: bash .github/scripts/ci-relocate-go-cache.sh | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| - name: Install jq | |
| run: sudo apt-get install -y jq | |
| - name: Set up Go | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.25.6' | |
| - name: Login to Docker Hub | |
| # See: https://github.com/docker/login-action/releases/tag/v4.2.0 | |
| uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee | |
| if: env.DOCKERHUB_USERNAME != '' | |
| env: | |
| DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Login to GitHub Container Registry | |
| # See: https://github.com/docker/login-action/releases/tag/v4.2.0 | |
| uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Download integration CI artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: integration-ci-artifacts | |
| - name: Load prebuilt seid and pull Docker images | |
| run: | | |
| tar -xzf integration-build.tar.gz | |
| # The seid binary is now extracted to build/seid; drop the | |
| # tarball so its copy does not sit on disk for the rest of the job. | |
| rm -f integration-build.tar.gz | |
| source .github/scripts/docker-registry-retry.sh | |
| pull_with_retry "${GHCR_LOCALNODE}:${{ github.run_id }}" | |
| pull_with_retry "${GHCR_RPCNODE}:${{ github.run_id }}" | |
| docker tag "${GHCR_LOCALNODE}:${{ github.run_id }}" sei-chain/localnode | |
| docker tag "${GHCR_RPCNODE}:${{ github.run_id }}" sei-chain/rpcnode | |
| # Drop the redundant run-id-tagged references now that the images are | |
| # retagged as sei-chain/*; keeps a single tag per image. | |
| docker image rm "${GHCR_LOCALNODE}:${{ github.run_id }}" "${GHCR_RPCNODE}:${{ github.run_id }}" || true | |
| - name: Start 4 node docker cluster | |
| run: DOCKER_DETACH=true INVARIANT_CHECK_INTERVAL=10 ${{matrix.test.env}} make docker-cluster-start-ci | |
| - name: Wait for docker cluster to start | |
| run: | | |
| until [ $(cat build/generated/launch.complete |wc -l) = 4 ] | |
| do | |
| sleep 10 | |
| done | |
| sleep 10 | |
| - name: Start rpc node | |
| run: ${{matrix.test.env}} make run-rpc-node-integration-ci & | |
| - name: Verify Sei Chain is running | |
| run: go test -tags yaml_integration -v -timeout 5m ./integration_test/runner/... -run TestStartup | |
| - name: ${{ matrix.test.name }} | |
| run: | | |
| scripts=$(echo '${{ toJson(matrix.test.scripts) }}' | jq -r '.[]') | |
| IFS=$'\n' # change the internal field separator to newline | |
| echo $scripts | |
| for script in $scripts | |
| do | |
| bash -c "${script}" | |
| done | |
| unset IFS # revert the internal field separator back to default | |
| - name: Print node logs on failure | |
| if: ${{ failure() }} | |
| run: | | |
| set -euo pipefail | |
| for c in sei-node-0 sei-node-1 sei-node-2 sei-node-3; do | |
| echo "==================== ${c} (docker logs tail) ====================" | |
| docker logs --tail 200 "${c}" || true | |
| echo "==================== ${c} (seid log file tail) ====================" | |
| # Logs are accessible on host since build/generated is mounted in containers | |
| NODE_ID=${c#sei-node-} | |
| if [ -f "build/generated/logs/seid-${NODE_ID}.log" ]; then | |
| tail -200 "build/generated/logs/seid-${NODE_ID}.log" || true | |
| fi | |
| done | |
| - name: Prepare log artifact name | |
| if: ${{ always() }} | |
| id: log_artifact_meta | |
| run: | | |
| raw="${{ matrix.test.name }}" | |
| safe=$(echo "$raw" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g' | sed -E 's/^-+|-+$//g') | |
| if [ -z "$safe" ]; then | |
| safe="logs" | |
| fi | |
| echo "artifact_name=$safe" >> $GITHUB_OUTPUT | |
| - name: Collect logs directory | |
| if: ${{ always() }} | |
| run: | | |
| LOG_ROOT="artifacts/sei-${{ steps.log_artifact_meta.outputs.artifact_name }}" | |
| mkdir -p "$LOG_ROOT" | |
| if [ -d build/generated/logs ]; then | |
| cp -r build/generated/logs "$LOG_ROOT/" | |
| else | |
| echo "No logs directory found" | |
| fi | |
| - name: Upload logs directory | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: integration-logs-${{ steps.log_artifact_meta.outputs.artifact_name }} | |
| path: artifacts/sei-${{ steps.log_artifact_meta.outputs.artifact_name }} | |
| if-no-files-found: warn | |
| - name: Upload RPC parity test report | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: rpc-parity-report-${{ steps.log_artifact_meta.outputs.artifact_name }} | |
| path: integration_test/rpc_tests/reports/merged | |
| if-no-files-found: ignore | |
| - name: Upload precompile test report | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: precompile-report-${{ steps.log_artifact_meta.outputs.artifact_name }} | |
| path: integration_test/precompile_tests/reports/merged | |
| if-no-files-found: ignore | |
| # Autobahn integration suite (Autobahn Basic) — boots its own cluster via | |
| # TestMain (docker-cluster-start / -stop), so it runs in a separate job | |
| # rather than as a matrix entry that would share the integration-tests | |
| # cluster. | |
| autobahn-integration-tests: | |
| name: Integration Test (Autobahn Basic) | |
| runs-on: ubuntu-large | |
| timeout-minutes: 45 | |
| needs: prepare-cluster | |
| permissions: | |
| packages: read | |
| contents: read | |
| env: | |
| GHCR_LOCALNODE: ghcr.io/sei-protocol/sei-chain-integration-test-localnode | |
| GHCR_RPCNODE: ghcr.io/sei-protocol/sei-chain-integration-test-rpcnode | |
| steps: | |
| # See: https://github.com/actions/checkout/releases/tag/v7.0.0 | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| - name: Reclaim runner disk | |
| run: bash .github/scripts/ci-free-disk.sh | |
| - name: Relocate Docker data-root to /mnt | |
| run: bash .github/scripts/ci-relocate-docker-data-root.sh | |
| - name: Relocate Go caches to /mnt | |
| run: bash .github/scripts/ci-relocate-go-cache.sh | |
| - uses: actions/setup-go@v6 | |
| with: | |
| go-version: '1.25.6' | |
| - name: Install jq | |
| run: sudo apt-get install -y jq | |
| - name: Login to Docker Hub | |
| uses: docker/login-action@v3 | |
| if: env.DOCKERHUB_USERNAME != '' | |
| env: | |
| DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Login to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.repository_owner }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Download integration CI artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: integration-ci-artifacts | |
| - name: Load prebuilt seid and pull Docker images | |
| run: | | |
| tar -xzf integration-build.tar.gz | |
| # The seid binary is now extracted to build/seid; drop the | |
| # tarball so its copy does not sit on disk for the rest of the job. | |
| rm -f integration-build.tar.gz | |
| source .github/scripts/docker-registry-retry.sh | |
| pull_with_retry "${GHCR_LOCALNODE}:${{ github.run_id }}" | |
| pull_with_retry "${GHCR_RPCNODE}:${{ github.run_id }}" | |
| docker tag "${GHCR_LOCALNODE}:${{ github.run_id }}" sei-chain/localnode | |
| docker tag "${GHCR_RPCNODE}:${{ github.run_id }}" sei-chain/rpcnode | |
| # Drop the redundant run-id-tagged references now that the images are | |
| # retagged as sei-chain/*; keeps a single tag per image. | |
| docker image rm "${GHCR_LOCALNODE}:${{ github.run_id }}" "${GHCR_RPCNODE}:${{ github.run_id }}" || true | |
| - name: Run autobahn integration tests | |
| run: make autobahn-integration-test | |
| - name: Print node logs on failure | |
| if: ${{ failure() }} | |
| run: | | |
| set -euo pipefail | |
| for c in sei-node-0 sei-node-1 sei-node-2 sei-node-3 sei-rpc-node; do | |
| echo "==================== ${c} (docker logs tail) ====================" | |
| docker logs --tail 200 "${c}" || true | |
| done | |
| - name: Collect logs directory | |
| if: ${{ always() }} | |
| run: | | |
| mkdir -p artifacts/sei-autobahn-integration | |
| if [ -d build/generated/logs ]; then | |
| cp -r build/generated/logs artifacts/sei-autobahn-integration/ | |
| fi | |
| - name: Upload logs directory | |
| if: ${{ always() }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: integration-logs-autobahn-integration | |
| path: artifacts/sei-autobahn-integration | |
| if-no-files-found: warn | |
| integration-test-check: | |
| name: Integration Test Check | |
| runs-on: ubuntu-latest | |
| needs: [ prepare-cluster, integration-tests, autobahn-integration-tests ] | |
| if: always() | |
| steps: | |
| - name: Verify prepare and test jobs succeeded | |
| run: | | |
| if [[ "${{ needs.prepare-cluster.result }}" != "success" ]]; then | |
| echo "prepare-cluster job did not succeed (${{ needs.prepare-cluster.result }})" | |
| exit 1 | |
| fi | |
| if [[ "${{ needs.integration-tests.result }}" != "success" ]]; then | |
| echo "integration-tests job did not succeed (${{ needs.integration-tests.result }})" | |
| exit 1 | |
| fi | |
| if [[ "${{ needs.autobahn-integration-tests.result }}" != "success" ]]; then | |
| echo "autobahn-integration-tests job did not succeed (${{ needs.autobahn-integration-tests.result }})" | |
| exit 1 | |
| fi | |
| echo "All integration test jobs passed." |