Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91320fdd80 | ||
|
|
ed781b990e | ||
|
|
9e618b3b90 | ||
|
|
f45cecf08c | ||
|
|
5bd68f9b8a | ||
|
|
bf8e309b19 |
4 changed files with 100 additions and 67 deletions
|
|
@ -3,106 +3,78 @@ name: CI
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: ["**"]
|
branches: ["**"]
|
||||||
# Lets `hive-forge ci-rerun` re-trigger CI via the workflow-dispatch API
|
# Lets `hive-forge ci-rerun` re-trigger CI via workflow-dispatch API
|
||||||
# without an empty commit. No effect on the PR-triggered runs above.
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check:
|
check:
|
||||||
name: nix flake check
|
name: nix flake check
|
||||||
runs-on: [hive-ci]
|
runs-on: [hive-ci]
|
||||||
# Bound the job so a wedged build fails in minutes instead of
|
# 30 min is well above a cold-cache rebuild (~15 min observed) and well
|
||||||
# hanging until the runner's 3h cap (or, when the runner itself
|
# under the runner's 3h cap
|
||||||
# deadlocks, never). 30 min is well above a cold-cache rebuild
|
|
||||||
# (~15 min observed) and well under the 3h hard cap — tune if a
|
|
||||||
# legit cold build ever trips it.
|
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: check
|
- name: check
|
||||||
# Runs all flake checks: formatting (treefmt+rustfmt), cargo test,
|
|
||||||
# cargo clippy, and module evaluation. No --no-build: the checks
|
|
||||||
# derivations are the canonical source of truth.
|
|
||||||
run: nix flake check
|
run: nix flake check
|
||||||
|
|
||||||
tracker-tags:
|
tracker-tags:
|
||||||
name: tracker-tag lint
|
name: tracker-tag lint
|
||||||
runs-on: [hive-ci]
|
runs-on: [hive-ci]
|
||||||
# Pure git+grep — seconds normally; a few minutes is already a hang.
|
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: lint
|
- name: lint
|
||||||
# Flags hash-number tracker tags in source (hive convention is
|
|
||||||
# prose, not tags — /knowledge/hive-rules.md). Its own job, and
|
|
||||||
# IS a required check on the forge (branch protection) — a hit
|
|
||||||
# blocks merge. See scripts/check-issue-refs.sh.
|
|
||||||
run: sh scripts/check-issue-refs.sh
|
run: sh scripts/check-issue-refs.sh
|
||||||
|
|
||||||
comment-blocks:
|
comment-blocks:
|
||||||
name: comment-block lint
|
name: comment-block lint
|
||||||
runs-on: [hive-ci]
|
runs-on: [hive-ci]
|
||||||
# Pure git+awk — seconds.
|
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: lint
|
- name: lint
|
||||||
# Flags contiguous comment blocks over 30 lines (a giant prose
|
|
||||||
# block belongs in docs/ as implementation notes, not in source).
|
|
||||||
# Own job, and IS a required check on the forge (branch
|
|
||||||
# protection) — a hit blocks merge. See
|
|
||||||
# scripts/check-comment-blocks.sh.
|
|
||||||
run: sh scripts/check-comment-blocks.sh
|
run: sh scripts/check-comment-blocks.sh
|
||||||
|
|
||||||
doc-refs:
|
doc-refs:
|
||||||
name: doc-pointer lint
|
name: doc-pointer lint
|
||||||
runs-on: [hive-ci]
|
runs-on: [hive-ci]
|
||||||
# Pure git+grep — seconds.
|
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: lint
|
- name: lint
|
||||||
# Flags `docs/…md` paths and relative markdown links that no
|
|
||||||
# longer resolve. Pointing at a doc is what the comment-block
|
|
||||||
# lint above pushes people toward, so the pointers need a gate of
|
|
||||||
# their own. See scripts/check-doc-refs.sh.
|
|
||||||
run: sh scripts/check-doc-refs.sh
|
run: sh scripts/check-doc-refs.sh
|
||||||
|
|
||||||
|
attribution-trailers:
|
||||||
|
name: attribution-trailer lint
|
||||||
|
runs-on: [hive-ci]
|
||||||
|
timeout-minutes: 5
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: lint
|
||||||
|
run: sh scripts/check-attribution-trailers.sh
|
||||||
|
|
||||||
prose-lint:
|
prose-lint:
|
||||||
name: prose lint (vale)
|
name: prose lint (vale)
|
||||||
runs-on: [hive-ci]
|
runs-on: [hive-ci]
|
||||||
# A `vale sync` + full docs/ run took under a minute in testing.
|
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: lint
|
- name: lint
|
||||||
# Styles (Microsoft + alex + write-good, named in .vale.ini's
|
# Styles are fetched fresh from Vale Package Hub each run (not vendored).
|
||||||
# `Packages` line) are fetched fresh from the Vale Package Hub each
|
# Not wired into branch protection — see prose-lint-errors below for the
|
||||||
# run rather than vendored, so this job always lints against
|
# error-only slice that is.
|
||||||
# upstream's current rules. Failing red on a hit is intentional --
|
|
||||||
# the existing docs/ tree has a standing backlog of warning- and
|
|
||||||
# suggestion-level rule hits, so this job stays red on unrelated
|
|
||||||
# PRs until that backlog is worked down (tracked separately, as a
|
|
||||||
# follow-up to the error-only work below). Not wired into branch
|
|
||||||
# protection -- see the sibling job below for the error-only slice
|
|
||||||
# that is.
|
|
||||||
run: XDG_DATA_HOME="$PWD/.vale-data" nix shell nixpkgs#vale --command sh -c 'vale sync && vale docs'
|
run: XDG_DATA_HOME="$PWD/.vale-data" nix shell nixpkgs#vale --command sh -c 'vale sync && vale docs'
|
||||||
|
|
||||||
prose-lint-errors:
|
prose-lint-errors:
|
||||||
name: prose lint (vale, errors)
|
name: prose lint (vale, errors)
|
||||||
runs-on: [hive-ci]
|
runs-on: [hive-ci]
|
||||||
# Own `vale sync` rather than reusing the sibling job's: each job gets
|
|
||||||
# a fresh checkout/environment, so there is nothing to share between
|
|
||||||
# them without an artifact-upload step this doesn't need.
|
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: lint
|
- name: lint
|
||||||
# The error-level-only slice of the sibling job above.
|
# Error-level-only slice. Split out so this job alone can be a required
|
||||||
# `--minAlertLevel=error` changes what vale both reports AND exits
|
# check without blocking merges on the warning/suggestion backlog.
|
||||||
# non-zero on, so this job's pass/fail tracks only error-severity
|
|
||||||
# rule hits, not the warning/suggestion backlog the sibling job
|
|
||||||
# carries. Split out so this one alone can be a required check
|
|
||||||
# (forge branch protection) without blocking merges on the
|
|
||||||
# pre-existing backlog the sibling job still surfaces.
|
|
||||||
run: XDG_DATA_HOME="$PWD/.vale-data" nix shell nixpkgs#vale --command sh -c 'vale sync && vale --minAlertLevel=error docs'
|
run: XDG_DATA_HOME="$PWD/.vale-data" nix shell nixpkgs#vale --command sh -c 'vale sync && vale --minAlertLevel=error docs'
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,12 @@ that switch on the forge is a separate operator action, not something this
|
||||||
table can assert ahead of it happening.
|
table can assert ahead of it happening.
|
||||||
|
|
||||||
| Job | What it runs | Required? |
|
| Job | What it runs | Required? |
|
||||||
| ----------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------- |
|
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------- | ------------------------------- |
|
||||||
| **nix flake check** | treefmt formatting, `cargo clippy -D warnings`, `cargo test`, module evaluation | yes |
|
| **nix flake check** | treefmt formatting, `cargo clippy -D warnings`, `cargo test`, module evaluation | yes |
|
||||||
| **tracker-tag lint** | flags `#NNN` issue tags in source and comments (`scripts/check-issue-refs.sh`) | yes |
|
| **tracker-tag lint** | flags `#NNN` issue tags in source and comments (`scripts/check-issue-refs.sh`) | yes |
|
||||||
| **comment-block lint** | flags contiguous comment blocks over 30 lines (`scripts/check-comment-blocks.sh`) | yes |
|
| **comment-block lint** | flags contiguous comment blocks over 30 lines (`scripts/check-comment-blocks.sh`) | yes |
|
||||||
| **doc-pointer lint** | flags `docs/…md` paths and relative markdown links that no longer resolve (`scripts/check-doc-refs.sh`) | yes |
|
| **doc-pointer lint** | flags `docs/…md` paths and relative markdown links that no longer resolve (`scripts/check-doc-refs.sh`) | yes |
|
||||||
|
| **attribution-trailer lint** | flags `Co-Authored-By` trailers with Claude/Anthropic attribution in PR commits (`scripts/check-attribution-trailers.sh`) | not yet — intended to be |
|
||||||
| **prose lint (vale, errors)** | vale, `docs/` tree, error-severity rule hits only | not yet — intended to be |
|
| **prose lint (vale, errors)** | vale, `docs/` tree, error-severity rule hits only | not yet — intended to be |
|
||||||
| **prose lint (vale)** | vale, `docs/` tree, full severity range (warnings + suggestions too) | no — advisory, standing backlog |
|
| **prose lint (vale)** | vale, `docs/` tree, full severity range (warnings + suggestions too) | no — advisory, standing backlog |
|
||||||
|
|
||||||
|
|
|
||||||
63
scripts/check-attribution-trailers.sh
Executable file
63
scripts/check-attribution-trailers.sh
Executable file
|
|
@ -0,0 +1,63 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Flags Co-Authored-By trailers with Claude/Anthropic attribution in PR commits.
|
||||||
|
# The hive convention in /knowledge/hive-rules.md forbids these trailers.
|
||||||
|
#
|
||||||
|
# Pattern is anchored to an actual git trailer line — `^[[:space:]]*co-authored-by:`
|
||||||
|
# — not any mention of the phrase, then requires the value name `claude`,
|
||||||
|
# `anthropic`, or `noreply@anthropic.com`. Matching is case-insensitive and
|
||||||
|
# per-line (git trailers are one `Key: value` per line) to cover variants like
|
||||||
|
# `Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>` while letting a
|
||||||
|
# commit subject/body that merely *discusses* the trailer (e.g. this script's
|
||||||
|
# own "add CI lint for Co-Authored-By/Claude/Anthropic trailers") pass.
|
||||||
|
#
|
||||||
|
# Scope is the PR's commits (BASE..HEAD), not entire history — old commits
|
||||||
|
# must not fail the build.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
trailer_re='^[[:space:]]*co-authored-by:.*(claude|anthropic|noreply@anthropic\.com)'
|
||||||
|
|
||||||
|
if [ -n "${GITHUB_BASE_REF:-}" ]; then
|
||||||
|
base="origin/${GITHUB_BASE_REF}"
|
||||||
|
else
|
||||||
|
base="origin/main"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# actions/checkout@v3 fetches the PR head but may not fetch the base branch
|
||||||
|
if ! git rev-parse --verify "$base" >/dev/null 2>&1; then
|
||||||
|
branch="${base#origin/}"
|
||||||
|
git fetch origin "$branch" 2>/dev/null || true
|
||||||
|
if ! git rev-parse --verify "$base" >/dev/null 2>&1; then
|
||||||
|
base="origin/main"
|
||||||
|
git fetch origin main 2>/dev/null || base="HEAD~10"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
commits="$(git log --reverse --format='%H' "${base}..HEAD" 2>/dev/null || true)"
|
||||||
|
|
||||||
|
if [ -z "$commits" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
hits=""
|
||||||
|
for sha in $commits; do
|
||||||
|
msg="$(git log -1 --format='%B' "$sha")"
|
||||||
|
if printf '%s\n' "$msg" | grep -qiE "$trailer_re"; then
|
||||||
|
subject="$(git log -1 --format='%s' "$sha")"
|
||||||
|
hits="${hits}${sha}|${subject}
|
||||||
|
"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "$hits" ]; then
|
||||||
|
printf '%s' "$hits" | while IFS='|' read -r sha subject; do
|
||||||
|
[ -z "$sha" ] && continue
|
||||||
|
short_sha="$(printf '%s' "$sha" | cut -c1-8)"
|
||||||
|
printf '::error title=Attribution trailer found in %s::%s — commit carries a Co-Authored-By trailer with Claude/Anthropic attribution, forbidden by /knowledge/hive-rules.md\n' \
|
||||||
|
"$short_sha" "$subject"
|
||||||
|
done
|
||||||
|
count="$(printf '%s' "$hits" | grep -c '|' || true)"
|
||||||
|
printf 'check-attribution-trailers: %s commit(s) with prohibited trailers found\n' "$count" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
@ -1,17 +1,8 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Git pre-push hook: runs the tracker-tag, comment-block and doc-pointer
|
# Install: ln -sf ../../scripts/pre-push .git/hooks/pre-push
|
||||||
# lints against the working tree before any push lands on the remote.
|
|
||||||
# Catches issues that would fail CI and require a follow-up commit
|
|
||||||
# (common failure mode: a nix comment containing a hash-issue-number
|
|
||||||
# tag added mid-session).
|
|
||||||
#
|
#
|
||||||
# Install (once per clone):
|
# Runs against the full working tree (not just staged or pushed files) to match
|
||||||
# ln -sf ../../scripts/pre-push .git/hooks/pre-push
|
# what CI sees: `nix flake check` builds from the committed tree.
|
||||||
#
|
|
||||||
# The hook runs against the full working tree (not just staged or
|
|
||||||
# pushed files) to match what CI sees: `nix flake check` builds from
|
|
||||||
# the committed tree, so an untracked hit on a staged file would still
|
|
||||||
# trip CI.
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
repo_root="$(git rev-parse --show-toplevel)"
|
repo_root="$(git rev-parse --show-toplevel)"
|
||||||
|
|
@ -34,5 +25,11 @@ if ! sh "$repo_root/scripts/check-doc-refs.sh"; then
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "pre-push: running attribution-trailer lint..." >&2
|
||||||
|
if ! sh "$repo_root/scripts/check-attribution-trailers.sh"; then
|
||||||
|
echo "pre-push: attribution-trailer lint FAILED — fix before pushing" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
echo "pre-push: lints passed ✓" >&2
|
echo "pre-push: lints passed ✓" >&2
|
||||||
exit 0
|
exit 0
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue