Skip to content
Merged
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
77 changes: 77 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: Lint

# Two roles for this workflow:
#
# 1. Self-test: triggers on pull_request + push to main of *this repo* so that
# typos in the reusable workflows here get caught before they break every
# downstream consumer.
#
# 2. Reusable: other repos can call it via
# jobs:
# lint:
# uses: topcoder1/ci-workflows/.github/workflows/lint.yml@main
# See callers/lint.yml in the templates dir for a copy-paste-ready caller.
#
# What it checks:
# - actionlint on every .github/workflows/*.yml (catches GHA-specific bugs +
# embedded shellcheck for `run:` blocks)
# - prettier --check on the markdown glob (default **/*.md)
#
# Why no husky/lint-staged: this is meant to plug into repos with mixed
# tooling (or none). CI-only enforcement keeps the dependency surface flat.

on:
pull_request:
push:
branches: [main]
workflow_call:
inputs:
markdown_glob:
description: "Glob passed to prettier --check. Default '**/*.md'."
required: false
type: string
default: "**/*.md"
run_actionlint:
description: "Run actionlint job. Default true."
required: false
type: boolean
default: true
run_prettier:
description: "Run prettier --check on markdown. Default true."
required: false
type: boolean
default: true

permissions:
contents: read

jobs:
actionlint:
name: actionlint
if: ${{ github.event_name != 'workflow_call' || inputs.run_actionlint }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Download actionlint
id: get_actionlint
run: bash <(curl -s https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Supply-chain risk: unpinned main-branch curl | bash

This fetches and executes a script from rhysd/actionlint's main branch with no integrity check. Any commit to that branch — including a compromise — lands immediately in this repo's CI with no review gate.

This is especially risky here because ci-workflows is a shared-reusable-workflow host: a poisoned actionlint binary could exfiltrate secrets injected by downstream callers.

Safer alternatives (in order of preference):

  1. Pin to a specific version tag using the official action:
Suggested change
run: bash <(curl -s https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
uses: rhysd/actionlint@v1.7.7

(replace with the current release; pinning to a SHA gives the strongest guarantee)

  1. Or, if you must use the download script, pin to a commit SHA:
run: bash <(curl -s https://raw.githubusercontent.com/rhysd/actionlint/<COMMIT_SHA>/scripts/download-actionlint.bash)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Supply chain risk: fetching from unpinned main branch

This curl | bash pulls from rhysd/actionlint@main with no version pin and no checksum verification. If that branch is ever compromised, the malicious script runs immediately in every subsequent CI run — and because this is a reusable workflow, all downstream consumers are exposed too.

Pin to a specific release tag so the content is immutable:

Suggested change
run: bash <(curl -s https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
run: bash <(curl -s https://raw.githubusercontent.com/rhysd/actionlint/v1.7.7/scripts/download-actionlint.bash)

Or use the official action pinned to a SHA for stronger guarantees:

- uses: rhysd/actionlint@11f75d9775d0829b8fdc43df25c96a6e4ba40de1 # v1.7.7

(No id: / outputs.executable step needed with the action form.)

shell: bash

- name: Run actionlint
run: ${{ steps.get_actionlint.outputs.executable }} -color
shell: bash

prettier:
name: prettier (markdown)
if: ${{ github.event_name != 'workflow_call' || inputs.run_prettier }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "20"

- name: prettier --check ${{ inputs.markdown_glob || '**/*.md' }}
run: npx --yes prettier@3 --check "${{ inputs.markdown_glob || '**/*.md' }}"
1 change: 1 addition & 0 deletions .github/workflows/pr-classify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ jobs:
echo "class=$class" >> "$GITHUB_OUTPUT"
echo "Computed risk class: $class"
echo "Changed files:"
# shellcheck disable=SC2001 # multiline indent — sed is clearer than ${var//.../...}
echo "$changed" | sed 's/^/ /'

- name: Set risk label on PR
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Reusable GitHub Actions workflows for solo-dev fleet management.
Runs Anthropic's [`claude-code-action@v1`](https://github.com/anthropics/claude-code-action) on PRs to post inline review comments. Caller passes `ANTHROPIC_API_KEY` as a secret.

**Inputs:**

- `review_focus` (string, optional) — appended to the base review prompt for project-specific guidance
- `checkout_depth` (number, default `0`) — git fetch-depth (0 = full history)

Expand All @@ -19,6 +20,7 @@ Runs Anthropic's [`claude-code-action@v1`](https://github.com/anthropics/claude-
Auto-merges Dependabot PRs for patch (and optionally minor) version bumps once required checks pass.

**Inputs:**

- `merge_method` (string, default `squash`) — `merge` | `squash` | `rebase`
- `allow_minor` (bool, default `true`) — also merge minor bumps

Expand Down
Loading