Antithesis #5
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: "Antithesis" | |
| env: | |
| TESTNET: testnets/cardano_node_governance | |
| DURATION: 2 | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| # run once a week | |
| - cron: '5 1 * * 1' | |
| jobs: | |
| run-cardano-node-governance: | |
| runs-on: ubuntu-latest | |
| env: | |
| MOOG_GITHUB_PAT: ${{ secrets.MOOG_GITHUB_PAT }} | |
| MOOG_WALLET_FILE: wallet.json | |
| MOOG_WALLET_PASSPHRASE: ${{ secrets.MOOG_WALLET_PASSPHRASE }} | |
| MOOG_SSH_PASSWORD: ${{ secrets.MOOG_WALLET_PASSPHRASE }} | |
| MOOG_MPFS_HOST: ${{ vars.MOOG_MPFS_HOST }} | |
| MOOG_TOKEN_ID: ${{ vars.MOOG_TOKEN_ID }} | |
| MOOG_PLATFORM: github | |
| MOOG_REQUESTER: cfhal | |
| timeout-minutes: 200 | |
| # contents:write to push the branch pinning the freshly fetched | |
| # cardano-node image (the image push itself uses GHCR_PAT, | |
| # not this token). | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Install Nix | |
| uses: cachix/install-nix-action@v31 | |
| with: | |
| extra_nix_config: | | |
| extra-trusted-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= | |
| extra-substituters = https://cache.iog.io/ | |
| # Pushes to ghcr.io/saratomaz/... (same namespace as gov-cli / | |
| # gov-configurator), matching the account registered with moog. That | |
| # namespace isn't owned by this repo, so the auto-generated | |
| # GITHUB_TOKEN (scoped to this org repo) can't write to it - needs a | |
| # personal PAT with write:packages instead (GHCR_PAT, separate from | |
| # MOOG_GITHUB_PAT which moog itself uses). | |
| - name: Log in to GitHub Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: saratomaz | |
| password: ${{ secrets.GHCR_PAT }} | |
| # cardano-node isn't built here: Hydra (IntersectMBO's own CI) builds | |
| # every master commit and caches it at cache.iog.io. `--max-jobs 0` | |
| # forbids a local build, so this only succeeds if Hydra has already | |
| # cached the current tip - which is normally the case within minutes | |
| # of a merge, but can occasionally lag on a very fresh commit. On | |
| # failure we fall back to whatever digest is already pinned in | |
| # docker-compose.yaml instead of failing the run. | |
| - name: Fetch cardano-node master from Hydra cache | |
| id: node-image | |
| continue-on-error: true | |
| run: | | |
| set -euo pipefail | |
| LOCKED_URL=$(nix flake metadata github:IntersectMBO/cardano-node/master --json | jq -r .url) | |
| echo "building: $LOCKED_URL" | |
| nix build --print-out-paths --builders "" --max-jobs 0 \ | |
| --out-link ./cardano-node-image \ | |
| "${LOCKED_URL}#packages.x86_64-linux.dockerImage/node" | |
| nix profile install nixpkgs#skopeo | |
| DEST="ghcr.io/saratomaz/cardano-node-tests-antithesis/cardano-node-master:${GITHUB_RUN_ID}" | |
| skopeo copy "docker-archive:./cardano-node-image" "docker://${DEST}" | |
| DIGEST=$(skopeo inspect --no-tags "docker://${DEST}" | jq -r .Digest) | |
| echo "image=ghcr.io/saratomaz/cardano-node-tests-antithesis/cardano-node-master@${DIGEST}" >> "$GITHUB_OUTPUT" | |
| - name: Pin fetched image into docker-compose.yaml | |
| id: pin | |
| if: steps.node-image.outcome == 'success' | |
| env: | |
| NEW_IMAGE: ${{ steps.node-image.outputs.image }} | |
| run: | | |
| set -euo pipefail | |
| sed -i "s|ghcr.io/intersectmbo/cardano-node@sha256:[0-9a-f]*|${NEW_IMAGE}|g" \ | |
| "$TESTNET/docker-compose.yaml" | |
| if git diff --quiet; then | |
| echo "cardano-node master image unchanged, nothing to pin" | |
| exit 0 | |
| fi | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| BRANCH="antithesis/governance-master-${GITHUB_RUN_ID}" | |
| git checkout -b "$BRANCH" | |
| git add "$TESTNET/docker-compose.yaml" | |
| git commit -m "Pin cardano-node master (Hydra build, run ${GITHUB_RUN_ID}) for Antithesis" | |
| git push origin "$BRANCH" | |
| echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" | |
| - name: Install moog | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| # Pinned, NOT latest: v2.0.0+ added a client-side precondition that | |
| # probes GET /status on the MPFS host as part of an in-progress | |
| # "mpfs-v2" migration (moog#96, moog#101 - still open). Production | |
| # mpfs.plutimus.com still only serves the legacy API, so /status | |
| # 404s and every moog command fails immediately. v0.5.1.5 is the | |
| # last release before that migration work and works against the | |
| # current production server. Bump this once moog#101 lands and a | |
| # new release is confirmed compatible with mpfs.plutimus.com. | |
| # | |
| # The portable Linux requester binary is the statically-linked musl | |
| # tarball (the old `*-linux64.tar.gz` asset was dropped at the 0.5.x | |
| # packaging change). | |
| TAG=v0.5.1.5 | |
| echo "moog release: $TAG" | |
| gh release download "$TAG" -R cardano-foundation/moog \ | |
| -p 'moog-*-x86_64-linux-musl.tar.gz' --clobber | |
| TARBALL=$(ls moog-*-x86_64-linux-musl.tar.gz | grep -vE 'moog-(agent|oracle)-' | head -1) | |
| echo "using $TARBALL" | |
| tar xzf "$TARBALL" | |
| sudo install -m 0755 moog /usr/local/bin/moog | |
| moog --version | |
| - name: Configure moog wallet | |
| run: printf '%s' "${{ secrets.MOOG_REQUESTER_WALLET }}" | base64 --decode > "$MOOG_WALLET_FILE" | |
| - name: Submit test | |
| id: request | |
| run: | | |
| set -euo pipefail | |
| COMMIT="${{ steps.pin.outputs.sha || github.sha }}" | |
| # Captured (instead of piped straight into jq) so the raw response | |
| # is visible in the log if it's ever shaped unexpectedly. | |
| FACTS=$(moog facts test-runs --whose "$MOOG_REQUESTER") | |
| echo "$FACTS" | |
| TRY=$(echo "$FACTS" | jq \ | |
| --arg commit "$COMMIT" \ | |
| --arg directory "$TESTNET" \ | |
| --arg platform "$MOOG_PLATFORM" \ | |
| --arg repository "$GITHUB_REPOSITORY" \ | |
| --arg requester "$MOOG_REQUESTER" \ | |
| '(if type == "array" then . else [.] end) | |
| | map(select( | |
| type == "object" | |
| and .key.type == "test-run" | |
| and .key.commitId == $commit | |
| and .key.directory == $directory | |
| and .key.platform == $platform | |
| and ((.key.repository.organization + "/" + .key.repository.repo) == $repository) | |
| and .key.requester == $requester | |
| )) | length') | |
| TRY=$((TRY + 1)) # start with try=1 | |
| echo "TRY=$TRY for $TESTNET" | |
| RESULT=$(moog requester create-test -d "$TESTNET" \ | |
| -c "$COMMIT" \ | |
| -r "$GITHUB_REPOSITORY" \ | |
| --try "$TRY" \ | |
| -t "$DURATION") | |
| echo "$RESULT" | |
| # Passing -e and -r in separate jq calls ensures we both unwrap | |
| # the string quotes and fail if the json isn't as expected. | |
| ID=$(echo "$RESULT" | jq -e .value.testRunId | jq -r .) | |
| TXID=$(echo "$RESULT" | jq -e .txHash | jq -r .) | |
| echo "id=$ID" >> "$GITHUB_OUTPUT" | |
| echo "txHash=$TXID" >> "$GITHUB_OUTPUT" | |
| - name: Wait for results | |
| run: timeout $(((DURATION + 1) * 3600)) ./scripts/wait-for-test.sh "${{ steps.request.outputs.id }}" |