.github/.github/workflows/compliance-audit.yaml
Adam Moussa e24004415e Add Claude Code review and compliance audit workflows
- Reusable PR review workflow (repos call via thin wrapper)
- Weekly compliance audit across all org repos
- Rollout script to push wrapper workflow to all repos
- Uses GitHub App tokens for cross-repo auth (no PAT rotation needed)
2026-05-06 15:10:48 -04:00

106 lines
3.8 KiB
YAML

name: Compliance Audit
on:
schedule:
- cron: "0 14 * * 1" # Every Monday at 10am ET (14:00 UTC)
workflow_dispatch:
jobs:
get-repos:
runs-on: ubuntu-latest
outputs:
repos: ${{ steps.list.outputs.repos }}
steps:
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.CLAUDE_CI_APP_ID }}
private-key: ${{ secrets.CLAUDE_CI_APP_PRIVATE_KEY }}
owner: Sea-Haven-Industries
- name: List org repos
id: list
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
repos=$(gh repo list Sea-Haven-Industries \
--no-archived \
--json name \
--jq '[.[].name] | @json' \
--limit 100)
echo "repos=$repos" >> "$GITHUB_OUTPUT"
audit:
needs: get-repos
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
max-parallel: 3
matrix:
repo: ${{ fromJson(needs.get-repos.outputs.repos) }}
steps:
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v1
with:
app-id: ${{ secrets.CLAUDE_CI_APP_ID }}
private-key: ${{ secrets.CLAUDE_CI_APP_PRIVATE_KEY }}
owner: Sea-Haven-Industries
repositories: ${{ matrix.repo }}
- name: Checkout repo
uses: actions/checkout@v4
with:
repository: Sea-Haven-Industries/${{ matrix.repo }}
token: ${{ steps.app-token.outputs.token }}
- name: Run compliance audit
uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
direct_prompt: |
Audit this repository for Sea Haven Industries compliance. Check each item and report pass/fail:
**Naming:**
- All resource names in IaC templates use kebab-case (no snake_case or PascalCase)
- Stack name matches repo name
**Secrets:**
- No secrets in Lambda environment variables
- No secrets in SSM Parameter Store (should be in Secrets Manager)
- No hardcoded API keys, tokens, or credentials in source code
- Secret names follow `stack-name/secret-name` convention
**Lambda defaults (if applicable):**
- Runtime is Python 3.12+ or Node 22.x
- Architecture is arm64
- Log retention is explicitly set to 60 days in the IaC template
**Project hygiene:**
- README exists and describes the project architecture
- .gitignore exists and covers .env, .aws-sam/, __pycache__
- samconfig.toml is gitignored (samconfig.toml.example committed if SAM project)
- CloudFormation outputs include function ARNs and URLs
Output a concise markdown report. Only flag actual violations — don't report items that don't apply (e.g., skip Lambda checks if no Lambdas exist).
- name: Create issue if violations found
if: failure()
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
existing=$(gh issue list \
--repo "Sea-Haven-Industries/${{ matrix.repo }}" \
--label "compliance" \
--state open \
--json number \
--jq 'length')
if [ "$existing" -eq 0 ]; then
gh issue create \
--repo "Sea-Haven-Industries/${{ matrix.repo }}" \
--title "Compliance audit: violations found" \
--body "The weekly compliance audit found violations in this repo. Check the [latest audit run](https://github.com/Sea-Haven-Industries/.github/actions/workflows/compliance-audit.yaml) for details." \
--label "compliance"
fi