diff --git a/Makefile b/Makefile index 020d753..55e8a1b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,7 @@ ACTIONS := \ docker \ node \ + claude/check-shared-block \ git/create_tag \ git/promotion-gate \ helm/diff \ diff --git a/README.md b/README.md index b4aa160..789a40b 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,12 @@ Reusable composite actions for Gitea CI/CD pipelines. ## Actions +### Claude + +| Action | Description | +|---|---| +| [claude/check-shared-block](claude/check-shared-block/README.md) | Fails when a repo's shared CLAUDE.md block has drifted from the canonical copy in stat-tackler-infra | + ### Docker | Action | Description | diff --git a/claude/check-shared-block/README.md b/claude/check-shared-block/README.md new file mode 100644 index 0000000..667347b --- /dev/null +++ b/claude/check-shared-block/README.md @@ -0,0 +1,44 @@ +# Check Shared CLAUDE.md Block + + +## Description + +Fails when a repo's shared CLAUDE.md block has drifted from the canonical copy in stat-tackler-infra + + + +## Inputs + +| name | description | required | default | +| --- | --- | --- | --- | +| `TARGET` |

Path to the CLAUDE.md file to check

| `false` | `CLAUDE.md` | +| `CANONICAL_URL` |

Raw URL of the canonical shared fragment

| `false` | `https://gitea.pixelparasol.com/stat-tackler/stat-tackler-infra/raw/branch/main/docs/CLAUDE.shared.md` | +| `GITEA_TOKEN` |

Gitea token with read access to stat-tackler-infra, if it is private

| `false` | `""` | + + + +## Runs + +This action is a `composite` action. + + +## Running locally + +The check logic has no dependency on the composite action wrapper beyond +`curl`, `awk`, and `diff` on `PATH`. From a repo's root: + +```bash +CANONICAL_URL=https://gitea.pixelparasol.com/stat-tackler/stat-tackler-infra/raw/branch/main/docs/CLAUDE.shared.md \ + TARGET=CLAUDE.md sh -c ' + extract() { awk "//{f=0}" "$1"; } + tmp=$(mktemp) + curl -sfSL "$CANONICAL_URL" -o "$tmp" + extract "$tmp" > "$tmp.canon" + extract "$TARGET" > "$tmp.mine" + diff -u "$tmp.canon" "$tmp.mine" && echo "matches canonical" + rm -f "$tmp" "$tmp.canon" "$tmp.mine" + ' +``` + +`GITEA_TOKEN` is only needed if `stat-tackler-infra` becomes private; it is +otherwise safe to omit. diff --git a/claude/check-shared-block/action.yml b/claude/check-shared-block/action.yml new file mode 100644 index 0000000..f084e6a --- /dev/null +++ b/claude/check-shared-block/action.yml @@ -0,0 +1,75 @@ +name: Check Shared CLAUDE.md Block +description: Fails when a repo's shared CLAUDE.md block has drifted from the canonical copy in stat-tackler-infra + +inputs: + TARGET: + description: "Path to the CLAUDE.md file to check" + default: "CLAUDE.md" + CANONICAL_URL: + description: "Raw URL of the canonical shared fragment" + default: "https://gitea.pixelparasol.com/stat-tackler/stat-tackler-infra/raw/branch/main/docs/CLAUDE.shared.md" + GITEA_TOKEN: + description: "Gitea token with read access to stat-tackler-infra, if it is private" + default: "" + +runs: + using: composite + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check shared CLAUDE.md block + shell: sh + env: + TARGET: ${{ inputs.TARGET }} + CANONICAL_URL: ${{ inputs.CANONICAL_URL }} + GITEA_TOKEN: ${{ inputs.GITEA_TOKEN }} + run: | + set -e + + if [ ! -f "$TARGET" ]; then + echo "::error::$TARGET not found" + exit 1 + fi + + extract() { + # Everything between the markers, markers included. + awk '//{f=0}' "$1" + } + + mine=$(extract "$TARGET") + if [ -z "$mine" ]; then + echo "::error::$TARGET has no SHARED:BEGIN/SHARED:END block." + echo "Copy it from $CANONICAL_URL" + exit 1 + fi + + tmp=$(mktemp) + if [ -n "$GITEA_TOKEN" ]; then + curl -sfSL -H "Authorization: token $GITEA_TOKEN" "$CANONICAL_URL" -o "$tmp" + else + curl -sfSL "$CANONICAL_URL" -o "$tmp" + fi + + theirs=$(extract "$tmp") + if [ -z "$theirs" ]; then + echo "::error::Could not read the canonical block from $CANONICAL_URL" + exit 1 + fi + + if [ "$mine" = "$theirs" ]; then + echo "Shared CLAUDE.md block matches the canonical copy." + rm -f "$tmp" + exit 0 + fi + + echo "::error::The shared CLAUDE.md block has drifted from the canonical copy." + echo "Canonical: $CANONICAL_URL" + echo + echo "--- canonical" + echo "+++ $TARGET" + printf '%s\n' "$theirs" > "$tmp.canon" + printf '%s\n' "$mine" > "$tmp.mine" + diff -u "$tmp.canon" "$tmp.mine" || true + rm -f "$tmp" "$tmp.canon" "$tmp.mine" + exit 1