chore: pin actions to commit SHAs and add Skills section to CLAUDE.md

Pin all GitHub Actions to commit SHAs instead of mutable version tags
across ci.yml, release.yml, maintenance.yml, and all reusable workflows.
This prevents supply-chain attacks via tag hijacking.

Add the required Skills section to CLAUDE.md mapping project files
(README.md, .github/workflows/*.yml) to their respective review skills.
This commit is contained in:
Andriy Kalashnykov
2026-03-29 17:16:56 -04:00
parent 527c79350c
commit 46f37ae4fb
7 changed files with 40 additions and 29 deletions

View File

@@ -34,10 +34,10 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Node.js ${{ matrix.node }} - name: Setup Node.js ${{ matrix.node }}
uses: actions/setup-node@v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
node-version: ${{ matrix.node }} node-version: ${{ matrix.node }}
@@ -68,7 +68,7 @@ jobs:
- name: Cache npm - name: Cache npm
if: matrix.pm == 'npm' if: matrix.pm == 'npm'
uses: actions/cache@v4 uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with: with:
path: ${{ steps.npm-cache-dir.outputs.dir }} path: ${{ steps.npm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ matrix.node }}-npm-${{ hashFiles('**/package-lock.json') }} key: ${{ runner.os }}-node-${{ matrix.node }}-npm-${{ hashFiles('**/package-lock.json') }}
@@ -83,7 +83,7 @@ jobs:
- name: Cache pnpm - name: Cache pnpm
if: matrix.pm == 'pnpm' if: matrix.pm == 'pnpm'
uses: actions/cache@v4 uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with: with:
path: ${{ steps.pnpm-cache-dir.outputs.dir }} path: ${{ steps.pnpm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ matrix.node }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} key: ${{ runner.os }}-node-${{ matrix.node }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
@@ -104,7 +104,7 @@ jobs:
- name: Cache yarn - name: Cache yarn
if: matrix.pm == 'yarn' if: matrix.pm == 'yarn'
uses: actions/cache@v4 uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with: with:
path: ${{ steps.yarn-cache-dir.outputs.dir }} path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ matrix.node }}-yarn-${{ hashFiles('**/yarn.lock') }} key: ${{ runner.os }}-node-${{ matrix.node }}-yarn-${{ hashFiles('**/yarn.lock') }}
@@ -113,7 +113,7 @@ jobs:
- name: Cache bun - name: Cache bun
if: matrix.pm == 'bun' if: matrix.pm == 'bun'
uses: actions/cache@v4 uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with: with:
path: ~/.bun/install/cache path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
@@ -146,7 +146,7 @@ jobs:
# Upload test artifacts on failure # Upload test artifacts on failure
- name: Upload test artifacts - name: Upload test artifacts
if: failure() if: failure()
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with: with:
name: test-results-${{ matrix.os }}-node${{ matrix.node }}-${{ matrix.pm }} name: test-results-${{ matrix.os }}-node${{ matrix.node }}-${{ matrix.pm }}
path: | path: |
@@ -160,10 +160,10 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
node-version: '20.x' node-version: '20.x'
@@ -205,10 +205,10 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
node-version: '20.x' node-version: '20.x'
@@ -223,10 +223,10 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
node-version: '20.x' node-version: '20.x'

View File

@@ -15,8 +15,8 @@ jobs:
name: Check Dependencies name: Check Dependencies
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
node-version: '20.x' node-version: '20.x'
- name: Check for outdated packages - name: Check for outdated packages
@@ -26,8 +26,8 @@ jobs:
name: Security Audit name: Security Audit
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
node-version: '20.x' node-version: '20.x'
- name: Run security audit - name: Run security audit
@@ -43,7 +43,7 @@ jobs:
name: Stale Issues/PRs name: Stale Issues/PRs
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/stale@v9 - uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9
with: with:
stale-issue-message: 'This issue is stale due to inactivity.' stale-issue-message: 'This issue is stale due to inactivity.'
stale-pr-message: 'This PR is stale due to inactivity.' stale-pr-message: 'This PR is stale due to inactivity.'

View File

@@ -14,7 +14,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with: with:
fetch-depth: 0 fetch-depth: 0

View File

@@ -23,7 +23,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with: with:
fetch-depth: 0 fetch-depth: 0

View File

@@ -27,10 +27,10 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
node-version: ${{ inputs.node-version }} node-version: ${{ inputs.node-version }}
@@ -59,7 +59,7 @@ jobs:
- name: Cache npm - name: Cache npm
if: inputs.package-manager == 'npm' if: inputs.package-manager == 'npm'
uses: actions/cache@v4 uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with: with:
path: ${{ steps.npm-cache-dir.outputs.dir }} path: ${{ steps.npm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ inputs.node-version }}-npm-${{ hashFiles('**/package-lock.json') }} key: ${{ runner.os }}-node-${{ inputs.node-version }}-npm-${{ hashFiles('**/package-lock.json') }}
@@ -74,7 +74,7 @@ jobs:
- name: Cache pnpm - name: Cache pnpm
if: inputs.package-manager == 'pnpm' if: inputs.package-manager == 'pnpm'
uses: actions/cache@v4 uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with: with:
path: ${{ steps.pnpm-cache-dir.outputs.dir }} path: ${{ steps.pnpm-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ inputs.node-version }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }} key: ${{ runner.os }}-node-${{ inputs.node-version }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
@@ -95,7 +95,7 @@ jobs:
- name: Cache yarn - name: Cache yarn
if: inputs.package-manager == 'yarn' if: inputs.package-manager == 'yarn'
uses: actions/cache@v4 uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with: with:
path: ${{ steps.yarn-cache-dir.outputs.dir }} path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-node-${{ inputs.node-version }}-yarn-${{ hashFiles('**/yarn.lock') }} key: ${{ runner.os }}-node-${{ inputs.node-version }}-yarn-${{ hashFiles('**/yarn.lock') }}
@@ -104,7 +104,7 @@ jobs:
- name: Cache bun - name: Cache bun
if: inputs.package-manager == 'bun' if: inputs.package-manager == 'bun'
uses: actions/cache@v4 uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with: with:
path: ~/.bun/install/cache path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }} key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lockb') }}
@@ -134,7 +134,7 @@ jobs:
- name: Upload test artifacts - name: Upload test artifacts
if: failure() if: failure()
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with: with:
name: test-results-${{ inputs.os }}-node${{ inputs.node-version }}-${{ inputs.package-manager }} name: test-results-${{ inputs.os }}-node${{ inputs.node-version }}-${{ inputs.package-manager }}
path: | path: |

View File

@@ -17,10 +17,10 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
node-version: ${{ inputs.node-version }} node-version: ${{ inputs.node-version }}

View File

@@ -59,3 +59,14 @@ Follow the formats in CONTRIBUTING.md:
- Hooks: JSON with matcher and hooks array - Hooks: JSON with matcher and hooks array
File naming: lowercase with hyphens (e.g., `python-reviewer.md`, `tdd-workflow.md`) File naming: lowercase with hyphens (e.g., `python-reviewer.md`, `tdd-workflow.md`)
## Skills
Use the following skills when working on related files:
| File(s) | Skill |
|---------|-------|
| `README.md` | `/readme` |
| `.github/workflows/*.yml` | `/ci-workflow` |
When spawning subagents, always pass conventions from the respective skill into the agent's prompt.