diff --git a/.github/workflows/changelog-release.yml b/.github/workflows/changelog-release.yml index f074b79..da58e9e 100644 --- a/.github/workflows/changelog-release.yml +++ b/.github/workflows/changelog-release.yml @@ -27,6 +27,15 @@ on: description: 'Commit message for version bump' type: string default: 'chore(release): bump version and update changelog [skip ci]' + app_id: + description: 'GitHub App ID for generating a token to bypass branch protections (optional)' + required: false + type: string + default: '' + secrets: + app_private_key: + description: 'GitHub App private key (required if app_id is set)' + required: false outputs: has_changes: description: 'Whether there were changes to release' @@ -48,11 +57,19 @@ jobs: env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true steps: + - name: Generate GitHub App token + id: app-token + if: ${{ inputs.app_id != '' }} + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ inputs.app_id }} + private-key: ${{ secrets.app_private_key }} + - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }} - name: Configure Git run: | @@ -396,7 +413,7 @@ jobs: - name: Create GitHub Release if: steps.changelog.outputs.has_changes == 'true' && inputs.create-github-release env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }} CHANGELOG: ${{ steps.changelog.outputs.changelog }} run: | while IFS= read -r tag; do diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9a8d5a5..3064652 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,15 @@ on: required: false type: boolean default: true + app_id: + description: 'GitHub App ID for generating a token to bypass branch protections (optional)' + required: false + type: string + default: '' + secrets: + app_private_key: + description: 'GitHub App private key (required if app_id is set)' + required: false permissions: contents: write @@ -28,6 +37,14 @@ jobs: env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true steps: + - name: Generate GitHub App token + id: app-token + if: ${{ inputs.app_id != '' }} + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ inputs.app_id }} + private-key: ${{ secrets.app_private_key }} + - name: Checkout repository uses: actions/checkout@v6 @@ -36,6 +53,7 @@ jobs: uses: googleapis/release-please-action@v5 with: release-type: ${{ inputs.release-type }} + token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }} update-readme-versions: name: Update README Versions @@ -45,11 +63,19 @@ jobs: env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true steps: + - name: Generate GitHub App token + id: app-token + if: ${{ inputs.app_id != '' }} + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ inputs.app_id }} + private-key: ${{ secrets.app_private_key }} + - name: Checkout uses: actions/checkout@v6 with: fetch-depth: 0 - token: ${{ secrets.GITHUB_TOKEN }} + token: ${{ steps.app-token.outputs.token || secrets.GITHUB_TOKEN }} - name: Update all README versions run: | diff --git a/docs/superpowers/specs/2026-05-20-trivy-tofu-scan-design.md b/docs/superpowers/specs/2026-05-20-trivy-tofu-scan-design.md deleted file mode 100644 index 21b78a8..0000000 --- a/docs/superpowers/specs/2026-05-20-trivy-tofu-scan-design.md +++ /dev/null @@ -1,91 +0,0 @@ -# Design: trivy-tofu-scan reusable workflow - -**Date:** 2026-05-20 -**Author:** David Fernandez -**Status:** Approved - -## Summary - -Replace `tfsec.yml` with a new reusable workflow `trivy-tofu-scan.yml` that uses Trivy to scan OpenTofu/Terraform IaC code for misconfigurations. The workflow generates a full report persisted in four ways: SARIF upload to the GitHub Security tab, JSON artifact, Job Summary, and PR comment. - -## Context - -The repo already has `tfsec.yml` for IaC security scanning. Trivy covers the same surface (OpenTofu/Terraform misconfigurations) via `--scanners misconfig` and provides richer output options, active maintenance, and a unified tool already used in `docker-security-scan.yml` and `ecr-security-scan.yml`. - -## Architecture - -A single file `.github/workflows/trivy-tofu-scan.yml` with `on: workflow_call`. Follows the exact pattern of `tfsec.yml`, `docker-security-scan.yml`, and `ecr-security-scan.yml`. - -### Permissions - -```yaml -permissions: - contents: read - security-events: write # SARIF upload to GitHub Security tab - pull-requests: write # PR comment -``` - -### Inputs - -| Input | Type | Default | Description | -|---|---|---|---| -| `upload_sarif` | boolean | `true` | Upload SARIF to GitHub Security tab | -| `post_comment` | boolean | `true` | Post comment on PR if findings found | - -Severity is hardcoded to `CRITICAL,HIGH` — not configurable. - -## Job: `trivy-iac` - -Runner: `ubuntu-24.04`. Env: `FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true`. - -### Steps - -1. **Checkout** — `actions/checkout@v6` - -2. **Find .tf files** — `find . -name "*.tf" -not -path "./.terraform/*"`. Sets `has_tf_files` output. Early exits (skip remaining steps) if no `.tf` files found. - -3. **Run Trivy IaC scan** — Installs Trivy CLI (pinned version), runs: - ``` - trivy config . --scanners misconfig --severity CRITICAL,HIGH \ - --format json --output trivy-results.json \ - --exit-code 1 - ``` - Uses `continue-on-error: true` to allow subsequent reporting steps to run. Captures exit code in step output. - -4. **Run Trivy SARIF export** — Re-runs Trivy with `--format sarif --output results.sarif --soft-fail`. Only runs if `has_tf_files == 'true'` and `inputs.upload_sarif`. - -5. **Upload SARIF** — `github/codeql-action/upload-sarif@v4` with `category: trivy-iac`. Runs if `upload_sarif` input is true and `results.sarif` exists. - -6. **Generate Job Summary** — Bash script parses `trivy-results.json` with `jq`, builds a markdown table of findings (ID, severity, resource, message) and writes to `$GITHUB_STEP_SUMMARY`. Always runs if `has_tf_files == 'true'`. - -7. **Upload artifact** — `actions/upload-artifact@v4` uploads `trivy-results.json` as `trivy-iac-scan-results`. Always runs if `has_tf_files == 'true'` (even on clean scans — artifact confirms the scan ran). - -8. **Post PR comment** — `actions/github-script@v9` posts a comment with finding count and link to the run. Runs if `post_comment` is true, `github.event_name == 'pull_request'`, and findings were found. - -9. **Fail if findings** — `run: exit 1` if Trivy step exit code was non-zero. - -## Error handling - -- No `.tf` files: steps 3–9 are skipped via `if: steps.find.outputs.has_tf_files == 'true'`. Workflow exits green. -- SARIF upload failure: `continue-on-error: true` so it doesn't block the fail step. -- Trivy install failure: the job fails immediately (no `continue-on-error`). - -## Migration from tfsec - -Callers replace: -```yaml -uses: nullplatform/actions-nullplatform/.github/workflows/tfsec.yml@main -``` -with: -```yaml -uses: nullplatform/actions-nullplatform/.github/workflows/trivy-tofu-scan.yml@main -``` - -The `minimum_severity` input from `tfsec.yml` has no equivalent — severity is fixed to `CRITICAL,HIGH`. - -## Files - -| Action | File | -|---|---| -| Create | `.github/workflows/trivy-tofu-scan.yml` | -| Delete (or deprecate) | `.github/workflows/tfsec.yml` |