diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml index 5e84fda..3b1fd23 100644 --- a/.github/workflows/scan.yml +++ b/.github/workflows/scan.yml @@ -12,6 +12,17 @@ on: dotnet_version: type: string default: '10.0.x' + style_check: + description: 'Opt-in house style gate: fail when an em dash (U+2014) is introduced in the change set' + type: boolean + default: false + secrets: + DISCORD_WEBHOOK_URL: + description: 'Incoming Discord webhook the run summary is posted to. Optional: omit to skip the Discord post.' + required: false + ANTHROPIC_API_KEY: + description: 'Anthropic API key enabling the optional Claude PR review. Optional: omit to skip that step.' + required: false permissions: contents: read @@ -24,24 +35,32 @@ jobs: GITLEAKS_VERSION: 8.24.3 steps: - name: Checkout consumer repo - uses: actions/checkout@v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: fetch-depth: 0 + # Check out SecureCheck at the SAME ref the consumer pinned (github.workflow_ref + # is "owner/repo/path@ref" for reusable workflows). Without this, a consumer + # pinning @v1.0.0 would get the v1.0.0 workflow but main-branch scripts. + - name: Resolve SecureCheck ref + id: scref + run: echo "ref=${GITHUB_WORKFLOW_REF##*@}" >> "$GITHUB_OUTPUT" + - name: Checkout SecureCheck - uses: actions/checkout@v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 with: repository: w1ck3ds0d4/SecureCheck + ref: ${{ steps.scref.outputs.ref }} path: .securecheck fetch-depth: 1 - name: Set up Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: node-version: ${{ inputs.node_version }} - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: ${{ inputs.python_version }} @@ -252,8 +271,12 @@ jobs: echo "duration=$(( $(date +%s) - T0 ))" >> "$GITHUB_OUTPUT" echo "jscpd clones: ${CLONES} (duplicated lines: ${COUNT})" + # Opt-in house-style gate (off by default). This is a personal authoring + # convention, not a security check, so consumers are never failed by it + # unless they explicitly set style_check: true on the caller. - name: Style check (no em-dashes introduced) id: em_dash + if: ${{ inputs.style_check }} run: | set -euo pipefail T0=$(date +%s) diff --git a/README.md b/README.md index 6b4810f..be0f8cb 100644 --- a/README.md +++ b/README.md @@ -47,10 +47,28 @@ permissions: jobs: scan: - uses: w1ck3ds0d4/SecureCheck/.github/workflows/scan.yml@main - secrets: inherit + uses: w1ck3ds0d4/SecureCheck/.github/workflows/scan.yml@v1 + secrets: + DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} # optional ``` +Pin `@v1` for the stable line (or `@main` for latest). The workflow checks out its own scripts at the **same ref you pin**, so a pinned caller is fully reproducible. Mapping the two secrets explicitly (rather than `secrets: inherit`) follows least privilege - only these two are ever passed; both are optional. + +### Inputs and secrets + +| Input | Default | Meaning | +| --- | --- | --- | +| `node_version` | `20` | Node version for ESLint / jscpd | +| `python_version` | `3.11` | Python version for ruff | +| `dotnet_version` | `10.0.x` | .NET SDK for `dotnet format` | +| `style_check` | `false` | Opt-in house-style gate (fails on an introduced em dash); off by default | + +| Secret | Required | Used for | +| --- | --- | --- | +| `DISCORD_WEBHOOK_URL` | no | Posting the run summary embed; omit to skip the Discord post | +| `ANTHROPIC_API_KEY` | no | The optional Claude PR review; omit to skip that step | + ### Configure secrets Set the webhook secret on the consumer repo: @@ -103,8 +121,9 @@ The reusable workflow accepts three optional inputs: ```yaml jobs: scan: - uses: w1ck3ds0d4/SecureCheck/.github/workflows/scan.yml@main - secrets: inherit + uses: w1ck3ds0d4/SecureCheck/.github/workflows/scan.yml@v1 + secrets: + DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} with: node_version: '22' python_version: '3.12' diff --git a/ROADMAP.md b/ROADMAP.md index a167ab7..3db6f9b 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -10,8 +10,8 @@ output as artifacts. ## Current state -Workflow is in production and consumed by DA-Task-Alert, RS3-Companion, -GlassVault, GlassVault.tools, and others. Gitleaks 8.24.3, Semgrep `auto`, +Workflow is in production and consumed across several private repositories. +Gitleaks 8.24.3, Semgrep `auto`, Trivy, Claude Sonnet step (gated on `ANTHROPIC_API_KEY`). Discord severity coding (green clean / yellow findings / orange many findings / red gitleaks hit). Per-scanner JSON artifacts retained 14 days. PR heartbeat posts even