- Python 68.5%
- Shell 26.4%
- Dockerfile 5.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .agents/skills | ||
| .beads | ||
| .claude | ||
| .codex | ||
| .tekton | ||
| docs | ||
| hack | ||
| openspec/changes/add-release-runner-task | ||
| skills | ||
| .containerignore | ||
| .gitignore | ||
| .releaserc | ||
| AGENTS.md | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| Containerfile | ||
| LICENSE | ||
| OWNERS | ||
| README.md | ||
| renovate.json5 | ||
| skills-lock.json | ||
semantic-release
This is a containerized version of the semantic-release tool. Hopefully it will be maintained and released by the cyborgs!
podman run --rm -ti --userns=keep-id:uid=1001,gid=0 \
-e NPM_TOKEN=npm_xxx -eEDITOR="echo 'Created-by: semantic-release' > $1" \
-v $(pwd):/workspace:Z -v <path-to-gpg-home-dir>:/opt/app-root/src/.gnupg:Z -v <path-to-home-dot-ssh>:/opt/app-root/src/.ssh:Z \
git.b4mad.industries/agentic-forges/semantic-release:v1.8.0 --debug --no-ci
https://github.com/semantic-release/semantic-release/issues/3065 was helpful wrt gpg-signed tags.
To onboard another repository on the forge, see docs/enabling-a-repository.md.
Agent skills
Both procedures are packaged as agent skills under skills/:
| Skill | Covers |
|---|---|
b4mad-enable-release |
onboarding a repo — preconditions, .releaserc, dry run |
b4mad-cut-release |
cutting or dry-running a release, and diagnosing one |
Install them with npx skills. This
forge serves source archives from the API path, not the web /archive/ path,
so point the installer at the API:
npx skills add https://git.b4mad.industries/api/v1/repos/agentic-forges/semantic-release/archive/main.tar.gz \
--skill b4mad-enable-release,b4mad-cut-release
Name the skills explicitly — --skill '*' would also pull in the vendored
beads skill under .agents/skills/, which is not ours to redistribute.
Releasing a repository from the cluster
The runner is the Tekton Task in
.tekton/tasks/semantic-release.yaml. It
clones the target over SSH and pushes a GPG-signed tag as
b4mad-release-agent; the target supplies its own .releaserc and needs no CI
of its own.
Two ways to drive it:
hack/release.sh |
--repo/--ref/--dry-run, applies the Task, waits, prints the log and the released version. Start here |
.tekton/release-repo.yaml |
The same TaskRun as a manifest, for when you want to edit params by hand or read them in review |
hack/release-job.yaml is the pre-Tekton Job. Nothing
drives it any more; it is kept as the fallback for a cluster without Pipelines.
Retiring it is af-1da.
Prerequisites
One Secret in the namespace the run happens in — b4mad-forgejo today:
forgejo-agent-b4mad-release-agent
ssh-privatekey pushes the release commit and tag
gpg-privatekey signs them
token Forgejo API; only used if the target's .releaserc
lists @ribbon-studios/semantic-release-forgejo
It is created by forge-agents/create-forge-agent.py, not by anything here. The
ServiceAccount is pipeline. The forge's SSH host key fingerprint is pinned in
the Task as SHA256:LFo9B+TvN+sXwkUBW58RxU4QVyqk8rRaohW5UPFiuYw on port 2222;
the Task keyscans the forge and fails closed if the live key does not match,
so a genuine host key rotation is a deliberate edit, never a blind one.
Triggering
./hack/release.sh --repo <owner>/<repo> --ref main --dry-run # always first
./hack/release.sh --repo <owner>/<repo> --ref main
The script applies the Task before every run, so the cluster's copy cannot drift
behind the one in git. --dry-run computes the next version and renders the
notes without pushing; do that once before a repository's first real release,
always.
By hand, without the script:
oc -n b4mad-forgejo apply -f .tekton/tasks/semantic-release.yaml # once
# edit repo_slug in the template, then:
oc -n b4mad-forgejo create -f .tekton/release-repo.yaml
oc -n b4mad-forgejo get taskrun <name> -o jsonpath='{range .status.results[*]}{.name}={.value}{"\n"}{end}'
Results are released-version and released-ref. Both come back empty when
there was nothing to release — that is success, not failure. On a dry run
released-version is the computed version and released-ref is empty, because
no tag was created.
If a run sits Pending forever, check oc get events for FailedMount: a
missing or misnamed agent Secret does not fail the TaskRun, it just never
starts. The template's timeout: 30m bounds it.
Configuration
GnuPG
[https://github.com/isislovecruft/python-gnupg/issues/137#issuecomment-459043779] was a helpful hint, as parts of the
magic is configured in the ~/.gnupg/gpg.conf file.
$ cat ~/.gnupg/gpg.conf
no-greeting
pinentry-mode loopback
[...]
Environment Variables
GIT_AUTHOR_NAME="b4mad-release-bot"
GIT_AUTHOR_EMAIL="[email protected]"
GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"
GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"
Git
Within the container we have to configure /workspace/ to be a safe directory for git operations, so the Containerfile contains the following lines:
RUN git config --global --add safe.directory /workspace