feat: publish releases with this repository's own SDK code
There is no CI: the instance has no act_runner and none is planned, so releases are cut by hand. That makes `make check` the only thing standing between a mistake and the tracker, and it is one command: gofmt, vet, the suite with the cache defeated, `go mod verify`, a vendored build, and `kettle gen skills --check`. The last one is the invariant worth having — the plugin's SKILL.md command reference is generated from the binary's registry, so a flag that changed cannot ship with documentation that recommends the old one. `cli/cmd/release` publishes to Gitea using the same SDK the binary already vendors, which is a pleasing thing to be able to say: nothing third-party handles the artifacts. It is a second binary rather than a `kettle` subcommand on purpose — `kettle`'s command tree is what generates the plugin's skills, so a verb there ships to every operator, and publishing a release is build infrastructure. It is idempotent end to end: an existing release for the tag is reused, an asset of the same name is replaced rather than doubled, and a retried run converges instead of duplicating. `make release` refuses three things, each with its own message: a dirty working tree, a TAG that is not what `git describe` reports, and a tag the remote does not have. A release built from uncommitted code is unreproducible and nobody finds out until they need to reproduce it. `kettle version` reports the stamp, the toolchain and the VCS revision. The default is `dev`, and a hand build says so and means it — a binary out of somebody's working tree is not a release and must not claim to be one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -197,6 +197,14 @@ func StatusIs(err error, status int) bool {
|
||||
return errors.As(err, &apiErr) && apiErr.Status == status
|
||||
}
|
||||
|
||||
// Fail is fail, exported for the one caller outside this package that needs it.
|
||||
//
|
||||
// `cmd/release` builds its own SDK client — see its package doc for why a build
|
||||
// tool must not use this one — but a failure it reports has to name a status
|
||||
// and quote what the server said in the same words a push does. One function,
|
||||
// so the two spellings of "the tracker said no" cannot drift apart.
|
||||
func Fail(resp *sdk.Response, err error) error { return fail(resp, err) }
|
||||
|
||||
// fail turns one SDK call's (response, error) pair into this package's error.
|
||||
//
|
||||
// BOTH HALVES OR NEITHER. The SDK reads the response body to build its error
|
||||
|
||||
Reference in New Issue
Block a user