mirror of
https://github.com/boshu2/agentops.git
synced 2026-09-14 15:08:13 +08:00
feat(release): release-artifact parity gate (FU5, age-8duhj)
Remove the vestigial in-repo homebrew-tap/Formula/agentops.rb (frozen at version 2.31.0 + license MIT while the repo is 3.2.0 / Apache-2.0); the live tap is generated by GoReleaser into boshu2/homebrew-agentops. Replace the tap README with a pointer that documents this and forbids re-adding a formula. Make the .goreleaser.yml archive files: list explicit (README.md, LICENSE, CHANGELOG.md) so the packed README always matches the tagged commit rather than relying on GoReleaser defaults. Add scripts/check-release-parity.sh: asserts (a) tarball README sha256 == repo README, (b) any in-repo formula license == LICENSE (Apache-2.0), (c) any in-repo formula version == release tag. Wired into .github/workflows/release.yml as a post-build gate over each dist/ tarball. Fixture-based bats coverage in tests/scripts/check-release-parity.bats (red on stale README / wrong license / stale version, green on parity).
This commit is contained in:
@@ -222,6 +222,16 @@ jobs:
|
||||
echo "No existing release for $VERSION"
|
||||
fi
|
||||
|
||||
- name: Release parity pre-check (inputs, fail-closed)
|
||||
run: |
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
chmod +x scripts/check-release-parity.sh
|
||||
# Input-level check BEFORE anything is published: lints any in-repo
|
||||
# formula against LICENSE and the tag (formula-only mode — no
|
||||
# tarball yet). A divergence here means no release asset and no tap
|
||||
# commit ever exist.
|
||||
scripts/check-release-parity.sh --tag "$VERSION"
|
||||
|
||||
- name: Publish with GoReleaser
|
||||
uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7
|
||||
with:
|
||||
@@ -231,6 +241,44 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }}
|
||||
|
||||
- name: Verify published artifacts (identity-bound parity gate)
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
VERSION="${{ steps.version.outputs.version }}"
|
||||
chmod +x scripts/check-release-parity.sh
|
||||
# Identity-bound: download the EXACT assets the release now serves
|
||||
# (not the local dist/ copies) and parity-check those. The checkout
|
||||
# is at the tag, so the working-tree README is the tag README.
|
||||
# GoReleaser wraps flat (wrap_in_directory: false), so README.md
|
||||
# sits at the tarball root. On ANY divergence: delete the release
|
||||
# so no bad asset stays served (the tap formula then points at a
|
||||
# missing asset and brew fails closed on download, not silently).
|
||||
dl="$(mktemp -d)"
|
||||
fail=0
|
||||
for name in ao-darwin-arm64.tar.gz ao-darwin-amd64.tar.gz \
|
||||
ao-linux-arm64.tar.gz ao-linux-amd64.tar.gz; do
|
||||
echo "== parity (published asset): $name =="
|
||||
# A failed download is itself a divergence (missing/renamed
|
||||
# asset) and must reach the rollback path, not abort under set -e.
|
||||
if ! gh release download "$VERSION" --pattern "$name" --dir "$dl"; then
|
||||
echo "FAIL download: $name missing from release $VERSION" >&2
|
||||
fail=1
|
||||
continue
|
||||
fi
|
||||
scripts/check-release-parity.sh --tarball "$dl/$name" --tag "$VERSION" || fail=1
|
||||
done
|
||||
if [ "$fail" -ne 0 ]; then
|
||||
echo "parity divergence in PUBLISHED assets — rolling back release $VERSION" >&2
|
||||
if gh release delete "$VERSION" --yes; then
|
||||
echo "rollback complete: release $VERSION deleted" >&2
|
||||
else
|
||||
echo "ROLLBACK FAILED: release $VERSION is still served and DIVERGENT — delete it manually NOW: gh release delete $VERSION --yes" >&2
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Set release notes
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -23,6 +23,13 @@ archives:
|
||||
- id: ao
|
||||
name_template: ao-{{ .Os }}-{{ .Arch }}
|
||||
wrap_in_directory: false
|
||||
# Pack the repo's own docs at tag time (explicit, not GoReleaser defaults) so
|
||||
# the tarball README/LICENSE always match the tagged commit. Enforced by
|
||||
# scripts/check-release-parity.sh (tarball README sha256 == repo README).
|
||||
files:
|
||||
- README.md
|
||||
- LICENSE
|
||||
- CHANGELOG.md
|
||||
|
||||
checksum:
|
||||
name_template: checksums.txt
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
# typed: false
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Agentops < Formula
|
||||
desc "AI-assisted development workflow CLI"
|
||||
homepage "https://github.com/boshu2/agentops"
|
||||
version "2.31.0"
|
||||
license "MIT"
|
||||
|
||||
on_macos do
|
||||
if Hardware::CPU.arm?
|
||||
url "https://github.com/boshu2/agentops/releases/download/v#{version}/ao-darwin-arm64.tar.gz"
|
||||
sha256 "aad4483f0b3209a02d10abf412eb29e78475312061d05d6a71c0fb4224bb5056"
|
||||
else
|
||||
url "https://github.com/boshu2/agentops/releases/download/v#{version}/ao-darwin-amd64.tar.gz"
|
||||
sha256 "3ad4c80b1a5784c8bbbdb892feef8e10e695fae31f6f39ee0fa74c264086a091"
|
||||
end
|
||||
end
|
||||
|
||||
on_linux do
|
||||
if Hardware::CPU.arm?
|
||||
url "https://github.com/boshu2/agentops/releases/download/v#{version}/ao-linux-arm64.tar.gz"
|
||||
sha256 "37e674a6311004a1031cbb90886bc9aef75b70ced8e6d21b65ab8001788a1687"
|
||||
else
|
||||
url "https://github.com/boshu2/agentops/releases/download/v#{version}/ao-linux-amd64.tar.gz"
|
||||
sha256 "df8ff9a41d748552b7dfb67dc8e4e19628fdf0e51a04f315493305bab1554b7f"
|
||||
end
|
||||
end
|
||||
|
||||
def install
|
||||
bin.install "ao"
|
||||
end
|
||||
|
||||
def caveats
|
||||
<<~EOS
|
||||
AgentOps ao CLI installed!
|
||||
|
||||
Commands:
|
||||
ao forge transcript <path> # Extract from JSONL transcripts
|
||||
ao forge markdown <path> # Extract from markdown files
|
||||
ao ratchet record <type> # Record progress
|
||||
ao ratchet verify <epic> # Verify completion
|
||||
|
||||
For the Claude Code plugin, run:
|
||||
claude /plugin add boshu2/agentops
|
||||
EOS
|
||||
end
|
||||
|
||||
test do
|
||||
assert_match version.to_s, shell_output("#{bin}/ao --version")
|
||||
end
|
||||
end
|
||||
+16
-29
@@ -1,8 +1,20 @@
|
||||
# Homebrew Tap for AgentOps
|
||||
# Homebrew Tap for AgentOps — pointer only
|
||||
|
||||
Install the ao CLI via Homebrew.
|
||||
**This directory does not contain the live Homebrew formula.**
|
||||
|
||||
## Quick Install
|
||||
The real tap lives at **[github.com/boshu2/homebrew-agentops](https://github.com/boshu2/homebrew-agentops)**
|
||||
and its `Formula/agentops.rb` is generated automatically by **GoReleaser** on every
|
||||
release tag (see the `brews:` block in [`.goreleaser.yml`](../.goreleaser.yml) and the
|
||||
[Release Publisher workflow](../.github/workflows/release.yml)). The generated formula
|
||||
carries the correct version, `license "Apache-2.0"`, and per-artifact `sha256` sums.
|
||||
|
||||
Do **not** re-add a hand-written `Formula/agentops.rb` here. A checked-in formula
|
||||
drifts silently from the release — it once shipped `version "2.31.0"` +
|
||||
`license "MIT"` while the repo was 3.2.0 / Apache-2.0, so anyone browsing the repo
|
||||
read the wrong license. `scripts/check-release-parity.sh` guards against a
|
||||
reintroduced in-repo formula that disagrees with `LICENSE` or the release tag.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
brew tap boshu2/agentops https://github.com/boshu2/homebrew-agentops
|
||||
@@ -15,34 +27,9 @@ Or directly:
|
||||
brew install boshu2/agentops/agentops
|
||||
```
|
||||
|
||||
## Update to Latest
|
||||
## Update
|
||||
|
||||
```bash
|
||||
brew update && brew upgrade agentops
|
||||
ao version
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
ao forge transcript <path> # Extract from JSONL transcripts
|
||||
ao forge markdown <path> # Extract from markdown files
|
||||
ao ratchet record <type> # Record progress
|
||||
ao ratchet verify <epic> # Verify completion
|
||||
```
|
||||
|
||||
## Claude Code Plugin
|
||||
|
||||
The ao CLI integrates with the AgentOps Claude Code plugin:
|
||||
|
||||
```bash
|
||||
claude plugin add boshu2/agentops
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
To install from HEAD:
|
||||
|
||||
```bash
|
||||
brew install --HEAD agentops
|
||||
```
|
||||
|
||||
Executable
+234
@@ -0,0 +1,234 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# check-release-parity.sh — assert release-artifact parity so a built tarball,
|
||||
# the in-repo tree, and any tap formula cannot silently diverge (FU5, age-8duhj).
|
||||
#
|
||||
# Three checks:
|
||||
# (a) README parity — README.md inside the built tarball has the same sha256
|
||||
# as the repo README at the release ref. Catches the
|
||||
# v3.2.0 hazard where the tarball shipped a stale README.
|
||||
# (b) License parity — every in-repo Homebrew formula (homebrew-tap/**/*.rb)
|
||||
# declares `license "<L>"` matching the repo LICENSE
|
||||
# (Apache-2.0). Catches the vestigial dir that said MIT.
|
||||
# (c) Version parity — every in-repo formula's `version "<V>"` matches the
|
||||
# release tag. Catches a hand-edited formula frozen at an
|
||||
# old version (it once said 2.31.0 while the repo was 3.2.0).
|
||||
#
|
||||
# The canonical tap is generated by GoReleaser into boshu2/homebrew-agentops, so
|
||||
# in the normal case there is NO in-repo formula and (b)/(c) simply pass — the
|
||||
# gate then acts as a regression guard against anyone re-adding a stale formula.
|
||||
#
|
||||
# Runs in CI (post-build, in .github/workflows/release.yml) and locally.
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<'USAGE'
|
||||
Usage: scripts/check-release-parity.sh [options]
|
||||
|
||||
Assert parity between a built release tarball, the repo tree, and any in-repo
|
||||
Homebrew formula.
|
||||
|
||||
Options:
|
||||
--tarball PATH Built ao-<os>-<arch>.tar.gz to check README parity against.
|
||||
Omit to skip check (a) and run only formula checks.
|
||||
--ref GITREF Compare the tarball README against README.md at this git
|
||||
ref (e.g. a tag). Default: the working-tree README.md
|
||||
(correct in CI, where the checkout is already at the tag).
|
||||
--tag TAG Release tag (e.g. v3.2.0). Any in-repo formula version
|
||||
must equal it (leading 'v' ignored). Omit to skip check (c).
|
||||
--repo-root DIR Repo root to scan. Default: git toplevel, else the
|
||||
script's parent directory.
|
||||
--expected-license L Override the expected SPDX license. Default: derived from
|
||||
the repo LICENSE file (Apache-2.0).
|
||||
-h, --help Show this help.
|
||||
|
||||
Exit status: 0 = all parity checks pass; 1 = a divergence was found; 2 = usage error.
|
||||
USAGE
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo "check-release-parity: ERROR: $*" >&2
|
||||
}
|
||||
|
||||
TARBALL=""
|
||||
REF=""
|
||||
TAG=""
|
||||
REPO_ROOT=""
|
||||
EXPECTED_LICENSE=""
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--tarball)
|
||||
TARBALL="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--ref)
|
||||
REF="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--tag)
|
||||
TAG="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--repo-root)
|
||||
REPO_ROOT="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--expected-license)
|
||||
EXPECTED_LICENSE="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
fail "unknown argument: $1"
|
||||
usage >&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Resolve the repo root.
|
||||
if [[ -z "$REPO_ROOT" ]]; then
|
||||
if REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null)"; then
|
||||
:
|
||||
else
|
||||
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
fi
|
||||
fi
|
||||
if [[ ! -d "$REPO_ROOT" ]]; then
|
||||
fail "repo root does not exist: $REPO_ROOT"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# sha256 of stdin, printed as the bare hex digest (portable across sha256sum /
|
||||
# shasum -a 256).
|
||||
sha256_stdin() {
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum | awk '{print $1}'
|
||||
else
|
||||
shasum -a 256 | awk '{print $1}'
|
||||
fi
|
||||
}
|
||||
|
||||
# Derive the expected SPDX license from the repo LICENSE file when not overridden.
|
||||
if [[ -z "$EXPECTED_LICENSE" ]]; then
|
||||
license_file="$REPO_ROOT/LICENSE"
|
||||
if [[ -f "$license_file" ]]; then
|
||||
if grep -qi "Apache License" "$license_file" && grep -qi "Version 2.0" "$license_file"; then
|
||||
EXPECTED_LICENSE="Apache-2.0"
|
||||
elif grep -qi "MIT License" "$license_file"; then
|
||||
EXPECTED_LICENSE="MIT"
|
||||
else
|
||||
fail "could not derive license from $license_file; pass --expected-license"
|
||||
exit 2
|
||||
fi
|
||||
else
|
||||
fail "no LICENSE file at $license_file; pass --expected-license"
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
FAILURES=0
|
||||
CHECKS=0
|
||||
|
||||
# ── Check (a): tarball README sha256 == repo README sha256 ────────────────────
|
||||
if [[ -n "$TARBALL" ]]; then
|
||||
CHECKS=$((CHECKS + 1))
|
||||
if [[ ! -f "$TARBALL" ]]; then
|
||||
fail "tarball not found: $TARBALL"
|
||||
FAILURES=$((FAILURES + 1))
|
||||
else
|
||||
# README.md sits at the archive root (wrap_in_directory: false).
|
||||
tarball_readme_sha=""
|
||||
if ! tarball_readme_sha="$(tar -xzf "$TARBALL" -O README.md 2>/dev/null | sha256_stdin)"; then
|
||||
fail "tarball $TARBALL does not contain README.md at its root"
|
||||
FAILURES=$((FAILURES + 1))
|
||||
tarball_readme_sha=""
|
||||
fi
|
||||
|
||||
repo_readme_sha=""
|
||||
if [[ -n "$REF" ]]; then
|
||||
if ! repo_readme_sha="$(git -C "$REPO_ROOT" show "${REF}:README.md" 2>/dev/null | sha256_stdin)"; then
|
||||
fail "cannot read README.md at ref '$REF' in $REPO_ROOT"
|
||||
FAILURES=$((FAILURES + 1))
|
||||
repo_readme_sha=""
|
||||
fi
|
||||
else
|
||||
if [[ -f "$REPO_ROOT/README.md" ]]; then
|
||||
repo_readme_sha="$(sha256_stdin < "$REPO_ROOT/README.md")"
|
||||
else
|
||||
fail "no README.md at $REPO_ROOT/README.md"
|
||||
FAILURES=$((FAILURES + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "$tarball_readme_sha" && -n "$repo_readme_sha" ]]; then
|
||||
if [[ "$tarball_readme_sha" == "$repo_readme_sha" ]]; then
|
||||
echo "PASS README parity: tarball README matches repo README (${tarball_readme_sha:0:12})"
|
||||
else
|
||||
fail "README divergence: tarball=${tarball_readme_sha:0:12} repo=${repo_readme_sha:0:12} (stale README packed in $TARBALL)"
|
||||
FAILURES=$((FAILURES + 1))
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "SKIP README parity: no --tarball provided"
|
||||
fi
|
||||
|
||||
# ── Checks (b)/(c): in-repo formula license + version parity ──────────────────
|
||||
# Collect any Homebrew formula checked into the repo. The canonical formula is
|
||||
# generated externally by GoReleaser, so finding none here is the healthy state.
|
||||
formulae=()
|
||||
if [[ -d "$REPO_ROOT/homebrew-tap" ]]; then
|
||||
while IFS= read -r f; do
|
||||
formulae+=("$f")
|
||||
done < <(find "$REPO_ROOT/homebrew-tap" -type f -name '*.rb' 2>/dev/null | sort)
|
||||
fi
|
||||
|
||||
if [[ ${#formulae[@]} -eq 0 ]]; then
|
||||
echo "PASS formula parity: no in-repo Homebrew formula (generated externally by GoReleaser)"
|
||||
else
|
||||
tag_version="${TAG#v}"
|
||||
for formula in "${formulae[@]}"; do
|
||||
rel="${formula#"$REPO_ROOT"/}"
|
||||
|
||||
# (b) License.
|
||||
CHECKS=$((CHECKS + 1))
|
||||
formula_license="$(grep -oE 'license[[:space:]]+"[^"]+"' "$formula" | head -1 | sed -E 's/license[[:space:]]+"([^"]+)"/\1/')"
|
||||
if [[ -z "$formula_license" ]]; then
|
||||
fail "$rel declares no license string (expected \"$EXPECTED_LICENSE\")"
|
||||
FAILURES=$((FAILURES + 1))
|
||||
elif [[ "$formula_license" != "$EXPECTED_LICENSE" ]]; then
|
||||
fail "$rel license \"$formula_license\" != repo license \"$EXPECTED_LICENSE\""
|
||||
FAILURES=$((FAILURES + 1))
|
||||
else
|
||||
echo "PASS license parity: $rel license \"$formula_license\""
|
||||
fi
|
||||
|
||||
# (c) Version — only when a release tag is supplied.
|
||||
if [[ -n "$tag_version" ]]; then
|
||||
CHECKS=$((CHECKS + 1))
|
||||
formula_version="$(grep -oE 'version[[:space:]]+"[^"]+"' "$formula" | head -1 | sed -E 's/version[[:space:]]+"([^"]+)"/\1/')"
|
||||
if [[ -z "$formula_version" ]]; then
|
||||
fail "$rel declares no version string (expected \"$tag_version\")"
|
||||
FAILURES=$((FAILURES + 1))
|
||||
elif [[ "$formula_version" != "$tag_version" ]]; then
|
||||
fail "$rel version \"$formula_version\" != release tag \"$tag_version\""
|
||||
FAILURES=$((FAILURES + 1))
|
||||
else
|
||||
echo "PASS version parity: $rel version \"$formula_version\""
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "---"
|
||||
if [[ "$FAILURES" -gt 0 ]]; then
|
||||
echo "check-release-parity: FAIL ($FAILURES divergence(s) across $CHECKS check(s))" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "check-release-parity: OK ($CHECKS check(s) passed)"
|
||||
exit 0
|
||||
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env bats
|
||||
# Acceptance surface for scripts/check-release-parity.sh (FU5, age-8duhj).
|
||||
#
|
||||
# Given a release-tag build, When artifacts are produced, Then the gate fails on
|
||||
# README / license / version divergence between the tarball, an in-repo tap
|
||||
# formula, and the repo tree — and passes when they agree.
|
||||
#
|
||||
# Fixtures are built in tmp trees (a synthetic --repo-root with its own LICENSE
|
||||
# and README) so the checker never scans the real repo's homebrew-tap/.
|
||||
|
||||
setup() {
|
||||
REPO_ROOT="$(cd "$BATS_TEST_DIRNAME/../.." && pwd)"
|
||||
SCRIPT="$REPO_ROOT/scripts/check-release-parity.sh"
|
||||
FIX="$(mktemp -d "$BATS_TMPDIR/parity.XXXXXX")"
|
||||
|
||||
# Synthetic repo root with an Apache-2.0 LICENSE and a canonical README.
|
||||
printf ' Apache License\n Version 2.0, January 2004\n' > "$FIX/LICENSE"
|
||||
printf '# AgentOps\n\nOperating loop for coding agents — intent -> validated code.\n' > "$FIX/README.md"
|
||||
|
||||
# A "good" tarball packs the current repo README at its root (flat archive).
|
||||
mkdir -p "$FIX/pack"
|
||||
cp "$FIX/README.md" "$FIX/pack/README.md"
|
||||
tar -czf "$FIX/ao-good.tar.gz" -C "$FIX/pack" README.md
|
||||
|
||||
# A "stale" tarball packs the PREVIOUS README (the v3.2.0 hazard).
|
||||
printf '# AgentOps\n\nAutonomous code validation for coding agents.\n' > "$FIX/pack/README.md"
|
||||
tar -czf "$FIX/ao-stale.tar.gz" -C "$FIX/pack" README.md
|
||||
}
|
||||
|
||||
teardown() {
|
||||
[ -n "${FIX:-}" ] && [ -d "$FIX" ] && find "$FIX" -mindepth 0 -delete 2>/dev/null || true
|
||||
}
|
||||
|
||||
@test "checker exists and is executable" {
|
||||
[ -f "$SCRIPT" ]
|
||||
[ -x "$SCRIPT" ]
|
||||
}
|
||||
|
||||
@test "--help prints usage and exits 0" {
|
||||
run bash "$SCRIPT" --help
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"Assert parity"* ]]
|
||||
[[ "$output" == *"--tarball"* ]]
|
||||
}
|
||||
|
||||
@test "red: stale README tarball -> gate FAILS naming README divergence" {
|
||||
run bash "$SCRIPT" --tarball "$FIX/ao-stale.tar.gz" --repo-root "$FIX"
|
||||
[ "$status" -eq 1 ]
|
||||
[[ "$output" == *"README divergence"* ]]
|
||||
}
|
||||
|
||||
@test "green: matching README tarball -> gate PASSES" {
|
||||
run bash "$SCRIPT" --tarball "$FIX/ao-good.tar.gz" --repo-root "$FIX"
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"README parity"* ]]
|
||||
[[ "$output" == *"OK"* ]]
|
||||
}
|
||||
|
||||
@test "green: no in-repo formula -> formula parity passes (GoReleaser owns the tap)" {
|
||||
run bash "$SCRIPT" --tarball "$FIX/ao-good.tar.gz" --repo-root "$FIX" --tag v3.2.0
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"no in-repo Homebrew formula"* ]]
|
||||
}
|
||||
|
||||
@test "red: in-repo formula with wrong license (MIT vs Apache-2.0) -> gate FAILS" {
|
||||
mkdir -p "$FIX/homebrew-tap/Formula"
|
||||
cat > "$FIX/homebrew-tap/Formula/agentops.rb" <<'RB'
|
||||
class Agentops < Formula
|
||||
version "3.2.0"
|
||||
license "MIT"
|
||||
end
|
||||
RB
|
||||
run bash "$SCRIPT" --tarball "$FIX/ao-good.tar.gz" --repo-root "$FIX" --tag v3.2.0
|
||||
[ "$status" -eq 1 ]
|
||||
[[ "$output" == *'license "MIT" != repo license "Apache-2.0"'* ]]
|
||||
}
|
||||
|
||||
@test "red: in-repo formula with stale version -> gate FAILS on version" {
|
||||
mkdir -p "$FIX/homebrew-tap/Formula"
|
||||
cat > "$FIX/homebrew-tap/Formula/agentops.rb" <<'RB'
|
||||
class Agentops < Formula
|
||||
version "2.31.0"
|
||||
license "Apache-2.0"
|
||||
end
|
||||
RB
|
||||
run bash "$SCRIPT" --tarball "$FIX/ao-good.tar.gz" --repo-root "$FIX" --tag v3.2.0
|
||||
[ "$status" -eq 1 ]
|
||||
[[ "$output" == *'version "2.31.0" != release tag "3.2.0"'* ]]
|
||||
}
|
||||
|
||||
@test "green: in-repo formula matching license + version -> gate PASSES" {
|
||||
mkdir -p "$FIX/homebrew-tap/Formula"
|
||||
cat > "$FIX/homebrew-tap/Formula/agentops.rb" <<'RB'
|
||||
class Agentops < Formula
|
||||
version "3.2.0"
|
||||
license "Apache-2.0"
|
||||
end
|
||||
RB
|
||||
run bash "$SCRIPT" --tarball "$FIX/ao-good.tar.gz" --repo-root "$FIX" --tag v3.2.0
|
||||
[ "$status" -eq 0 ]
|
||||
[[ "$output" == *"license parity"* ]]
|
||||
[[ "$output" == *"version parity"* ]]
|
||||
}
|
||||
|
||||
@test "formula-only run (no --tarball) skips README check and still lints formula" {
|
||||
mkdir -p "$FIX/homebrew-tap/Formula"
|
||||
cat > "$FIX/homebrew-tap/Formula/agentops.rb" <<'RB'
|
||||
class Agentops < Formula
|
||||
version "3.2.0"
|
||||
license "MIT"
|
||||
end
|
||||
RB
|
||||
run bash "$SCRIPT" --repo-root "$FIX" --tag v3.2.0
|
||||
[ "$status" -eq 1 ]
|
||||
[[ "$output" == *"SKIP README parity"* ]]
|
||||
[[ "$output" == *'license "MIT"'* ]]
|
||||
}
|
||||
Reference in New Issue
Block a user