Skip to content

Antithesis

Antithesis #5

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 }}"