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
35 changes: 20 additions & 15 deletions .github/actions/setup-hermetic/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ runs:
# renovate: depName=forkcloser/hermetic
HERMETIC_VERSION: v0.2.3
HERMETIC_CHECKSUMS_SHA256: c7eb09712dc3d756bead96ae1286b53de275134d0012601ef37f57ec793f9431
# The job's own token, for `gh attestation verify` only, here and not
# exported: a read of GitHub's attestations API, before any
# branch-declared binary runs.
# The job's own token, for gh alone (the release download and
# `gh attestation verify`), here and not exported: reads of GitHub's
# API, before any branch-declared binary runs.
GH_TOKEN: ${{ github.token }}
run: |
# Pin the root explicitly: hermetic's own default differs per
Expand Down Expand Up @@ -71,16 +71,23 @@ runs:
echo "hermetic ${HERMETIC_VERSION} already in the root (the cache image)"
else
tmp="$(mktemp -d)"
base="https://github.com/forkcloser/hermetic/releases/download/${HERMETIC_VERSION}"
# Retries for transient runner failures. Windows curl (schannel)
# refuses a handshake when the CA's revocation server is unreachable
# (exit 35, seen repeatedly): best-effort revocation still rejects a
# known-revoked certificate, and the checksums below are the real
# guard. schannel-only flag, so windows-only.
revoke=()
[ "$RUNNER_OS" != Windows ] || revoke=(--ssl-revoke-best-effort)
curl --proto '=https' --tlsv1.2 -fsSL --retry 5 --retry-delay 3 --retry-all-errors "${revoke[@]}" \
-o "${tmp}/checksums.txt" "${base}/checksums.txt"
# Through the releases API with the job's token, by gh: the release
# page's download URL is an anonymous fetch, which GitHub throttles
# per runner IP under load (a 504 on every lane of a run, through
# curl's own retries), and a token sent there is routed, not checked.
# gh retries nothing itself; --clobber so a retry starts over. A
# pattern no asset matches is not an error to gh while another
# matches, so each file is checked for.
attempt=0
until gh release download "${HERMETIC_VERSION}" --repo forkcloser/hermetic --dir "${tmp}" --clobber \
--pattern checksums.txt --pattern "${asset}"; do
attempt=$((attempt + 1))
[ "$attempt" -lt 5 ] || { echo "::error::hermetic ${HERMETIC_VERSION}: checksums.txt or ${asset} could not be downloaded"; exit 1; }
sleep 3
done
for f in checksums.txt "${asset}"; do
[ -f "${tmp}/${f}" ] || { echo "::error::hermetic ${HERMETIC_VERSION} has no release asset ${f}"; exit 1; }
done
# No single digest tool exists everywhere: linux and windows git-bash
# ship coreutils sha256sum, macOS ships perl shasum. A mismatch names
# the computed digest and the size beside the expected one: a stale
Expand All @@ -101,8 +108,6 @@ runs:
echo "sha256 ok: $(basename "$file")"
}
verify_sha256 "${HERMETIC_CHECKSUMS_SHA256}" "${tmp}/checksums.txt"
curl --proto '=https' --tlsv1.2 -fsSL --retry 5 --retry-delay 3 --retry-all-errors "${revoke[@]}" \
-o "${tmp}/${asset}" "${base}/${asset}"
expected="$(awk -v a="$asset" '$2 == a {print $1}' "${tmp}/checksums.txt")"
[ -n "$expected" ] || { echo "::error::checksums.txt of hermetic ${HERMETIC_VERSION} does not list ${asset}"; exit 1; }
verify_sha256 "${expected}" "${tmp}/${asset}"
Expand Down
56 changes: 28 additions & 28 deletions .hermetic/aqua-checksums.json
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
{
"checksums": [
{
"id": "github_release/github.com/anchore/syft/v1.55.0/syft_1.55.0_darwin_arm64.tar.gz",
"checksum": "1217C258BD5EB91EF3189CF22A82E02F9CAC07E4CE934350F428E93AFF674625",
"id": "github_release/github.com/anchore/syft/v1.57.0/syft_1.57.0_darwin_arm64.tar.gz",
"checksum": "17012A5A110323BB1069E513A8665F1AE445905C56B4E3F9A9DF4F95C5BB6161",
"algorithm": "sha256"
},
{
"id": "github_release/github.com/anchore/syft/v1.55.0/syft_1.55.0_linux_amd64.tar.gz",
"checksum": "BB65249542DB5FEDEEB4D3F9B018B75E7264DBFBBB10486F044581A92F90490D",
"id": "github_release/github.com/anchore/syft/v1.57.0/syft_1.57.0_linux_amd64.tar.gz",
"checksum": "9C077A7D43029B3B13E98A8DB720661E700C4D58DB6352153A06395AE4A2A704",
"algorithm": "sha256"
},
{
"id": "github_release/github.com/anchore/syft/v1.55.0/syft_1.55.0_linux_arm64.tar.gz",
"checksum": "929BD163DB2D7CD2255D3BCB8967208079813D7B46B0C952F7B794D8E2C7D304",
"id": "github_release/github.com/anchore/syft/v1.57.0/syft_1.57.0_linux_arm64.tar.gz",
"checksum": "410CBFA0AE0F63246BC0057843760B1DE2833CD23919E025E368FD7681308CDB",
"algorithm": "sha256"
},
{
"id": "github_release/github.com/anchore/syft/v1.55.0/syft_1.55.0_windows_amd64.zip",
"checksum": "ADA4C9B93AF575F479CE80FCE6629897272A2D41F300A14BC49BACE020767CA2",
"id": "github_release/github.com/anchore/syft/v1.57.0/syft_1.57.0_windows_amd64.zip",
"checksum": "06E9663E55F7F38FF966710670FBE0763182C621F7AC2F191BCB209A6DFBD969",
"algorithm": "sha256"
},
{
Expand Down Expand Up @@ -66,28 +66,28 @@
"algorithm": "sha256"
},
{
"id": "github_release/github.com/farcloser/limen/v0.25.0/limen_0.25.0_darwin_arm64.tar.gz",
"checksum": "7D2179EEEA49466B7B8EF834C94AF27273CBA1886E798E36894B17A4DD81EAEF",
"id": "github_release/github.com/farcloser/limen/v0.26.0/limen_0.26.0_darwin_arm64.tar.gz",
"checksum": "6C013BBA485F3081BBA15342E7F6A9BB62B63E5D10D548DC2D425FACBE01CE87",
"algorithm": "sha256"
},
{
"id": "github_release/github.com/farcloser/limen/v0.25.0/limen_0.25.0_linux_amd64.tar.gz",
"checksum": "0739BC4C12D7754CB95DA24F4F6143F0DABCB498047A26AB96BD1F619C7F2D05",
"id": "github_release/github.com/farcloser/limen/v0.26.0/limen_0.26.0_linux_amd64.tar.gz",
"checksum": "C054388FC8BD99D049C2D342FEC6422AAD181FFA4B1520D2E789E16A90D8C8F6",
"algorithm": "sha256"
},
{
"id": "github_release/github.com/farcloser/limen/v0.25.0/limen_0.25.0_linux_arm64.tar.gz",
"checksum": "DD719BB5BCB231B42EA26172B90F91432AE2292EC88EA31752ECE1428A223242",
"id": "github_release/github.com/farcloser/limen/v0.26.0/limen_0.26.0_linux_arm64.tar.gz",
"checksum": "AF2541BCCE26DFEEC8B62F802327E65EAC6C054D8647D251370E4072F668FB5A",
"algorithm": "sha256"
},
{
"id": "github_release/github.com/farcloser/limen/v0.25.0/limen_0.25.0_windows_amd64.tar.gz",
"checksum": "826533D0573A75F61193F8C41B2156267BD9C2CBF709F3B9C0EC00BF24218675",
"id": "github_release/github.com/farcloser/limen/v0.26.0/limen_0.26.0_windows_amd64.tar.gz",
"checksum": "53F06B63777631B57F08FBDE8BD466AA456286D54701DFD04553AF06306C14A0",
"algorithm": "sha256"
},
{
"id": "github_release/github.com/farcloser/limen/v0.25.0/limen_0.25.0_windows_arm64.tar.gz",
"checksum": "0610256371832BF1616633F2A50787632CA35E8DBEED479E88B2FC17329DE100",
"id": "github_release/github.com/farcloser/limen/v0.26.0/limen_0.26.0_windows_arm64.tar.gz",
"checksum": "E83991B59F70E7DA0AB7A22FEAC93F6BF58768C683901C1B1D458BC4130E4879",
"algorithm": "sha256"
},
{
Expand Down Expand Up @@ -156,28 +156,28 @@
"algorithm": "sha256"
},
{
"id": "github_release/github.com/goreleaser/goreleaser/v2.19.0/goreleaser_Darwin_all.tar.gz",
"checksum": "21ADCEFF6E676EF63497FC129983F8C454E5A46EC0125B905CBA0F83E7879722",
"id": "github_release/github.com/goreleaser/goreleaser/v2.20.0/goreleaser_Darwin_all.tar.gz",
"checksum": "B4F0702BCB2AAD05BD13AF5AC69EC94D84270DCE59B917E7A8C446C974E29372",
"algorithm": "sha256"
},
{
"id": "github_release/github.com/goreleaser/goreleaser/v2.19.0/goreleaser_Linux_arm64.tar.gz",
"checksum": "EF33741B684C9F62D6A21E7A3C8B051F139EA7B1D301693B67CC819C46226D53",
"id": "github_release/github.com/goreleaser/goreleaser/v2.20.0/goreleaser_Linux_arm64.tar.gz",
"checksum": "2DADA0A6BBCD10F3A05228D98E77D25FB362EFB9E5BAB6362CF37E64C8A26CB9",
"algorithm": "sha256"
},
{
"id": "github_release/github.com/goreleaser/goreleaser/v2.19.0/goreleaser_Linux_x86_64.tar.gz",
"checksum": "EBC3194AD1D1B1787614405285A0039665CD4C5BD3305215A1B201600F90630B",
"id": "github_release/github.com/goreleaser/goreleaser/v2.20.0/goreleaser_Linux_x86_64.tar.gz",
"checksum": "D2483159E6007F814132CB56635AD30A70013DBEB813D6033A7E01ADF6AE108C",
"algorithm": "sha256"
},
{
"id": "github_release/github.com/goreleaser/goreleaser/v2.19.0/goreleaser_Windows_arm64.zip",
"checksum": "FF7A728EBDF86770D45C522F88B901E7FB3C06692B0D0C6A8A3A2C9BCF01B682",
"id": "github_release/github.com/goreleaser/goreleaser/v2.20.0/goreleaser_Windows_arm64.zip",
"checksum": "B7AE30D558DB74D67BD03E39D3309AABF47E1A18649EF4AC4429F329C357F496",
"algorithm": "sha256"
},
{
"id": "github_release/github.com/goreleaser/goreleaser/v2.19.0/goreleaser_Windows_x86_64.zip",
"checksum": "67807490E909A37F58EF40B67601896D8D4DA2411C9839221DAE55732C243FE9",
"id": "github_release/github.com/goreleaser/goreleaser/v2.20.0/goreleaser_Windows_x86_64.zip",
"checksum": "3C6A58F6941224A25EC28DE733554743E9B2517C40C76991EEF5474F8C1C2C1A",
"algorithm": "sha256"
},
{
Expand Down
2 changes: 1 addition & 1 deletion .hermetic/hermetic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ registries:
packages:
# The limen this repository runs, and with it every canonical file it
# writes: the one canonical pin kept here, where Renovate bumps it.
- name: farcloser/limen@v0.25.0 # renovate: depName=farcloser/limen
- name: farcloser/limen@v0.26.0 # renovate: depName=farcloser/limen
registry: local
# This repository's own tools, beyond limen's canonical set: yq for the
# issue-forms validation (.justfile).
Expand Down
4 changes: 2 additions & 2 deletions .limen/hermetic.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ packages:
- name: casey/just@1.59.0
- name: koalaman/shellcheck@v0.11.0
- name: lycheeverse/lychee@lychee-v0.24.2
- name: goreleaser/goreleaser@v2.19.0
- name: goreleaser/goreleaser@v2.20.0
- name: sigstore/cosign@v3.1.4
# The SBOM generator the release lane runs over every archive (book/releasing.md).
- name: anchore/syft@v1.55.0
- name: anchore/syft@v1.57.0
- name: jqlang/jq@jq-1.8.2
- name: cli/cli@v2.103.3
# --- spec tooling (local registry; see .limen/hermetic-registry.yaml) ---
Expand Down
25 changes: 22 additions & 3 deletions .limen/just/release.just
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,13 @@ release *args:
}
# A fourth segment is a fork's rebuild of the same upstream version
# (v10.6.1.2, book/forks.md): never a -suffix, which semver sorts before
# the release it rebuilds.
# the release it rebuilds. A rebuild carries no prerelease of its own:
# goreleaser reads no semver from it (--ci below), so a suffix would be
# published as a full release.
rebuild_tag_re='^v[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'
require_version_tag() {
if ! printf '%s' "$1" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?(-[0-9A-Za-z][0-9A-Za-z.-]*)?$'; then
if ! printf '%s' "$1" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z][0-9A-Za-z.-]*)?$' &&
! printf '%s' "$1" | grep -qE "$rebuild_tag_re"; then
echo "'$1' is not a version tag (vX.Y.Z, vX.Y.Z-prerelease, or a fork's rebuild vX.Y.Z.N)." >&2
exit 2
fi
Expand Down Expand Up @@ -154,7 +158,22 @@ release *args:
echo "HEAD carries no tag — this lane only runs on a tag push." >&2
exit 1
fi
exec goreleaser release --config .release-go.yaml --clean
# goreleaser refuses a tag that is not semver, and a fork's
# rebuild tag is not: --skip=validate is its one way past, and it
# also drops goreleaser's dirty-tree and tag-at-HEAD checks, so
# the two are made here first, on the tag this run was pushed for.
opts=()
tag="${GITHUB_REF_NAME:-}"
if printf '%s' "$tag" | grep -qE "$rebuild_tag_re"; then
require_clean
if ! git describe --exact-match --tags --match "$tag" HEAD >/dev/null 2>&1; then
echo "$tag is not on HEAD — this lane releases the tag its run was pushed for." >&2
exit 1
fi
export GORELEASER_CURRENT_TAG="$tag"
opts+=(--skip=validate)
fi
exec goreleaser release --config .release-go.yaml --clean ${opts[@]+"${opts[@]}"}
;;
--dry-run)
echo "dry runs are a local concern: use 'just do release --local --dry-run'." >&2
Expand Down
15 changes: 15 additions & 0 deletions .limen/renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"packageRules, golang/go, versioning: Go tags its releases go1.N.M, and the candidates golang/go offers are tags (it publishes no GitHub release). The regex managers' default versioning, semver-coerced, parses such a tag but calls every one unstable, since its stability check accepts only a bare or v-prefixed number; from a current version it holds unstable, Renovate lets through only a candidate with the same major, minor and patch, so no bump was ever proposed, silently. Regex versioning that carries the prefix parses the pin and the candidates alike, as lychee's does, and leaves the rc tags out by construction. Out of the aqua tools group: a toolchain patch is the standard-library fix the pin exists to receive without delay, in a pull request that names it.",
"packageRules, lychee: releases are tagged lychee-vX.Y.Z next to lychee-lib-vX.Y.Z and nightly; regex versioning that carries the prefix parses the pin and the candidates alike and excludes the others by construction.",
"packageRules, git-for-windows: releases are tagged vX.Y.Z.windows.N, and the N moves on its own (a Git for Windows rebuild of the same Git); a semver reading drops it and would never propose that bump. The build group carries it, and release candidates (vX.Y.Z-rcN.windows.N) fall outside the pattern.",
"packageRules, own releases, versioning: a fork's rebuild of the same upstream version is tagged with a fourth segment, vX.Y.Z.N (book/forks.md); the regex managers' default versioning, semver-coerced, reads v8.22.0.2 as 8.22.0 and so never proposes a rebuild (limen stayed on forkcloser/curl v8.22.0 through v8.22.0.1 and v8.22.0.2). The build group carries the fourth segment; absent, the release compares as the one its rebuilds follow, and a -suffix stays a prerelease. The rule claims a pin by its current value, a v-prefixed version, since a packageRule's versioning overrides the one a pins.yaml entry declares for itself: a release line of another shape (ossein-kernel's X.Y.Z-ossein.N, read by its own regex in the pin) keeps its own.",
"packageRules, runner images: the github-actions manager, which config:recommended enables, also proposes the runs-on images (ubuntu-24.04 to 26.04, macos-15 to 26) from the github-runners datasource. Those are product targets, not dependencies: the matrix is the set of platforms the code and the commands are proven on, set by the canonical ci.yaml seed and moved deliberately, on purpose, as a reviewed change. Off for that datasource; the actions themselves keep moving.",
"customManagers, pins.yaml: the artifacts a repository fetches by hand (a kernel tarball, a toolchain release, a source archive) live in one limen-owned file, each entry naming its own datasource and depName on its renovate: line (or `manual`, the one word, for a pin no datasource serves, which the regex below then leaves alone and a hand moves), optionally an extract-version regexp and a versioning scheme on the two lines after it, the version: line that moves, and for a commit pin (git-refs: the version is the branch) a commit: line after it, captured as the digest, so Renovate proposes the branch's new head. The digest follows in the same pull request: the checksum workflow runs `limen pins refresh`, which recomputes it through the verifier the entry declares. Watched here, once, for every repository; nobody writes a regex manager per pin.",
"commitBody: `just do lint commits` enforces DCO on every PR range, bot commits included.",
Expand Down Expand Up @@ -191,6 +192,20 @@
],
"versioning": "regex:^v(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)\\.windows\\.(?<build>\\d+)$"
},
{
"matchManagers": [
"custom.regex"
],
"matchDatasources": [
"github-releases",
"github-tags"
],
"matchDepNames": [
"/^(farcloser|forkcloser|mycophonic)/[^/]+$/"
],
"matchCurrentValue": "/^v\\d+\\.\\d+\\.\\d+(\\.\\d+)?(-[0-9A-Za-z.-]+)?$/",
"versioning": "regex:^v(?<major>\\d+)\\.(?<minor>\\d+)\\.(?<patch>\\d+)(?:\\.(?<build>\\d+))?(?:-(?<prerelease>[0-9A-Za-z.-]+))?$"
},
{
"matchDepNames": [
"golang/go"
Expand Down
17 changes: 11 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,22 @@ chapter; the procedure is limen's `skills/contribute`.
private repository is never armed: its pull request is bound for the human, who merges by
hand after approving. No review request, no review comments, no message at open.
- **Your worktree goes when its pull request has merged.** Once `git status` in it is clean
and its head is on `main`, remove it with `~/.claude/bin/farclauder worktree remove <path>`,
run as the whole Bash command: `git worktree remove` cannot finish inside the sandbox, and
the exclusion that runs farclauder outside it matches the call's text (the book's
and its head is on `main`, remove it with
`/Users/apostasie/.claude/bin/farclauder worktree remove <path>`, run as the whole Bash
command and by that absolute path: `git worktree remove` cannot finish inside the sandbox,
and the exclusion that runs farclauder outside it matches the call's text, which the `~`
form does not (the book's
[identity](https://github.com/farcloser/limen/blob/main/book/identity.md)).
- **A native stack** is reviewed and opened layer by layer the same way; the project
manager merges it from the top once every layer is approved, never from the middle. A
lower layer merged alone comes back rebased and signed by GitHub, which `lint commits`
rejects.
- **Not yours to do:** merge by hand, push to `main`, force-push a shared branch, tag a
release. A release waits for an empty queue: no tag while a pull request is open, a bot's
included, unless the human parks it by number for that tag (`PARKED_PRS`).
- **Not yours to do:** merge by hand, push to `main` (but for the empty `Birth` commit that
creates it on a new repository, the book's
[creating a repository](https://github.com/farcloser/limen/blob/main/book/github.md#creating-a-repository)),
force-push a shared branch, tag a release. A release waits for an empty queue: no tag
while a pull request is open, a bot's included, unless the human parks it by number for
that tag (`PARKED_PRS`).

## Scope

Expand Down
Loading