chore(deps): bump the actions group with 3 updates #50
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This workflow is managed by gh actions-lock. | |
| # SPDX-License-Identifier: MPL-2.0 | |
| # workflow-linter.yml - Validates GitHub workflows against RSR security standards | |
| # This workflow can be copied to other repos for consistent enforcement | |
| name: Workflow Security Linter | |
| on: | |
| push: | |
| paths: | |
| - '.github/workflows/**' | |
| pull_request: | |
| paths: | |
| - '.github/workflows/**' | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| lint-workflows: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7.0.1 | |
| - name: Check SPDX Headers | |
| run: | | |
| echo "=== Checking SPDX License Headers ===" | |
| failed=0 | |
| for file in .github/workflows/*.yml .github/workflows/*.yaml; do | |
| [ -f "$file" ] || continue | |
| # actions-lock may prepend its own comment. Require the licence | |
| # in the leading comment block, before the workflow body. | |
| if ! awk '/^# SPDX-License-Identifier:/ { found=1 } /^[^#[:space:]]/ { exit } END { exit !found }' "$file"; then | |
| echo "ERROR: $file missing SPDX header" | |
| failed=1 | |
| fi | |
| done | |
| if [ $failed -eq 1 ]; then | |
| echo "Add '# SPDX-License-Identifier: MPL-2.0' to the leading comment block" | |
| exit 1 | |
| fi | |
| echo "All workflows have SPDX headers" | |
| - name: Check Permissions Declaration | |
| run: | | |
| echo "=== Checking Permissions ===" | |
| failed=0 | |
| for file in .github/workflows/*.yml .github/workflows/*.yaml; do | |
| [ -f "$file" ] || continue | |
| if ! grep -q "^permissions:" "$file"; then | |
| echo "ERROR: $file missing top-level 'permissions:' declaration" | |
| failed=1 | |
| fi | |
| done | |
| if [ $failed -eq 1 ]; then | |
| echo "Add a top-level 'permissions:' block (e.g. contents: read)" | |
| exit 1 | |
| fi | |
| echo "All workflows have permissions declared" | |
| # Bun is the estate's first-choice runtime (LANGUAGE-POLICY.adoc §1: | |
| # Bun > Deno > pnpm > npm) and executes .ts directly (§1.2). Tag form | |
| # matches every other ref in this repo and is resolved by actions.lock. | |
| - name: Set up Bun | |
| uses: oven-sh/setup-bun@v2.2.0 | |
| with: | |
| bun-version: latest | |
| - name: Check SHA-Pinned Actions | |
| run: | | |
| echo "=== Checking Action Pinning ===" | |
| # Find any uses: lines that don't have @SHA format | |
| # Pattern: uses: owner/repo@<40-char-hex> | |
| # Delegated to scripts/check-action-pinning.js. The rule it enforces is | |
| # unchanged in spirit — every action ref must resolve to an immutable | |
| # commit — but "pinned" now includes refs the workflow lockfile | |
| # resolves, which is how this repo pins them. Kept as a script rather | |
| # than inline because the inline form needs a heredoc inside a YAML | |
| # block scalar, and that is a well-known way to ship a gate that | |
| # silently does nothing. | |
| if ! bun scripts/check-action-pinning.js; then | |
| unpinned="see above" | |
| else | |
| unpinned="" | |
| fi | |
| if [ -n "$unpinned" ]; then | |
| echo "ERROR: Found unpinned actions:" | |
| echo "" | |
| echo "Replace version tags with SHA pins, e.g.:" | |
| echo " uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6.0.1" | |
| exit 1 | |
| fi | |
| echo "All actions are SHA-pinned" | |
| - name: Check for Duplicate Workflows | |
| run: | | |
| echo "=== Checking for Duplicates ===" | |
| # Known duplicate patterns | |
| if [ -f .github/workflows/codeql.yml ] && [ -f .github/workflows/codeql-analysis.yml ]; then | |
| echo "ERROR: Duplicate CodeQL workflows found" | |
| echo "Delete codeql-analysis.yml (keep codeql.yml)" | |
| exit 1 | |
| fi | |
| if [ -f .github/workflows/rust.yml ] && [ -f .github/workflows/rust-ci.yml ]; then | |
| echo "WARNING: Potential duplicate Rust workflows" | |
| echo "Consider consolidating rust.yml and rust-ci.yml" | |
| fi | |
| echo "No critical duplicates found" | |
| - name: Check CodeQL Language Matrix | |
| run: | | |
| echo "=== Checking CodeQL Configuration ===" | |
| if [ ! -f .github/workflows/codeql.yml ]; then | |
| echo "No CodeQL workflow found (optional)" | |
| exit 0 | |
| fi | |
| # Detect repo languages | |
| has_js=$(find . -name "*.js" -o -name "*.ts" -o -name "*.jsx" -o -name "*.tsx" -path "*/src/*" -o -path "*/lib/*" 2>/dev/null | head -1) | |
| has_py=$(find . -name "*.py" -path "*/src/*" -o -path "*/lib/*" 2>/dev/null | head -1) | |
| has_go=$(find . -name "*.go" -path "*/src/*" -o -path "*/cmd/*" -o -path "*/pkg/*" 2>/dev/null | head -1) | |
| has_rs=$(find . -name "*.rs" -path "*/src/*" 2>/dev/null | head -1) | |
| has_java=$(find . -name "*.java" -path "*/src/*" 2>/dev/null | head -1) | |
| has_rb=$(find . -name "*.rb" -path "*/lib/*" -o -path "*/app/*" 2>/dev/null | head -1) | |
| echo "Detected languages:" | |
| [ -n "$has_py" ] && echo " - python" | |
| [ -n "$has_go" ] && echo " - go" | |
| [ -n "$has_rs" ] && echo " - rust (note: CodeQL rust is limited)" | |
| [ -n "$has_java" ] && echo " - java-kotlin" | |
| [ -n "$has_rb" ] && echo " - ruby" | |
| # Check for over-reach | |
| if grep -q "language:.*'go'" .github/workflows/codeql.yml && [ -z "$has_go" ]; then | |
| echo "WARNING: CodeQL configured for Go but no Go files found" | |
| fi | |
| if grep -q "language:.*'python'" .github/workflows/codeql.yml && [ -z "$has_py" ]; then | |
| echo "WARNING: CodeQL configured for Python but no Python files found" | |
| fi | |
| if grep -q "language:.*'java'" .github/workflows/codeql.yml && [ -z "$has_java" ]; then | |
| echo "WARNING: CodeQL configured for Java but no Java files found" | |
| fi | |
| if grep -q "language:.*'ruby'" .github/workflows/codeql.yml && [ -z "$has_rb" ]; then | |
| echo "WARNING: CodeQL configured for Ruby but no Ruby files found" | |
| fi | |
| echo "CodeQL check complete" | |
| - name: Check Secrets Guards | |
| run: | | |
| echo "=== Checking Secrets Usage ===" | |
| # Look for secrets without conditional guards in mirror workflows | |
| if [ -f .github/workflows/mirror.yml ]; then | |
| if grep -q "secrets\." .github/workflows/mirror.yml; then | |
| if ! grep -q "if:.*vars\." .github/workflows/mirror.yml; then | |
| echo "WARNING: mirror.yml uses secrets without vars guard" | |
| echo "Add 'if: vars.FEATURE_ENABLED == true' to jobs" | |
| fi | |
| fi | |
| fi | |
| echo "Secrets check complete" | |
| - name: Summary | |
| run: | | |
| echo "" | |
| echo "=== Workflow Linter Summary ===" | |
| echo "All critical checks passed." | |
| echo "" | |
| echo "For more info, see: robot-repo-bot/ERROR-CATALOG.scm" |