Build and Test #146
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: Build and Test | |
| on: | |
| push: | |
| branches: | |
| - dev | |
| - stage | |
| - main | |
| - release** | |
| pull_request: | |
| types: [opened, synchronize, reopened, ready_for_review] | |
| schedule: | |
| - cron: "0 1 * * *" # 02:00 UTC+1 | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.event_name == 'pull_request' && format('{0}-pr-{1}', github.workflow, github.event.pull_request.number) || format('{0}-push-{1}-{2}', github.workflow, github.ref, github.run_id) }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # Build, lint and test the standalone UI bundle. Independent of the Go | |
| # jobs — the Go binary is UI-blind, so this exists to catch UI build | |
| # failures on PRs and to feed the standalone-UI Docker image build. | |
| # --------------------------------------------------------------------------- | |
| job_ui: | |
| name: UI bundle | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: "20" | |
| cache: "pnpm" | |
| cache-dependency-path: | | |
| sdk/pnpm-lock.yaml | |
| ui/pnpm-lock.yaml | |
| - name: Install and build SDK | |
| working-directory: sdk | |
| run: pnpm install --frozen-lockfile && pnpm build | |
| - name: Install UI dependencies | |
| working-directory: ui | |
| run: pnpm install --frozen-lockfile | |
| - name: Type-check & lint | |
| working-directory: ui | |
| run: pnpm run lint | |
| - name: Run UI tests | |
| working-directory: ui | |
| run: pnpm run test | |
| - name: Build UI | |
| working-directory: ui | |
| run: pnpm run build | |
| env: | |
| VITE_BUILD_VERSION: ${{ github.sha }} | |
| # --------------------------------------------------------------------------- | |
| # Static analysis and formatting checks | |
| # --------------------------------------------------------------------------- | |
| job_go_checks: | |
| name: Go Checks | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Run go mod tidy | |
| run: | | |
| go mod tidy | |
| if [[ $(git status --porcelain) ]]; then | |
| git diff | |
| echo | |
| echo "go mod tidy made changes — run 'go mod tidy' and commit the result" | |
| exit 1 | |
| fi | |
| - name: Run go vet | |
| run: go vet ./... | |
| - name: Run gofumpt | |
| run: | | |
| go install mvdan.cc/gofumpt@latest | |
| diff=$(gofumpt -l .) | |
| if [[ -n "$diff" ]]; then | |
| echo "::error::gofumpt found unformatted files:" | |
| echo "$diff" | |
| exit 1 | |
| fi | |
| - name: Run golangci-lint | |
| uses: golangci/golangci-lint-action@v8 | |
| with: | |
| version: v2.5 | |
| # --------------------------------------------------------------------------- | |
| # Solidity contract tests | |
| # --------------------------------------------------------------------------- | |
| job_forge_test: | |
| name: Forge Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Install Foundry | |
| uses: foundry-rs/foundry-toolchain@v1 | |
| - name: Run forge build | |
| working-directory: solidity | |
| run: forge build | |
| - name: Run forge test | |
| working-directory: solidity | |
| run: forge test -vvv | |
| # --------------------------------------------------------------------------- | |
| # Go unit tests (no chain, no proofs — fast path). Runs on self-hosted | |
| # to match davinci-node's pattern: Go tests in this project exercise | |
| # Groth16 trusted-setup code paths whose performance on GitHub-hosted | |
| # runners is 5–10× slower than on our dedicated boxes. | |
| # --------------------------------------------------------------------------- | |
| job_go_unit_test: | |
| name: Go Unit Tests | |
| runs-on: [self-hosted] | |
| env: | |
| LOG_LEVEL: debug | |
| RUN_INTEGRATION_TESTS: "false" | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Build all binaries | |
| run: go build ./cmd/... | |
| - name: Run unit tests | |
| run: | | |
| go test -v \ | |
| $(go list ./... | grep -v github.com/vocdoni/davinci-dkg/tests) \ | |
| -timeout=30m \ | |
| -failfast | |
| # --------------------------------------------------------------------------- | |
| # Go integration tests (Anvil + Docker Compose deployer). Self-hosted: | |
| # the pre-step regenerates all six Groth16 circuits via a trusted setup | |
| # (MaxN=16 contribution circuit alone ≈ 90 s), so a cold GitHub-hosted | |
| # runner would easily triple the job duration. | |
| # --------------------------------------------------------------------------- | |
| job_go_integration_test: | |
| name: Go Integration Tests | |
| runs-on: [self-hosted] | |
| # Serialize across the whole repo on the shared self-hosted runner. | |
| # Prevents two concurrent jobs (from different PRs / branches) from | |
| # racing through `foundry-rs/foundry-toolchain@v1`: foundryup aborts | |
| # with "'anvil' is currently running" when another job's in-flight | |
| # anvil process (host- or container-visible) is still alive. | |
| # cancel-in-progress must stay false so a queued job waits instead of | |
| # cancelling the one that got there first. | |
| concurrency: | |
| group: self-hosted-integration | |
| cancel-in-progress: false | |
| env: | |
| LOG_LEVEL: debug | |
| RUN_INTEGRATION_TESTS: "true" | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - uses: actions/setup-go@v5 | |
| with: | |
| go-version-file: go.mod | |
| - name: Install Foundry (for deployer container build) | |
| uses: foundry-rs/foundry-toolchain@v1 | |
| # Groth16 trusted setup is randomized: every invocation of | |
| # `circuit-compile` produces a fresh proving key and verifying key | |
| # with a new pair of hashes. The committed config/circuit_artifacts.go | |
| # and solidity/src/verifiers/*_vkey.sol files are snapshots of one | |
| # past setup run whose artifacts no CI runner has on disk. If we just | |
| # run the test with the committed hashes, the Go prover falls back to | |
| # a local setup whose vk does not match the deployed Solidity | |
| # verifier, and every submitContribution reverts with | |
| # ProofInvalid() (selector 0x7fcdd1f4). | |
| # | |
| # The fix is to regenerate *both* halves together in the same job: | |
| # circuits-compile writes pk/vk to ~/.davinci/artifacts and rewrites | |
| # solidity/src/verifiers/*_vkey.sol; circuits-update-hashes patches | |
| # config/circuit_artifacts.go and the PROVING_KEY_HASH constants in | |
| # the verifier wrappers; solidity-build recompiles the contracts with | |
| # the fresh vkey. The integration test then sees a self-consistent | |
| # triple (Go pk ↔ pinned hashes ↔ Solidity verifier vk) all coming | |
| # from the same trusted setup run. | |
| # | |
| # Cost: ~3–5 minutes per run (dominated by contribution + finalize | |
| # trusted setup at MaxN=16). Caching is not worthwhile — Setup is | |
| # non-deterministic so each run's output is fresh regardless. | |
| - name: Regenerate circuit artifacts and Solidity verifiers | |
| run: make circuits-compile circuits-update-hashes solidity-build | |
| - name: Run integration tests | |
| if: github.event.pull_request.draft != true | |
| run: | | |
| go test -v ./tests/... \ | |
| -timeout=2h \ | |
| -failfast \ | |
| -count=1 | |
| # ── TypeScript SDK integration tests ───────────────────────────────── | |
| # Runs after Go tests so that: | |
| # • Circuit artifacts are already compiled in ~/.davinci/artifacts | |
| # (the sdk-test-fixture binary uses them to generate ZK proofs). | |
| # • The Go binary in cmd/sdk-test-fixture is buildable without a | |
| # separate circuit-compile step. | |
| # The SDK tests start their own isolated Docker Compose stack (fresh | |
| # Anvil + deployer) so they do not interfere with the Go test stack. | |
| - name: Set up pnpm | |
| if: github.event.pull_request.draft != true | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| - name: Set up Node.js | |
| if: github.event.pull_request.draft != true | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: "20" | |
| cache: "pnpm" | |
| cache-dependency-path: sdk/pnpm-lock.yaml | |
| - name: Install SDK dependencies | |
| if: github.event.pull_request.draft != true | |
| working-directory: sdk | |
| run: pnpm install --frozen-lockfile | |
| - name: Run SDK integration tests | |
| if: github.event.pull_request.draft != true | |
| working-directory: sdk | |
| run: pnpm test:integration | |
| env: | |
| RUN_INTEGRATION_TESTS: "true" | |
| # --------------------------------------------------------------------------- | |
| # Docker image build (calls reusable workflow). Only runs after all tests | |
| # are green, and only pushes on branch pushes (not PRs). | |
| # --------------------------------------------------------------------------- | |
| call-docker-build: | |
| name: Docker | |
| needs: | |
| - job_go_checks | |
| - job_forge_test | |
| - job_go_unit_test | |
| - job_go_integration_test | |
| permissions: | |
| contents: read | |
| packages: write | |
| if: github.event.pull_request.draft != true | |
| uses: ./.github/workflows/docker-build.yml | |
| secrets: inherit | |
| with: | |
| image-tag: ${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || github.ref_name }} | |
| push: ${{ github.event_name == 'push' }} | |
| # --------------------------------------------------------------------------- | |
| # Standalone UI image build. Independent of the node image — gated only on | |
| # the UI bundle building cleanly, since the runtime image bundles its own | |
| # nginx and doesn't share Go test infrastructure. | |
| # --------------------------------------------------------------------------- | |
| call-ui-docker-build: | |
| name: UI Docker | |
| needs: | |
| - job_ui | |
| permissions: | |
| contents: read | |
| packages: write | |
| if: github.event.pull_request.draft != true | |
| uses: ./.github/workflows/ui-docker-build.yml | |
| secrets: inherit | |
| with: | |
| image-tag: ${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || github.ref_name }} | |
| push: ${{ github.event_name == 'push' }} |