main is protected (enable_push: false, empty whitelist), so
@semantic-release/git's commit-back is rejected by the pre-receive
hook -- and it would be rejected *after* the tag was pushed, leaving a
tagged release the run then reports as failed. Found by trying to push
this branch to main.
Whitelisting the CI user was the alternative and is declined: it
weakens a protection someone set deliberately and lets a bot push to
main without the checks every human PR has to pass.
So the release page is the changelog. The changelog plugin now writes a
gitignored .release-notes.md, which exists only to carry the notes into
gitea-release.sh without interpolating them into a shell command, and
CHANGELOG.md is a signpost -- a file claiming to be a changelog while
silently never updating is worse than no file.
Tags are not protected, so the tag push is unaffected.
The config has been sitting in .releaserc.yml complete and uninvoked;
this is the workflow that runs it, and the one Gitea-shaped adaptation
it needs.
@semantic-release/github speaks GitHub's API, not Gitea's /api/v1, so
@semantic-release/exec calls scripts/gitea-release.sh instead. That
script reads the notes out of CHANGELOG.md rather than taking them as an
argument: release notes are rendered commit messages, so interpolating
the notes into a shell command would be an injection whose input is the
commit log.
The tag is pushed with a user PAT because Gitea does not start a
workflow from a ref pushed by a workflow's own token, and the three
publishing workflows are keyed on it.