release-kit 0.2.1

A canonical release workflow: a technology-agnostic method, per-technology bindings, and the rk CLI that lands and serves them.
Documentation
#!/usr/bin/env sh
# Protect the release lines, for the projects that keep older lines: while a
# line is alive, release/* can be neither force-pushed nor deleted. Direct
# pushes stay allowed, because a cherry-pick lands on a line by push. This
# step is optional — a project with no older lines never runs it — and when a
# line dies its tags pin the commits, so the operator removes this ruleset
# together with the last line. Rerunning updates in place.
set -eu
: "${RK_REPO:?rk sets this; run this script through rk setup}"

name=release-lines
id="$(gh api "repos/$RK_REPO/rulesets" -q ".[] | select(.name == \"$name\") | .id" | head -n 1)"

if [ -n "$id" ]; then
  gh api -X PUT "repos/$RK_REPO/rulesets/$id" --input - >/dev/null
else
  gh api -X POST "repos/$RK_REPO/rulesets" --input - >/dev/null
fi <<JSON
{
  "name": "$name",
  "target": "branch",
  "enforcement": "active",
  "conditions": {
    "ref_name": { "include": ["refs/heads/release/*"], "exclude": [] }
  },
  "rules": [
    { "type": "deletion" },
    { "type": "non_fast_forward" }
  ]
}
JSON

echo "check: prints $name"
gh api "repos/$RK_REPO/rulesets" -q ".[] | select(.name == \"$name\") | .name"