Guide

Automate in CI/CD

Generate and sign packs automatically in GitHub Actions, GitLab CI, or any CI system.

GitHub Actions

Build and sign a pack

.github/workflows/evidence.yml
name: Generate Evidence Pack

on:
  schedule:
    - cron: '0 0 * * 0'  # Weekly
  workflow_dispatch:

permissions:
  id-token: write      # Required for Sigstore
  contents: read

jobs:
  generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install epack
        run: go install -tags components github.com/locktivity/epack/cmd/epack@v0.1.29

      - name: Build pack
        run: epack build evidence.pack ./artifacts/* --stream ${{ github.repository }}

      - name: Sign pack
        run: epack sign evidence.pack

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: evidence-pack
          path: evidence.pack

Run collectors

Use epack collect to run configured collectors:

.github/workflows/evidence.yml
name: Collect Evidence

on:
  schedule:
    - cron: '0 0 * * 0'
  workflow_dispatch:

permissions:
  id-token: write
  contents: read

jobs:
  collect:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install epack (with collectors)
        run: go install -tags components github.com/locktivity/epack/cmd/epack@v0.1.29

      - name: Collect and build
        run: epack collect --frozen
        env:
          GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}

      - name: Sign pack
        run: epack sign packs/*.pack

      - uses: actions/upload-artifact@v4
        with:
          name: evidence-pack
          path: packs/*.pack
Why --frozen? Fails the build if the lockfile doesn't match. This prevents supply chain attacks from modified collector images.

GitLab CI

.gitlab-ci.yml
evidence-pack:
  image: golang:1.21
  id_tokens:
    SIGSTORE_ID_TOKEN:
      aud: sigstore
  script:
    - go install -tags components github.com/locktivity/epack/cmd/epack@v0.1.29
    - epack build evidence.pack ./artifacts/* --stream $CI_PROJECT_PATH
    - EPACK_OIDC_TOKEN=$SIGSTORE_ID_TOKEN epack sign evidence.pack
  artifacts:
    paths:
      - evidence.pack
  rules:
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
    - if: '$CI_PIPELINE_SOURCE == "web"'

Push to a remote

After signing, push to a configured remote:

# Add to your workflow after signing
- name: Push to remote
  run: |
    epack push myremote packs/*.pack -y \
      --label automated \
      --label "build-${{ github.run_number }}"

Verify packs in CI

Verify vendor packs as part of your supply chain checks:

.github/workflows/verify-vendor.yml
name: Verify Vendor

on:
  workflow_dispatch:
    inputs:
      pack_url:
        description: 'URL to vendor pack'
        required: true

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - name: Download pack
        run: curl -L "${{ inputs.pack_url }}" -o vendor.pack

      - name: Install epack
        run: go install -tags components github.com/locktivity/epack/cmd/epack@v0.1.29

      - name: Verify signature
        run: |
          epack verify vendor.pack \
            --issuer "https://accounts.google.com" \
            --subject "security@vendor.com"

Environment variables

Variable Purpose
EPACK_OIDC_TOKEN OIDC token for keyless signing (required in CI without browser)
GITHUB_TOKEN For GitHub collector
NO_COLOR=1 Disable colored output
EPACK_DEBUG=true Enable debug logging

Tips

  • Pin versions: Use @v0.1.29 instead of @latest for reproducibility
  • Use --frozen: Always use in CI to fail if lockfile is stale
  • Upload as artifacts: Store packs for traceability
  • Schedule regularly: Weekly or monthly keeps evidence current