GitHub Identity #73
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
| # GitHub Identity Attestation | |
| # | |
| # PURPOSE: Prove you control a GitHub account by running a workflow. | |
| # | |
| # ARTIFACT: JSON containing your GitHub username, recipient address, and target faucet, | |
| # plus a ZK proof ready for on-chain submission. | |
| # | |
| # TRUST MODEL: | |
| # - The workflow runs in YOUR repo (you triggered it) | |
| # - Sigstore signs: "repo X at commit Y produced artifact Z" | |
| # - Verifier trusts: this workflow correctly outputs github.actor | |
| # | |
| # HOW TO CLAIM: | |
| # 1. Run this workflow with your ETH address | |
| # 2. Download the identity-proof artifact | |
| # 3. Open issue at main repo with title "[CLAIM]" and paste claim.json | |
| # | |
| # NO SECRETS NEEDED - just fork and run. | |
| name: GitHub Identity | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| recipient_address: | |
| description: 'ETH address to receive funds (0x...)' | |
| required: true | |
| faucet_address: | |
| description: 'Faucet contract address (Base Sepolia)' | |
| required: true | |
| default: '0x72cd70d28284dD215257f73e1C5aD8e28847215B' | |
| generate_proof: | |
| description: 'Generate ZK proof (takes ~5 min)' | |
| required: true | |
| type: boolean | |
| default: true | |
| permissions: | |
| id-token: write | |
| contents: read | |
| attestations: write | |
| jobs: | |
| attest: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Validate inputs | |
| run: | | |
| if ! echo "${{ inputs.recipient_address }}" | grep -qE '^0x[a-fA-F0-9]{40}$'; then | |
| echo "Invalid recipient address format" | |
| exit 1 | |
| fi | |
| if ! echo "${{ inputs.faucet_address }}" | grep -qE '^0x[a-fA-F0-9]{40}$'; then | |
| echo "Invalid faucet address format" | |
| exit 1 | |
| fi | |
| - name: Generate identity certificate | |
| run: | | |
| mkdir -p proof | |
| RECIPIENT=$(echo "${{ inputs.recipient_address }}" | tr '[:upper:]' '[:lower:]') | |
| FAUCET=$(echo "${{ inputs.faucet_address }}" | tr '[:upper:]' '[:lower:]') | |
| cat > proof/certificate.json << EOF | |
| { | |
| "type": "github-identity", | |
| "github_actor": "${{ github.actor }}", | |
| "github_repository": "${{ github.repository }}", | |
| "recipient_address": "$RECIPIENT", | |
| "faucet_address": "$FAUCET", | |
| "chain_id": 84532, | |
| "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)", | |
| "workflow_run": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| } | |
| EOF | |
| echo "Certificate:" && cat proof/certificate.json | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: identity-proof | |
| path: proof/ | |
| - name: Attest | |
| id: attest | |
| uses: actions/attest-build-provenance@v2 | |
| with: | |
| subject-path: proof/certificate.json | |
| - name: Copy attestation bundle | |
| if: ${{ inputs.generate_proof }} | |
| run: cp ${{ steps.attest.outputs.bundle-path }} proof/bundle.json | |
| - name: Generate ZK proof | |
| if: ${{ inputs.generate_proof }} | |
| run: | | |
| PROVER_DIGEST=$(python3 -c "import json; print(json.load(open('VERSIONS.json'))['reference']['prover_digest']['value'])") | |
| EXPECTED_VK_HASH=$(python3 -c "import json; print(json.load(open('VERSIONS.json'))['requirements']['vk_hash']['value'])") | |
| REGISTRY="${{ vars.PROVER_REGISTRY || 'ghcr.io/amiller/zkproof' }}" | |
| echo "Using prover: ${REGISTRY}@${PROVER_DIGEST}" | |
| docker run --rm -e EXPECTED_VK_HASH="${EXPECTED_VK_HASH}" \ | |
| -v ${{ github.workspace }}/proof:/work \ | |
| "${REGISTRY}@${PROVER_DIGEST}" generate /work/bundle.json /work | |
| - name: Update artifact with proof | |
| if: ${{ inputs.generate_proof }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: identity-proof | |
| path: proof/ | |
| overwrite: true |