mirror of
https://github.com/gastownhall/beads.git
synced 2026-09-14 20:17:24 +08:00
c3e600c940
* fix(pr-preflight): sample PR-gate health, not just base-branch runs (bd-msll) The base-branch health check reads gh run list --branch <base>, which only sees workflows that run on the base branch itself. A job that exists only in the PR workflow (pr.yml) never runs there, so preflight could report "base is green" while every fresh PR was red in that job, and pr-babysit mirrors preflight's verdict. Add a supplemental sample of recent completed pull_request-event runs across PRs: warn (or block under PR_PREFLIGHT_BLOCK_RED_BASE=1) only when at least 6 decisive runs span 3+ distinct branches and every one of them failed; stay silent otherwise (some success, too few samples, or an empty/unreadable sample). Agent-Signature: claude-sonnet-5-medium on behalf of matt wilkie * fix(pr-preflight): per-workflow PR-gate detection, warn-only, skip on red base Review found the lumped-sample design could never fire for a single broken pr.yml-only job: mixing all pull_request-event runs together diluted one red workflow against every other green PR workflow. Rework to group_by(workflowName) and flag any single workflow whose decisive runs (>=5, >=3 distinct headBranch values) are ALL failure-class, naming that workflow in the message. Also: drop the PR_PREFLIGHT_BLOCK_RED_BASE coupling entirely (a [block] line here matched neither pr-babysit's red-base nor transient-block patterns, which would have parked every merge lane and revoked the red-base merge exception — wiring this into the patrol is a separate change); skip the sample when the base branch is already red (that already explains PR redness and avoids the contradictory "base branch shows green" wording); add startup_failure to the failure-class regex to mirror pr-babysit's probe; and guard against gh exiting 0 with non-JSON output so a malformed sample stays silent instead of aborting under set -euo pipefail. Tests reworked for the per-workflow design: fake gh keys the PR-gate dispatch on the presence of --event pull_request; new cases cover a mixed-workflow sample (only the all-red workflow fires and is named), red-base-skips-sample, an unreadable/non-JSON sample, positive coverage of the base-branch dispatch via BASE_RUN_LIST, and the newest-run selection. Removed the PR_PREFLIGHT_BLOCK_RED_BASE=1 block-mode test for this detector. Agent-Signature: claude-sonnet-5-medium on behalf of matt wilkie * test(pr-preflight): pin the PR-gate detector's warn-only contract; harden jq guard; document Review round: a regression test asserts the detector never emits [block] even under PR_PREFLIGHT_BLOCK_RED_BASE=1 (downstream automation classifies unrecognized block lines as genuine merge blockers), the group_by jq gets an abort guard for valid-JSON-but-not-objects input, and scripts/README.md describes the new sample. Agent-Signature: claude-fable-5-high on behalf of matt wilkie * fix(pr-preflight): only diagnose the PR gate against a known-green base Codex review round: with zero decisive base runs preflight has just warned that base health is undetermined, and the broken-gate message's 'while the base branch shows green' clause would contradict it. Gate the sample on base_green_count > 0; fixture cases now supply a green base sample and a new case pins the undetermined-base silence. Agent-Signature: claude-fable-5-high on behalf of matt wilkie * fix(pr-preflight): group the PR-gate sample by workflowDatabaseId, not display name Codex review round 2: workflow display names are not unique and org/ruleset runs can lack one entirely, so name-grouping could merge distinct gates. Group by the stable id, keep the name for display. The repo-wide sample's base-branch conflation is documented as an accepted limitation of a warn-only supplemental detector. Agent-Signature: claude-fable-5-high on behalf of matt wilkie
272 lines
8.4 KiB
Markdown
272 lines
8.4 KiB
Markdown
# Beads Scripts
|
|
|
|
Utility scripts for maintaining the beads project.
|
|
|
|
## ci/
|
|
|
|
Repository-owned CI command wrappers. These scripts are the source of truth for
|
|
the target CI tiers; Make targets are aliases for local discoverability.
|
|
|
|
```bash
|
|
make ci-pr-core
|
|
make ci-pr-policy
|
|
make ci-pr-lint
|
|
make ci-package-mcp
|
|
make ci-package-npm
|
|
```
|
|
|
|
Each wrapper auto-detects the repository root, sources `.buildflags` when it
|
|
invokes Go in the default build mode, and records per-command timing through
|
|
`scripts/ci/lib/timing.sh`.
|
|
|
|
Broad Go test wrappers also source `scripts/ci/lib/test-env.sh`, which creates a
|
|
temporary HOME/XDG/Dolt root, isolates Git global/system config, clears runtime
|
|
Beads/Dolt environment variables, and sets `BEADS_TEST_SKIP=dolt` before tests
|
|
run. This keeps local `make test` and `make ci-pr-core` results comparable to
|
|
the fast PR-core contract even on shared agent hosts. Set
|
|
`BEADS_TEST_ENV_RUN_DOLT=1` only when intentionally running the Dolt-dependent
|
|
tests through these broad wrappers, or `BEADS_TEST_ENV_DISABLE=1` when debugging
|
|
against your real local configuration.
|
|
|
|
The broad Go wrappers also cap package and test parallelism to `4` by default
|
|
(`GO_TEST_PKG_PARALLEL` and `GO_TEST_PARALLEL`). This avoids turning high-core
|
|
shared hosts into a different test topology than GitHub Actions.
|
|
|
|
`make ci-pr-policy` includes `scripts/check-testing-short.sh`, which enforces
|
|
that `testing.Short()` is only used for runtime, stress, or large-fixture skips.
|
|
Use build tags, environment checks, or named wrappers for integration/e2e/API
|
|
boundaries.
|
|
|
|
Package gate wrappers validate publishable/package-adjacent surfaces:
|
|
|
|
- `make ci-package-mcp` builds or consumes a `bd` binary, puts it on `PATH` as
|
|
`bd`, then runs locked MCP package `uv sync`, Ruff, mypy, pytest, and build
|
|
checks.
|
|
- `make ci-package-npm` builds or consumes the native binary expected by
|
|
`npm-package/bin/bd`, runs the npm package test suite, and checks
|
|
`npm pack --dry-run`.
|
|
|
|
Set `BEADS_TEST_BD_BINARY=/path/to/bd` for MCP and npm package gates to reuse a
|
|
prebuilt candidate binary instead of rebuilding it inside the wrapper.
|
|
|
|
## pr-preflight.sh
|
|
|
|
Read-only PR safety check for agents and maintainers.
|
|
|
|
```bash
|
|
# Before implementing or opening a related PR
|
|
./scripts/pr-preflight.sh --search "topic keywords" --repo gastownhall/beads
|
|
|
|
# Before changing, closing, or merging an existing PR
|
|
./scripts/pr-preflight.sh 123 --repo gastownhall/beads
|
|
```
|
|
|
|
It reports contributor/fork status, draft/review/merge/check state, risky diff
|
|
signals such as `.beads/` changes or missing tests, and the required
|
|
contributor-protection next steps. It does not replace code review or local
|
|
validation.
|
|
|
|
Base-branch health is supplemented by a warn-only PR-gate sample: the last 60
|
|
completed `pull_request`-event runs, grouped per workflow. A single workflow
|
|
whose decisive runs (>= 5, across >= 3 distinct head branches) are all
|
|
failure-class is reported as a broken PR gate — the case where a job that
|
|
exists only in the PR workflow is red for every PR while the base branch shows
|
|
green. This detector never blocks (deliberately: automation classifies
|
|
unrecognized `[block]` lines as genuine merge blockers and would park merge
|
|
lanes on a false positive); it is skipped entirely while the base branch is
|
|
red.
|
|
|
|
## gh-body-lint
|
|
|
|
Lint Markdown files before posting them with `gh ... --body-file`.
|
|
|
|
```bash
|
|
./scripts/gh-body-lint body.md
|
|
./scripts/gh-body-lint --fix body.md
|
|
```
|
|
|
|
The lint catches literal `\n` sequences, which render poorly on GitHub, and
|
|
`GH#123` references, which do not auto-link like `#123` or `owner/repo#123`.
|
|
|
|
## release.sh (⭐ The Easy Button)
|
|
|
|
**One-command release** from version bump to local installation.
|
|
|
|
### Usage
|
|
|
|
```bash
|
|
# Full release (does everything)
|
|
./scripts/release.sh 0.9.3
|
|
|
|
# Preview what would happen
|
|
./scripts/release.sh 0.9.3 --dry-run
|
|
```
|
|
|
|
### What It Does
|
|
|
|
This master script automates the **entire release process**:
|
|
|
|
1. ✅ Stops running Dolt servers (avoids version conflicts)
|
|
2. ✅ Runs tests and linting
|
|
3. ✅ Bumps version in all files
|
|
4. ✅ Commits and pushes version bump
|
|
5. ✅ Creates and pushes git tag
|
|
6. ✅ Verifies or opens the Homebrew core formula PR
|
|
7. ✅ Upgrades local Homebrew installation
|
|
8. ✅ Verifies everything works
|
|
|
|
**After this script completes, your system is running the new version!**
|
|
|
|
### Examples
|
|
|
|
```bash
|
|
# Release version 0.9.3
|
|
./scripts/release.sh 0.9.3
|
|
|
|
# Preview a release (no changes made)
|
|
./scripts/release.sh 1.0.0 --dry-run
|
|
```
|
|
|
|
### Prerequisites
|
|
|
|
- Clean git working directory
|
|
- All changes committed
|
|
- golangci-lint installed
|
|
- Homebrew installed (for local upgrade)
|
|
- Push access to gastownhall/beads
|
|
|
|
### Output
|
|
|
|
The script provides colorful, step-by-step progress output:
|
|
- 🟨 Yellow: Current step
|
|
- 🟩 Green: Step completed
|
|
- 🟥 Red: Errors
|
|
- 🟦 Blue: Section headers
|
|
|
|
### What Happens Next
|
|
|
|
After the script finishes:
|
|
- GitHub Actions builds binaries for all platforms (~5 minutes)
|
|
- PyPI package is published automatically
|
|
- Homebrew core formula is verified or tracked through its canonical PR
|
|
- Users can `brew upgrade beads` to get the new version after Homebrew merges
|
|
- GitHub Release is created with binaries and changelog
|
|
|
|
---
|
|
|
|
## bump-version.sh
|
|
|
|
Bumps the version number across all beads components in a single command.
|
|
|
|
### Usage
|
|
|
|
```bash
|
|
# Show usage
|
|
./scripts/bump-version.sh
|
|
|
|
# Update versions (shows diff, no commit)
|
|
./scripts/bump-version.sh 0.9.3
|
|
|
|
# Update versions and auto-commit
|
|
./scripts/bump-version.sh 0.9.3 --commit
|
|
```
|
|
|
|
### What It Does
|
|
|
|
Updates version in all these files:
|
|
- `cmd/bd/version.go` - bd CLI version constant
|
|
- `plugins/beads/.claude-plugin/plugin.json` - Claude plugin version
|
|
- `plugins/beads/.codex-plugin/plugin.json` - Codex plugin version
|
|
- `.claude-plugin/marketplace.json` - Claude marketplace plugin version
|
|
- `integrations/beads-mcp/pyproject.toml` - MCP server version
|
|
- `README.md` - Alpha status version
|
|
- `PLUGIN.md` - Version requirements
|
|
|
|
### Features
|
|
|
|
- **Validates** semantic versioning format (MAJOR.MINOR.PATCH)
|
|
- **Verifies** all versions match after update
|
|
- **Shows** git diff of changes
|
|
- **Auto-commits** with standardized message (optional)
|
|
- **Cross-platform** compatible (macOS and Linux)
|
|
|
|
### Examples
|
|
|
|
```bash
|
|
# Bump to 0.9.3 and review changes
|
|
./scripts/bump-version.sh 0.9.3
|
|
# Review the diff, then manually commit
|
|
|
|
# Bump to 1.0.0 and auto-commit
|
|
./scripts/bump-version.sh 1.0.0 --commit
|
|
git push origin main
|
|
```
|
|
|
|
### Why This Script Exists
|
|
|
|
Previously, version bumps only updated `cmd/bd/version.go`, leaving other components out of sync. This script ensures all version numbers stay consistent across the project.
|
|
|
|
### Safety
|
|
|
|
- Checks for uncommitted changes before proceeding
|
|
- Refuses to auto-commit if there are existing uncommitted changes
|
|
- Validates version format before making any changes
|
|
- Verifies all versions match after update
|
|
- Shows diff for review before commit
|
|
|
|
---
|
|
|
|
## sign-windows.sh
|
|
|
|
Signs Windows executables with an Authenticode certificate using osslsigncode.
|
|
|
|
### Usage
|
|
|
|
```bash
|
|
# Sign a Windows executable
|
|
./scripts/sign-windows.sh path/to/bd.exe
|
|
|
|
# Environment variables required for signing:
|
|
export WINDOWS_SIGNING_CERT_PFX_BASE64="<base64-encoded-pfx>"
|
|
export WINDOWS_SIGNING_CERT_PASSWORD="<certificate-password>"
|
|
```
|
|
|
|
### What It Does
|
|
|
|
This script is called automatically by GoReleaser during the release process:
|
|
|
|
1. **Decodes** the PFX certificate from base64
|
|
2. **Signs** the Windows executable using osslsigncode
|
|
3. **Timestamps** the signature using DigiCert's RFC3161 server
|
|
4. **Replaces** the original binary with the signed version
|
|
5. **Verifies** the signature was applied correctly
|
|
|
|
### Prerequisites
|
|
|
|
- `osslsigncode` installed (`apt install osslsigncode` or `brew install osslsigncode`)
|
|
- EV code signing certificate exported as PFX file
|
|
- GitHub secrets configured:
|
|
- `WINDOWS_SIGNING_CERT_PFX_BASE64` - base64-encoded PFX file
|
|
- `WINDOWS_SIGNING_CERT_PASSWORD` - certificate password
|
|
|
|
### Graceful Degradation
|
|
|
|
If the signing secrets are not configured:
|
|
- The script prints a warning and exits successfully
|
|
- GoReleaser continues without signing
|
|
- The release proceeds with unsigned Windows binaries
|
|
|
|
This allows releases to work before a certificate is acquired.
|
|
|
|
### Why This Script Exists
|
|
|
|
Windows code signing helps reduce antivirus false positives that affect Go binaries.
|
|
Kaspersky and other AV software commonly flag unsigned Go executables as potentially
|
|
malicious due to heuristic detection. See `docs/reference/antivirus.md` for details.
|
|
|
|
---
|
|
|
|
## Future Scripts
|
|
|
|
Additional maintenance scripts may be added here as needed.
|