ci: publish a release on every push to master
Release / release (push) Successful in 5s

Tags are what make `dsh plugin update` work at all: a plugin installed as a
bare `git+https://…/repo.git` is pinned to a commit in the profile's lockfile,
so with no tags there is nothing for an update to move to. This adds the
pipeline that creates them.

`.gitea/workflows/release.yml` runs on a push to master and on manual dispatch:
it reads the commit subjects since the last tag, derives the bump, prepends a
`CHANGELOG.md` section, commits and tags `vX.Y.Z`, and publishes the Gitea
release with those subjects as the body. The range with no tags yet is the
whole history, so the first release describes everything it contains.

The logic lives in `.gitea/scripts/release.sh` rather than in the YAML so it can
run — and be checked — without a runner: `npm run test:release` exercises it
(43 checks), `npm run release:plan` says whether HEAD would release, and
`npm run release:notes` prints the notes it would publish. `AGENTS.md` states
the subject conventions a contributor has to follow, because the subject is both
the version decision and the sentence a user reads in the release notes.

One property worth knowing: with no tags yet the version released is the one
`package.json` already declares — no bump is applied to a version that has never
been published — so the first tag is `v0.1.0`, and the bump rules take effect
from the second release onward.
This commit is contained in:
NotExpectedYet committed 2026-09-26 06:42:46 +01:00
1 parent 040c69b57d
commit 7261d46ee2
7 files changed
+724 -1

No files matched your search

+36
View File
@@ -352,6 +352,42 @@ Three things now guard against it:
If `status` reports `endpoint did NOT answer`, check `ollama ps` on that host
before assuming the plugin is at fault.
## Releases
`.gitea/workflows/release.yml` runs on every push to `master`: it works out the
range since the last tag, bumps `package.json`, prepends a `CHANGELOG.md`
section, commits and tags `vX.Y.Z`, then creates the Gitea release with the
commit subjects as the body.
The bug it fixes is not tidiness. Installed as a bare `git+https://…/repo.git`,
a plugin is pinned to a **commit** in the profile's lockfile, so with no tags
there is nothing for `dsh plugin update` to move to. Point the profile at
`#semver:^0.1.0` and the updates follow releases instead:
```jsonc
"dsh-recall": "git+https://git.notexpectedyet.com/Not-Expected-Yet/dsh-recall.git#semver:^0.1.0"
```
The bump is read from the commit subjects being released:
| in a commit subject | effect |
|---|---|
| `feat`, as its own word (`feat:`, `feat(x):`) | minor — `0.1.0` → `0.2.0` |
| `feat!:` / `fix(x)!:` / `BREAKING` | major — `0.1.0` → `1.0.0` |
| `fix:`, `docs:`, prose, anything else | patch — `0.1.0` → `0.1.1` |
| `[minor]` / `[major]` | force the bump when the subject cannot carry it |
| `[skip release]` | this push publishes nothing |
Only the **subject** line is read, and `feat` has to be a word — `Fix the feature
flag leak` is a patch, not a minor. With no tags yet, the version already in
`package.json` is what gets tagged, so the first release matches the code.
The logic lives in `.gitea/scripts/release.sh` so it runs without a runner:
`npm run test:release` exercises it — an empty range, a repository with no tags
yet, a `feat` that is only a word — `npm run release:plan` says whether the
current HEAD would release, and `npm run release:notes` prints the notes it
would publish.
## Development
```sh