GitHub Action Integration
Automate evidence collection in CI/CD pipelines with the evidence GitHub Action.
Quick Start
Add evidence collection to any GitHub repository:
# .github/workflows/evidence.yml
name: evidence collection
on:
schedule:
- cron: '0 0 1 * *' # Monthly on the 1st
workflow_dispatch: # Manual trigger
jobs:
collect:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: evidence-sdk/action@v1
with:
command: collect
upload: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EVIDENCE_SIGNING_KEY: ${{ secrets.EVIDENCE_SIGNING_KEY }}
EVIDENCE_API_KEY: ${{ secrets.EVIDENCE_API_KEY }}What this does:
- Runs monthly (1st of each month at midnight UTC)
- Can also be triggered manually via GitHub UI
- Collects evidence using configuration in repository
- Automatically uploads bundle to evidence platform
- Uses GitHub-provided
GITHUB_TOKENfor authentication
Installation
Step 1: Add Configuration File
Create evidence.yaml in your repository root:
framework: soc2_type1
controls:
- CC6.1
- CC6.6
- CC7.2
sources:
github:
mode: token
token_env: GITHUB_TOKEN
org: your-org
repos:
- your-org/backend
- your-org/frontend
bundle:
signing:
private_key_env: EVIDENCE_SIGNING_KEYStep 2: Generate Signing Key
Generate an Ed25519 signing key locally:
# Install evidence CLI
npm install -g @evidence-oss/cli
# Generate key pair
evidence init --generate-keys
# Copy private key (base64-encoded for GitHub Secrets)
cat ~/.evidence/keys/private.pem | base64Step 3: Add Repository Secrets
Go to Repository Settings → Secrets and variables → Actions:
Add these secrets:
| Secret Name | Value | Source |
|---|---|---|
EVIDENCE_SIGNING_KEY | Base64-encoded private key | Output from Step 2 |
EVIDENCE_API_KEY | API key for evidence platform | evidence platform dashboard |
Note: GITHUB_TOKEN is provided automatically by GitHub Actions. No need to add it.
Step 4: Create Workflow File
Create .github/workflows/evidence.yml:
name: evidence collection
on:
schedule:
- cron: '0 0 1 * *' # Monthly
workflow_dispatch:
jobs:
collect:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: evidence-sdk/action@v1
with:
command: collect
upload: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EVIDENCE_SIGNING_KEY: ${{ secrets.EVIDENCE_SIGNING_KEY }}
EVIDENCE_API_KEY: ${{ secrets.EVIDENCE_API_KEY }}Step 5: Test Workflow
Trigger manually to test:
- Go to repository → Actions tab
- Select "evidence collection" workflow
- Click "Run workflow" → "Run workflow"
- Monitor execution in Actions tab
Expected output:
✓ Configuration valid
✓ GitHub connection successful
✓ Collecting evidence...
✓ Bundle created
✓ Bundle verified
✓ Uploaded to evidence platformTrigger Patterns
Scheduled Collection
Monthly (SOC 2 Type I):
on:
schedule:
- cron: '0 0 1 * *' # 1st of month, midnight UTCWeekly (Frequent monitoring):
on:
schedule:
- cron: '0 0 * * 1' # Every Monday, midnight UTCDaily (Dev/testing):
on:
schedule:
- cron: '0 0 * * *' # Every day, midnight UTCCustom schedule:
on:
schedule:
# Every 1st and 15th at 3:00 AM UTC
- cron: '0 3 1,15 * *'Manual Triggers
on:
workflow_dispatch: # Enables "Run workflow" button in Actions tabWith inputs:
on:
workflow_dispatch:
inputs:
upload:
description: 'Upload bundle to platform'
required: false
default: 'true'
type: boolean
jobs:
collect:
steps:
- uses: evidence-sdk/action@v1
with:
upload: ${{ inputs.upload }}Event-Triggered Collection
On release:
on:
release:
types: [published]On push to main:
on:
push:
branches: [main]On PR merge:
on:
pull_request:
types: [closed]
branches: [main]Action Inputs
Complete reference for evidence-sdk/action@v1:
| Input | Type | Required | Default | Description |
|---|---|---|---|---|
command | string | Yes | - | Command to run: collect, verify, upload |
config-path | string | No | ./evidence.yaml | Path to configuration file |
output-path | string | No | ./evidence-bundles | Output directory for bundles |
bundle-path | string | No | - | Path to bundle (for verify/upload) |
upload | boolean | No | false | Auto-upload after collect |
cli-version | string | No | latest | evidence CLI version to use |
Examples
Collect only (no upload):
- uses: evidence-sdk/action@v1
with:
command: collect
upload: falseCustom config path:
- uses: evidence-sdk/action@v1
with:
command: collect
config-path: ./config/evidence.production.yamlSpecific CLI version:
- uses: evidence-sdk/action@v1
with:
command: collect
cli-version: '0.1.0'Action Outputs
Outputs available via steps.<step-id>.outputs:
| Output | Type | Description |
|---|---|---|
bundle-path | string | Path to created bundle |
bundle-id | string | Bundle ID from manifest |
upload-url | string | URL of uploaded bundle (if upload: true) |
verified | boolean | Bundle verification status |
Example Usage
jobs:
collect:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- id: collect-evidence
uses: evidence-sdk/action@v1
with:
command: collect
upload: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EVIDENCE_SIGNING_KEY: ${{ secrets.EVIDENCE_SIGNING_KEY }}
- name: Print bundle info
run: |
echo "Bundle created: ${{ steps.collect-evidence.outputs.bundle-path }}"
echo "Bundle ID: ${{ steps.collect-evidence.outputs.bundle-id }}"
echo "Upload URL: ${{ steps.collect-evidence.outputs.upload-url }}"Multi-Source Configuration
Collect from multiple sources (GitHub, AWS, Google Workspace):
name: evidence collection (multi-source)
on:
schedule:
- cron: '0 0 1 * *'
jobs:
collect:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: evidence-sdk/action@v1
with:
command: collect
upload: true
env:
# GitHub
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# AWS
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: us-east-1
# Google Workspace
GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
# evidence Platform
EVIDENCE_SIGNING_KEY: ${{ secrets.EVIDENCE_SIGNING_KEY }}
EVIDENCE_API_KEY: ${{ secrets.EVIDENCE_API_KEY }}Configuration file:
# evidence.yaml
framework: soc2_type1
controls: [CC6.1, CC6.6, CC7.2]
sources:
github:
mode: token
token_env: GITHUB_TOKEN
org: acme
repos: '*'
aws:
mode: env
region: us-east-1
log_groups: '*'
google_workspace:
mode: service_account
credentials_env: GOOGLE_APPLICATION_CREDENTIALS
customer_id: C0xxxxxxx
admin_email: admin@acme.com
bundle:
signing:
private_key_env: EVIDENCE_SIGNING_KEYAdvanced Workflows
Collect → Verify → Upload
Separate steps for more control:
jobs:
collect-and-verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Step 1: Collect
- id: collect
uses: evidence-sdk/action@v1
with:
command: collect
upload: false # Don't upload yet
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EVIDENCE_SIGNING_KEY: ${{ secrets.EVIDENCE_SIGNING_KEY }}
# Step 2: Verify
- uses: evidence-sdk/action@v1
with:
command: verify
bundle-path: ${{ steps.collect.outputs.bundle-path }}
# Step 3: Upload (only if verified)
- uses: evidence-sdk/action@v1
with:
command: upload
bundle-path: ${{ steps.collect.outputs.bundle-path }}
env:
EVIDENCE_API_KEY: ${{ secrets.EVIDENCE_API_KEY }}Store Bundle as Artifact
Save bundle for manual review:
jobs:
collect:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- id: collect
uses: evidence-sdk/action@v1
with:
command: collect
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EVIDENCE_SIGNING_KEY: ${{ secrets.EVIDENCE_SIGNING_KEY }}
# Upload as GitHub Actions artifact
- uses: actions/upload-artifact@v4
with:
name: evidence-bundle
path: ${{ steps.collect.outputs.bundle-path }}
retention-days: 90Download later:
- Go to workflow run → Artifacts
- Download
evidence-bundle - Extract and inspect locally
Notify on Failure
Send notifications if collection fails:
jobs:
collect:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: evidence-sdk/action@v1
id: collect-evidence
with:
command: collect
upload: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EVIDENCE_SIGNING_KEY: ${{ secrets.EVIDENCE_SIGNING_KEY }}
# Notify on failure
- name: Notify Slack on failure
if: failure()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"text": "evidence collection failed for ${{ github.repository }}",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "evidence collection failed\n*Repository:* ${{ github.repository }}\n*Workflow:* ${{ github.workflow }}\n*Run:* ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
}
}
]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}Matrix Strategy (Multiple Orgs)
Collect evidence for multiple organizations in parallel:
jobs:
collect:
runs-on: ubuntu-latest
strategy:
matrix:
org:
- name: acme-corp
config: evidence.acme.yaml
- name: acme-labs
config: evidence.labs.yaml
steps:
- uses: actions/checkout@v4
- uses: evidence-sdk/action@v1
with:
command: collect
config-path: ${{ matrix.org.config }}
upload: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EVIDENCE_SIGNING_KEY: ${{ secrets[format('{0}_SIGNING_KEY', matrix.org.name)] }}
EVIDENCE_API_KEY: ${{ secrets.EVIDENCE_API_KEY }}Security Best Practices
1. Use Repository Secrets
Never hardcode credentials:
# ❌ BAD
env:
GITHUB_TOKEN: ghp_hardcoded_token
# ✅ GOOD
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}2. Limit Workflow Permissions
Restrict what workflows can do:
permissions:
contents: read # Read-only access to repository
actions: read # Read workflow files3. Pin Action Versions
Use specific versions, not @main:
# ❌ BAD - uses latest, could break
- uses: evidence-sdk/action@main
# ✅ GOOD - pinned version
- uses: evidence-sdk/action@v1.0.0
# ✅ ACCEPTABLE - major version
- uses: evidence-sdk/action@v14. Separate Keys Per Environment
# Production workflow
env:
EVIDENCE_SIGNING_KEY: ${{ secrets.PROD_SIGNING_KEY }}
# Staging workflow
env:
EVIDENCE_SIGNING_KEY: ${{ secrets.STAGING_SIGNING_KEY }}5. Use Environment Protection Rules
Set up environment-specific secrets:
- Go to Repository Settings → Environments
- Create
productionenvironment - Add protection rules (required reviewers, wait timer)
- Add environment-specific secrets
jobs:
collect:
runs-on: ubuntu-latest
environment: production # Requires approval
steps:
- uses: evidence-sdk/action@v1
env:
EVIDENCE_API_KEY: ${{ secrets.EVIDENCE_API_KEY }}Troubleshooting
Collection Fails with "Invalid Token"
Symptom:
✗ GitHub connection failed: Bad credentialsCauses:
GITHUB_TOKENsecret not set- Token expired or revoked
- Insufficient token permissions
Solution:
- Verify secret exists: Repository Settings → Secrets
- Check GitHub Actions can access secret
- Verify token has required scopes (
repo:read,read:org)
Bundle Verification Fails
Symptom:
✗ Signature verification failedCauses:
EVIDENCE_SIGNING_KEYmalformed (not base64)- Different key used for signing vs. verification
- Key rotation without updating secret
Solution:
- Regenerate key:
evidence init --generate-keys - Base64 encode:
cat private.pem | base64 - Update secret in repository settings
- Verify: Re-run workflow
Workflow Not Triggering on Schedule
Symptom: Workflow doesn't run at scheduled time
Causes:
- Repository inactive (GitHub disables scheduled workflows after 60 days)
- Workflow file syntax error
- Schedule timezone (UTC only)
Solution:
- Check workflow syntax: Actions tab → workflow → "View workflow file"
- Test manually: "Run workflow" button
- Verify cron syntax: Use crontab.guru
- Re-enable scheduled workflows if repository was inactive
Next Steps
Complete Examples See full workflow examples for different scenarios.
Configure Multi-Source Collection Add AWS and Google Workspace to your evidence collection.
Monitor Compliance Over Time View continuous compliance timeline in evidence platform.