From 5aec889c7df443fd9b98c3ab42558cdbaa981080 Mon Sep 17 00:00:00 2001 From: Bryan Young Date: Sun, 19 Apr 2026 10:15:28 -0400 Subject: [PATCH 1/3] harden GitHub Actions --- .github/CODEOWNERS | 3 +++ .github/workflows/ci.yml | 9 ++++++--- .github/workflows/claude-code-review.yml | 4 ++-- .github/workflows/claude.yml | 4 ++-- .github/workflows/dependency-review.yml | 22 ++++++++++++++++++++++ .github/workflows/homebrew-release.yml | 11 +++++++---- 6 files changed, 42 insertions(+), 11 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 .github/workflows/dependency-review.yml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..eac3de5 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# Require explicit review for workflow and GitHub automation changes. +.github/workflows/** @intertwine +.github/actions/** @intertwine diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ee51d4..b519b2d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,9 @@ on: branches: [main] workflow_dispatch: +permissions: + contents: read + jobs: test: runs-on: ubuntu-latest @@ -16,15 +19,15 @@ jobs: fail-fast: false steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: ${{ matrix.python-version }} - name: Install uv - uses: astral-sh/setup-uv@v8.0.0 + uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 - name: Install dependencies run: uv sync diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 71bea42..2d65679 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -29,13 +29,13 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 1 - name: Run Claude Code Review id: claude-review - uses: anthropics/claude-code-action@v1 + uses: anthropics/claude-code-action@c7c8889b30499b4e46f4c32b892e43cd364bc2fe # v1 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 9370e4f..7b80cdc 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -28,13 +28,13 @@ jobs: actions: read # Required for Claude to read CI results on PRs steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 1 - name: Run Claude Code id: claude - uses: anthropics/claude-code-action@v1 + uses: anthropics/claude-code-action@c7c8889b30499b4e46f4c32b892e43cd364bc2fe # v1 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..e2509d1 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,22 @@ +name: Dependency Review + +on: + pull_request: + branches: [main] + paths: + - "pyproject.toml" + - "uv.lock" + - "poetry.lock" + - "requirements*.txt" + - ".github/workflows/**" + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + + steps: + - name: Dependency Review + uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 diff --git a/.github/workflows/homebrew-release.yml b/.github/workflows/homebrew-release.yml index 7070cfd..5f94a05 100644 --- a/.github/workflows/homebrew-release.yml +++ b/.github/workflows/homebrew-release.yml @@ -6,21 +6,24 @@ on: - "v*" workflow_dispatch: +permissions: + contents: read + jobs: update-tap: runs-on: ubuntu-latest steps: - name: Checkout source repo - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - name: Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: "3.13" - name: Install uv - uses: astral-sh/setup-uv@v8.0.0 + uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0 - name: Check formula name availability in Homebrew/core run: | @@ -71,7 +74,7 @@ jobs: run: uv run --with pip python scripts/generate_homebrew_formula.py --output packaging/homebrew/observational-memory.rb - name: Checkout tap repo - uses: actions/checkout@v6 + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: repository: ${{ vars.HOMEBREW_TAP_REPO }} token: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} From c6fc00969f6ed4046ff8f53687febe7304f8e1d6 Mon Sep 17 00:00:00 2001 From: Bryan Young Date: Sun, 19 Apr 2026 16:24:35 -0400 Subject: [PATCH 2/3] address PR feedback --- .github/CODEOWNERS | 1 + .github/workflows/claude-code-review.yml | 20 +++++++++++++- .github/workflows/dependency-review.yml | 33 +++++++++++++++++++++++- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index eac3de5..ac48398 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,4 @@ # Require explicit review for workflow and GitHub automation changes. +.github/CODEOWNERS @intertwine .github/workflows/** @intertwine .github/actions/** @intertwine diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index 2d65679..2c41fcc 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -10,6 +10,9 @@ on: # - "src/**/*.js" # - "src/**/*.jsx" +permissions: + contents: read + jobs: claude-review: # Optional: Filter by PR author @@ -31,10 +34,25 @@ jobs: - name: Checkout repository uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: - fetch-depth: 1 + fetch-depth: 0 + + - name: Skip when the review workflow itself changes + id: workflow-change + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + run: | + set -euo pipefail + if git diff --name-only "${BASE_SHA}...${HEAD_SHA}" | grep -Fxq ".github/workflows/claude-code-review.yml"; then + echo "skip=true" >> "$GITHUB_OUTPUT" + echo "Skipping Claude review because this pull request updates the review workflow itself." + else + echo "skip=false" >> "$GITHUB_OUTPUT" + fi - name: Run Claude Code Review id: claude-review + if: steps.workflow-change.outputs.skip != 'true' uses: anthropics/claude-code-action@c7c8889b30499b4e46f4c32b892e43cd364bc2fe # v1 with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index e2509d1..8c37c0f 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -8,15 +8,46 @@ on: - "uv.lock" - "poetry.lock" - "requirements*.txt" - - ".github/workflows/**" + - ".github/workflows/**" # GitHub tracks Actions in the dependency graph. permissions: contents: read + pull-requests: read jobs: dependency-review: runs-on: ubuntu-latest steps: + - name: Check dependency review availability + id: availability + env: + GH_TOKEN: ${{ github.token }} + BASE_SHA: ${{ github.event.pull_request.base.sha }} + HEAD_SHA: ${{ github.event.pull_request.head.sha }} + run: | + set -euo pipefail + api="https://api.github.com/repos/${GITHUB_REPOSITORY}/dependency-graph/compare/${BASE_SHA}...${HEAD_SHA}" + status="$(curl -sS -o response.json -w '%{http_code}' \ + -H 'Accept: application/vnd.github+json' \ + -H "Authorization: Bearer ${GH_TOKEN}" \ + -H 'X-GitHub-Api-Version: 2022-11-28' \ + "$api")" + if [ "$status" = "200" ]; then + echo "supported=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + + message="$(jq -r '.message // empty' response.json)" + if [ "$status" = "403" ] || [ "$status" = "404" ]; then + echo "supported=false" >> "$GITHUB_OUTPUT" + echo "::warning::Skipping dependency review: ${message:-Dependency graph is not enabled for this repository.}" + exit 0 + fi + + cat response.json + exit 1 + - name: Dependency Review + if: steps.availability.outputs.supported == 'true' uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 From 2fa306b50b5568bf1a8256c75c4ae16841df9508 Mon Sep 17 00:00:00 2001 From: Bryan Young Date: Sun, 19 Apr 2026 16:35:20 -0400 Subject: [PATCH 3/3] restore direct dependency review --- .github/workflows/dependency-review.yml | 30 ------------------------- 1 file changed, 30 deletions(-) diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index 8c37c0f..4198a71 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -19,35 +19,5 @@ jobs: runs-on: ubuntu-latest steps: - - name: Check dependency review availability - id: availability - env: - GH_TOKEN: ${{ github.token }} - BASE_SHA: ${{ github.event.pull_request.base.sha }} - HEAD_SHA: ${{ github.event.pull_request.head.sha }} - run: | - set -euo pipefail - api="https://api.github.com/repos/${GITHUB_REPOSITORY}/dependency-graph/compare/${BASE_SHA}...${HEAD_SHA}" - status="$(curl -sS -o response.json -w '%{http_code}' \ - -H 'Accept: application/vnd.github+json' \ - -H "Authorization: Bearer ${GH_TOKEN}" \ - -H 'X-GitHub-Api-Version: 2022-11-28' \ - "$api")" - if [ "$status" = "200" ]; then - echo "supported=true" >> "$GITHUB_OUTPUT" - exit 0 - fi - - message="$(jq -r '.message // empty' response.json)" - if [ "$status" = "403" ] || [ "$status" = "404" ]; then - echo "supported=false" >> "$GITHUB_OUTPUT" - echo "::warning::Skipping dependency review: ${message:-Dependency graph is not enabled for this repository.}" - exit 0 - fi - - cat response.json - exit 1 - - name: Dependency Review - if: steps.availability.outputs.supported == 'true' uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0