5 Commits

Author SHA1 Message Date
k3nny 104167d7d2 docs(releaser): add documentation URL https://releaser.k3nny.fr
ci / vet, staticcheck, test, build (push) Successful in 3m12s
- README.md: add Documentation link below the release badge
- ROADMAP.md: update shipped docs-site entry with live URL
- docs/hugo.toml: set baseURL to the live site address

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 22:56:39 +02:00
k3nny 88ed87b095 build(ci): release v1.6.2 — staticcheck in task ci, SA4006 fix
ci / vet, staticcheck, test, build (push) Successful in 3m5s
ci / vet, staticcheck, test, build (pull_request) Failing after 12s
Add go tool staticcheck ./... to the task ci pipeline (between vet and
test), consistent with the Gitea CI workflow. Fix the SA4006 it surfaced
in TestLatestTagTagsIterFails where err from PlainOpen was assigned but
never read before being overwritten.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 21:47:39 +02:00
k3nny 6381a6440b build(ci): add staticcheck to CI pipeline; fix SA4006 in gitutil test
ci / vet, staticcheck, test, build (push) Successful in 3m5s
Add `go tool staticcheck ./...` between vet and test in the `task ci`
pipeline. Fix the SA4006 finding it surfaced: the PlainOpen error in
TestLatestTagTagsIterFails was assigned but never read (the nil check was
lost when the skip logic was simplified).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 21:45:49 +02:00
k3nny 4f933bf130 fix(ci): release v1.6.1 — skip chmod tests when running as root
ci / vet, staticcheck, test, build (push) Failing after 3m0s
Four tests relied on os.Chmod to force error paths but were failing in
Docker CI (golang:1.26-alpine runs as root, where chmod restrictions have
no effect). Added os.Getuid() == 0 skip guards to:
- internal/gradle: TestWriteVersionReadOnly
- internal/gitutil: TestLatestTagTagsIterFails (replaced broken skip logic
  that only fired if Chmod itself errored)
- cmd: TestInitConfigWriteFails, TestRunLatestTagFails

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 21:38:26 +02:00
k3nny a4cd00cc4d test(ci): skip chmod-dependent tests when running as root
ci / vet, staticcheck, test, build (push) Failing after 2m54s
Docker CI containers run as root by default (golang:1.26-alpine), where
os.Chmod has no effect and permission restrictions don't apply. Four
tests were failing because they relied on chmod to force error paths:

- gradle: TestWriteVersionReadOnly
- cmd:    TestInitConfigWriteFails, TestRunLatestTagFails
- gitutil: TestLatestTagTagsIterFails (had broken skip logic that only
  fired if Chmod itself errored, which never happens as root)

Replace all four with an upfront os.Getuid() == 0 check so they are
skipped cleanly in root environments and still run (and must pass) on
non-root local development.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 21:10:41 +02:00
8 changed files with 39 additions and 9 deletions
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
## [1.6.2] - 2026-07-11
### Changed
- **`task ci` now runs `go tool staticcheck ./...`** — runs between `go vet` and `go test`; matches the step already present in the Gitea CI workflow
### Fixed
- **SA4006 in `TestLatestTagTagsIterFails`** — `err` from `gogit.PlainOpen` was assigned then immediately overwritten without being read; added the missing `if err != nil { t.Fatalf(...) }` check
## [1.6.1] - 2026-07-11
### Fixed
- **CI root-permission failures** — four tests that used `os.Chmod` to force error paths were failing in Docker CI (which runs as root, where chmod has no enforcement effect); each now skips with `os.Getuid() == 0`; the gitutil test had broken skip logic that only fired if `Chmod` itself errored — replaced with the same upfront UID check
## [1.6.0] - 2026-07-11 ## [1.6.0] - 2026-07-11
### Added ### Added
+3 -1
View File
@@ -1,9 +1,11 @@
# releaser # releaser
![release](https://img.shields.io/badge/release-v1.6.0-blue.svg) ![release](https://img.shields.io/badge/release-v1.6.2-blue.svg)
A CI-friendly release automation tool for GitFlow workflows using Conventional Commits. A CI-friendly release automation tool for GitFlow workflows using Conventional Commits.
**[Documentation](https://releaser.k3nny.fr)**
## Problem ## Problem
Standard tools like `semantic-release` are designed for trunk-based development. In a GitFlow setup with versioned release branches (`release/1.1`, `release/1.2`), they either fail to respect the branch's version range or require brittle configuration. Standard tools like `semantic-release` are designed for trunk-based development. In a GitFlow setup with versioned release branches (`release/1.1`, `release/1.2`), they either fail to respect the branch's version range or require brittle configuration.
+1 -1
View File
@@ -74,7 +74,7 @@
- [x] ~~GitHub release support~~ — ✓ shipped v1.4.0 (`internal/ghclient`, `GITHUB_TOKEN` env, `github.token`/`github.repo` config; GitHub takes precedence over GitLab) - [x] ~~GitHub release support~~ — ✓ shipped v1.4.0 (`internal/ghclient`, `GITHUB_TOKEN` env, `github.token`/`github.repo` config; GitHub takes precedence over GitLab)
- [x] ~~SSH agent push~~ — ✓ shipped v1.4.0 (go-git `gitssh.NewSSHAgentAuth` for `git@`/`ssh://` remotes) - [x] ~~SSH agent push~~ — ✓ shipped v1.4.0 (go-git `gitssh.NewSSHAgentAuth` for `git@`/`ssh://` remotes)
- [x] ~~Configurable bump rules~~ — ✓ shipped v1.4.0 (`git.releasable_types` config; filter which commit types trigger a release) - [x] ~~Configurable bump rules~~ — ✓ shipped v1.4.0 (`git.releasable_types` config; filter which commit types trigger a release)
- [x] ~~Documentation site~~ — ✓ shipped v1.5.1 (Hugo + Geekdoc; installation, CLI reference, configuration, CI integration pages; deployed via Gitea CI to `gh-pages`) - [x] ~~Documentation site~~ — ✓ shipped v1.5.1 (Hugo + Geekdoc; installation, CLI reference, configuration, CI integration pages; live at https://releaser.k3nny.fr)
## v1.5 — Multi-module, Node.js, configurable bump rules ✅ ## v1.5 — Multi-module, Node.js, configurable bump rules ✅
+2 -1
View File
@@ -77,7 +77,7 @@ tasks:
- go test -run='^Fuzz' {{.PKG}} - go test -run='^Fuzz' {{.PKG}}
ci: ci:
desc: Full CI pipeline — tidy check, vet, test desc: Full CI pipeline — tidy check, vet, staticcheck, test
cmds: cmds:
- task: tidy - task: tidy
- | - |
@@ -86,6 +86,7 @@ tasks:
exit 1 exit 1
fi fi
- task: lint - task: lint
- go tool staticcheck ./...
- task: test - task: test
clean: clean:
+6
View File
@@ -852,6 +852,9 @@ func TestPrintVerboseConfigDirect(t *testing.T) {
// ── initConfig coverage ─────────────────────────────────────────────────────── // ── initConfig coverage ───────────────────────────────────────────────────────
func TestInitConfigWriteFails(t *testing.T) { func TestInitConfigWriteFails(t *testing.T) {
if os.Getuid() == 0 {
t.Skip("skipping: chmod restrictions do not apply when running as root")
}
dir := t.TempDir() dir := t.TempDir()
os.Chmod(dir, 0555) os.Chmod(dir, 0555)
defer os.Chmod(dir, 0755) defer os.Chmod(dir, 0755)
@@ -904,6 +907,9 @@ func TestRunWorkingTreeCheckFails(t *testing.T) {
} }
func TestRunLatestTagFails(t *testing.T) { func TestRunLatestTagFails(t *testing.T) {
if os.Getuid() == 0 {
t.Skip("skipping: chmod restrictions do not apply when running as root")
}
_, dir := setupRepo(t) _, dir := setupRepo(t)
addFile(t, dir, "x.go", "// fix") addFile(t, dir, "x.go", "// fix")
repo, _ := gogit.PlainOpen(dir) repo, _ := gogit.PlainOpen(dir)
+1 -1
View File
@@ -1,4 +1,4 @@
baseURL = "/" baseURL = "https://releaser.k3nny.fr/"
title = "releaser" title = "releaser"
theme = "geekdoc" theme = "geekdoc"
+7 -5
View File
@@ -752,19 +752,21 @@ func TestLatestTagTagsIterFails(t *testing.T) {
repo, dir := newTestRepo(t) repo, dir := newTestRepo(t)
addCommit(t, repo, dir, "fix: c1", "v1") addCommit(t, repo, dir, "fix: c1", "v1")
if os.Getuid() == 0 {
t.Skip("skipping: chmod restrictions do not apply when running as root")
}
// Make .git/refs/tags/ unreadable so that go-git's walkReferencesTree // Make .git/refs/tags/ unreadable so that go-git's walkReferencesTree
// returns EPERM when it tries to list the directory, triggering the // returns EPERM when it tries to list the directory, triggering the
// Tags() error path. Skip when running as root (chmod has no effect). // Tags() error path.
tagsDir := filepath.Join(dir, ".git", "refs", "tags") tagsDir := filepath.Join(dir, ".git", "refs", "tags")
if err := os.Chmod(tagsDir, 0000); err != nil { os.Chmod(tagsDir, 0000)
t.Skipf("cannot chmod %s: %v", tagsDir, err)
}
t.Cleanup(func() { os.Chmod(tagsDir, 0755) }) t.Cleanup(func() { os.Chmod(tagsDir, 0755) })
// Reopen so the filesystem storer holds no cached state. // Reopen so the filesystem storer holds no cached state.
repo2, err := gogit.PlainOpen(dir) repo2, err := gogit.PlainOpen(dir)
if err != nil { if err != nil {
t.Skipf("PlainOpen failed (likely running as root): %v", err) t.Fatalf("PlainOpen: %v", err)
} }
_, _, err = LatestTag(repo2, branch.Info{Major: 1, Minor: 2, TagPrefix: "v"}) _, _, err = LatestTag(repo2, branch.Info{Major: 1, Minor: 2, TagPrefix: "v"})
+3
View File
@@ -124,6 +124,9 @@ func TestWriteVersionNotFound(t *testing.T) {
} }
func TestWriteVersionReadOnly(t *testing.T) { func TestWriteVersionReadOnly(t *testing.T) {
if os.Getuid() == 0 {
t.Skip("skipping: chmod restrictions do not apply when running as root")
}
path := writeGradle(t, gradleKotlin) path := writeGradle(t, gradleKotlin)
os.Chmod(path, 0444) os.Chmod(path, 0444)
defer os.Chmod(path, 0644) defer os.Chmod(path, 0644)