Integrating GitHub Actions
Wire Verdifax into a CI workflow so every model evaluation, every staging deployment, and every release artifact ships with a sealed manifest hash attached.
Pattern
The Verdifax orchestrator is reachable from the workflow runner over the network. You publish your manifest hash as a workflow output, attach it to a release, or post it to your model registry.
Example workflow
name: Attest model release
on:
release:
types: [created]
jobs:
attest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install verdifax
run: pip install verdifax
- name: Run model evaluation
id: eval
run: |
python eval.py > /tmp/eval-output.txt
echo "output_path=/tmp/eval-output.txt" >> $GITHUB_OUTPUT
- name: Attest the evaluation
id: attest
env:
VERDIFAX_API_URL: ${{ secrets.VERDIFAX_API_URL }}
VERDIFAX_API_KEY: ${{ secrets.VERDIFAX_API_KEY }}
run: |
HASH=$(python -c "
import verdifax
with open('${{ steps.eval.outputs.output_path }}') as f:
receipt = verdifax.attest(
payload=f.read(),
program_id='${{ vars.VERDIFAX_PROGRAM_ID }}',
route_id='ci-release',
registry_record_hash='${{ vars.VERDIFAX_REGISTRY_RECORD_HASH }}',
)
print(receipt.manifest_hash)
")
echo "manifest_hash=$HASH" >> $GITHUB_OUTPUT
echo "::notice title=Verdifax seal::$HASH"
- name: Attach hash to release
uses: actions/github-script@v7
with:
script: |
github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: context.payload.release.id,
body: context.payload.release.body +
"\n\n**Verdifax seal:** `${{ steps.attest.outputs.manifest_hash }}`"
});
Secrets and vars to set
| Where | Name | What |
|---|---|---|
| Repository secret | VERDIFAX_API_URL | URL of your orchestrator |
| Repository secret | VERDIFAX_API_KEY | API key issued for CI use |
| Repository var | VERDIFAX_PROGRAM_ID | 64-char hex program identifier |
| Repository var | VERDIFAX_REGISTRY_RECORD_HASH | 64-char hex registry record hash |
What you get
Every release ships with a manifest hash glued into its description. Anyone holding the run's audit bundle can check it with the open-source verifier, which recomputes every section hash from the bundle's own fields and confirms every section is bound to that manifest hash, showing the sealed evaluation result was not edited after the fact. Re-running the same evaluation produces a new run with a different hash, because each run seals its own admission clock and per-run nonce.
