Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 27 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
# Same-repo PRs have a writable token; fork PRs get a read-only token that
# cannot upload SARIF. Computed once here and reused by every upload step
# instead of repeating the same three-line condition in each job.
UPLOAD_SARIF: >-
${{ github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository }}

jobs:
build:
runs-on: ubuntu-latest
Expand All @@ -25,6 +33,11 @@ jobs:
contents: read
security-events: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
with:
egress-policy: audit

- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand Down Expand Up @@ -62,10 +75,7 @@ jobs:
--report-path gitleaks.sarif

- name: Upload gitleaks SARIF
if: >
always() &&
(github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository)
if: always() && env.UPLOAD_SARIF == 'true'
uses: github/codeql-action/upload-sarif@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4
with:
sarif_file: gitleaks.sarif
Expand All @@ -91,6 +101,11 @@ jobs:
permissions:
contents: read
steps:
- name: Harden Runner
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
with:
egress-policy: audit

- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand All @@ -107,15 +122,8 @@ jobs:
echo "::error::$cmd is missing"
exit 1
fi
"$cmd" --version 2>&1 | head -1
done
python3 --version
node --version
npm --version
gh --version
opencode --version
curl --version | head -1
jq --version
claude --version

scan:
runs-on: ubuntu-latest
Expand All @@ -126,6 +134,11 @@ jobs:
contents: read
security-events: write
steps:
- name: Harden Runner
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
with:
egress-policy: audit

- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
Expand Down Expand Up @@ -155,10 +168,7 @@ jobs:
cache: false

- name: Upload Trivy image scan results
if: >
always() &&
(github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository)
if: always() && env.UPLOAD_SARIF == 'true'
uses: github/codeql-action/upload-sarif@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4
with:
sarif_file: 'trivy-results.sarif'
Expand Down Expand Up @@ -196,10 +206,7 @@ jobs:
cache: false

- name: Upload Trivy filesystem scan results
if: >
always() &&
(github.event_name != 'pull_request' ||
github.event.pull_request.head.repo.full_name == github.repository)
if: always() && env.UPLOAD_SARIF == 'true'
uses: github/codeql-action/upload-sarif@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4
with:
sarif_file: 'trivy-fs-results.sarif'
Expand Down
15 changes: 15 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ current via daily PRs.
`# hadolint ignore=DLXXXX` with a justification comment.
- Keep the package list minimal — features (not the Dockerfile) install
language runtimes and CLI tools.
- The `linux-libc-dev` purge and Pebble binary removal are deliberate CVE
fixes (see inline comments) — the `scan` job gates on CRITICAL Trivy
findings, so don't drop these lines without re-verifying the scan stays
clean.

## CI pipeline (`ci.yml`)

Expand Down Expand Up @@ -119,3 +123,14 @@ npx @devcontainers/cli exec --workspace-folder . -- bash -c '
- **Volume mount target.** The Claude Code volume is mounted at
`/home/vscode/.claude` (matching `remoteUser: vscode`). If the remote user
ever changes, the mount target must be updated to match.
- **Claude Code CLI is installed by the devcontainer feature**
(`ghcr.io/anthropics/devcontainer-features/claude-code:1.0`), which runs as
root during the image build and places the package under the nvm global
`node_modules` dir. Never add `npm install -g @anthropic-ai/claude-code` (or
re-run its `install.cjs`) to `updateContentCommand` — that step runs as user
`vscode` and fails with `EACCES` trying to rename the root-owned package
(this broke CI in PR #51). `updateContentCommand` should only install
user-writable packages (currently just `opencode-ai`).
- **CI runs on Copilot/bot-authored PR branches often show `action_required`**
and won't execute automatically. Approve them in the GitHub UI, or run
`gh run rerun <run-id> --repo idvoretskyi/dev` to trigger them.