Releases: adaouat/heraut
v1.0.0
🚀 Features
-
(app) Check runtime --env checks the env's effective platforms - (74ae0e1) by @bchatard
RuntimeCheck's Platforms section only ever read cfg.Release.Platforms,
soheraut check runtime --env <env>(and bareheraut check --env <env>) silently ignored an environment's release.platforms override.RuntimeCheck gains an env parameter and resolves the effective platform
list with the same replace semantics as buildReleasePipelineConfig and
hasEffectivePlatforms (T89): the env's release.platforms replaces the
root list wholesale when non-empty, otherwise the root list is checked.
internal/cmd/check.go reads the root --env flag and threads it through
runRuntimeCheck for both the bare check and check runtime commands.Roadmap:docs/tasks/roadmap.md -> T100 Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(config) Validate tag_pattern requires git-cliff generator - (bcd9467) by @bchatard
tag_pattern is a git-cliff-only field — communique and cocogitto
silently ignore it. Gate it in validateContentDriver the same way
tickets is gated, so a non-git-cliff generator paired with tag_pattern
now fails heraut check config with an actionable hint instead of being
silently dropped.The single check covers top-level changelog/release.notes and their
per-env equivalents, since MergeContentDriver (ADR-0019) already
resolves each per-env driver to its effective (generator, tag_pattern)
pair before validation runs.Roadmap:docs/tasks/roadmap.md -> T97 Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(scaffold) Warn before dropping unsupported settings on init update - (1a0f3f9) by @bchatard
The "Update it?" flow in
heraut initregenerates .heraut.yml from
ConfigToAnswers/GenerateYAML, which don't round-trip tickets,
remote_metadata, release.assets, per-platform base_url/draft/prerelease,
or per-env changelog/release overrides. Previously this loss was silent.Add scaffold.DroppedFields to detect any of these in the loaded config
and print a warning (with the affected YAML paths) before the wizard
runs, so the user can decide whether to continue. Export
config.DefaultBaseURL so the base_url check can ignore type defaults
filled in by normalizePlatforms.Roadmap:docs/tasks/roadmap.md -> T99 Co-Authored-By:Claude Fable 5 noreply@anthropic.com
🐛 Bug Fixes
-
(cmd) Unify --version override validation across release/changelog - (e269720) by @bchatard
heraut release rejected valid CalVer and pre-release --version overrides
via a SemVer-only regex, while heraut changelog --version validated
nothing. NewResolver already treats --version as an opaque string with
zero shape validation (StaticResolver), and spec 03 documents no shape
restriction.Drop the SemVer regex and add tagfmt.ValidateVersionOverride /
app.ValidateVersionOverride — non-empty, no whitespace, otherwise
format-agnostic (mirrors ValidateBuildID minus the "/" ban, since a full
tag override may contain one). Apply identically to both commands.Roadmap:docs/tasks/roadmap.md -> T90 Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(cmd) Align check/version validation, no-config, and exit codes - (d2406b6) by @bchatard
Three consistency fixes:
-
version next/current now run config.Validate before resolving, so
per-env misconfigs (e.g. promotion cycles) print the same path/hint
output as check config and exit Config, instead of surfacing as raw
resolver errors deep in the perenv promotion logic. -
Bare
heraut checkdegrades likecheck runtimewhen no config
file exists (warns and proceeds with cfg = nil) instead of hard
failing, so it works the same as running each subcommand
individually in a config-less directory. -
Bare
heraut checknow classifies its exit code by what failed:
Config if the config section had errors (even if runtime/cliff also
failed), Runtime otherwise.
Roadmap:docs/tasks/roadmap.md -> T98 Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
-
(cmd/release) Inherit root platforms when env release omits platforms - (1b5283e) by @bchatard
hasEffectivePlatforms returned false whenever an env's release: block
was non-nil but set no platforms (e.g. notes-only override), even
though buildReleasePipelineConfig correctly falls back to the root
platform list in that case. Align the guard with the builder's merge
semantics: env platforms replace root only when non-empty.Roadmap:docs/tasks/roadmap.md -> T89 Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(pipeline) Push only the resolved tag, not all local tags - (8e08976) by @bchatard
Both pipelines ran
git push origin --tags, which publishes every local
tag including stale or experimental ones. Add gitHelper.pushTag(tag) and
use it to push result.Tag explicitly. Align the changelog pipeline's
"Push tags" step naming with the release pipeline's "Push tag", and have
dry-run output name the exact tag being pushed.Roadmap:docs/tasks/roadmap.md -> T93 Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(platforms/gitlab) Inject token_env into release-time glab calls - (bd0bcb9) by @bchatard
CreateRelease and UploadAssets passed only hostEnv(), so a custom
token_env (or a self-hosted instance with its own token, ADR-0025's
motivating scenario) would passheraut check runtimebut fail at
glab release create/uploadtime. Mirror checkAPIAuth's and
GitHub's tokenEnvSlice()+hostEnv() composition.Roadmap:docs/tasks/roadmap.md -> T88 Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(versioning/perenv) Skip pre-release tags in semver-per-env BumpAuto - (938b911) by @bchatard
tagfmt.ParseVersion's {version} capture is a greedy
.+with no
pre-release filter, so a tag like dev/1.3.0-rc.1 parses to bare
"1.3.0-rc.1" unfiltered. Without versionsort.suffix, git can sort that
tag above dev/1.2.3, making it currentVersion — and BumpVersion's
strconv.Atoi on the "0-rc.1" patch segment fails, the same "invalid
patch" mode T92 fixed for plain semver.Export semver.IsBareVersion and apply it in perenv.resolveAuto's
shared tag-filter loop. The loop is shared with calver-per-env, but
IsBareVersion accepts any 3-part all-integer version and
calver.BumpFromDate already does its own per-tag skip, so this is a
no-op there.Roadmap:docs/tasks/roadmap.md -> T103 Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(versioning/semver) Anchor breaking-change bang to commit type prefix - (f4a8e9e) by @bchatard
isBreaking matched "!:" anywhere in the subject, so a fix commit whose
description happens to contain "!: " (e.g. "fix: handle the foo!: token")
triggered a spurious major bump. Anchor the bang to the conventional-commit
type/optional-scope prefix instead.Also recognize the hyphenated BREAKING-CHANGE: footer as a synonym of
BREAKING CHANGE:, per Conventional Commits 1.0.Roadmap:docs/tasks/roadmap.md -> T91 Co-Authored-By:Claude Fable 5 noreply@anthropic.com
-
(versioning/semver) Skip pre-release tags when resolving current version - (3e4b71a) by @bchatard
Without versionsort.suffix configured, git's default version:refname tag
sort orders a pre-release tag (e.g. v1.3.0-rc.1) above its release
(v1.2.3), so resolveAuto picked the pre-release as the current tag and
BumpVersion failed parsing its "-rc.1" suffix.resolveAuto now walks the sorted tags and picks the first whose bare form
is a plain MAJOR.MINOR.PATCH (new isBareVersion helper), mirroring the
CalVer resolver's skip-unparsable-tag pattern. Falls back to
initial_version if every matching tag is non-conforming. Documented in a
new "Pre-release tags" subsection of spec 04.Also adds T102 (spec 04's bump-determination table doesn't reflect T91's
anchored "!" / BREAKING-CHANGE: synonym) and T103 (semver-per-env's
BumpAuto may hit the same pre-release-tag issue via perenv.resolveAuto)
as follow-up roadmap tasks discovered during this work.Roadmap:docs/tasks/roadmap.md -> T92 Co-Authored-By:Claude Fable 5 noreply@anthropic.com
🚜 Refactor
-
(config) Extract shared EffectivePlatforms helper (T105) - (f9ec386) by @bchatard
internal/app/pipeline.go (buildReleasePipelineConfig), internal/cmd/release.go
(hasEffectivePlatforms, T89), and internal/app/check.go (RuntimeCheck, T100)
each independently implemented the same env/root release-platforms merge
rule. config.EffectivePlatforms is now the single implementation; the cmd
and app call sites delegate to it.Roadmap:docs/tasks/roadmap.md -> T105
-
Hygiene pass — drop T-id comments, dedupe iota, unify case - ([8413f47](https://github.com/adaouat/he...
v0.31.0
🚀 Features
-
(app) One heraut check runtime Platforms row per configured entry - (6bdc4b4) by @bchatard
RuntimeCheck now dispatches one Platforms row per release.platforms
entry, labeled by the entry's configured name, running each entry's
full Check() (binary + token + project/repository + API auth). With
no platforms configured, falls back to a binary-only probe of glab
and gh. Removes configuredPlatforms/findPlatformCfg, which assumed at
most one entry per platform type.Roadmap:docs/tasks/roadmap.md → T86
-
(config) Require unique platform name, allow self-hosted base_url - (2d6f2f6) by @bchatard
Adds a required
namefield to release.platforms entries (unique per
list scope) and lifts ADR-0020's "self-hosted hosts are not yet
supported" gate on base_url — both are prerequisites for publishing to
two instances of the same platform type (ADR-0025).Roadmap:docs/tasks/roadmap.md → T83
-
(platforms/github) Support self-hosted instances via GH_HOST - (c113508) by @bchatard
Name() now returns the configured platform name, ReleaseURL() honors
base_url, and CreateRelease/UploadAssets/Check inject GH_HOST and
GH_ENTERPRISE_TOKEN when base_url targets a non-default (GHES) host.
Actions-token autologin is skipped for self-hosted instances in favor
of the configured token.Roadmap:docs/tasks/roadmap.md → T85
-
(platforms/gitlab) Support self-hosted instances via GITLAB_HOST - (3bfdb06) by @bchatard
Name() now returns the configured platform name, ReleaseURL() honors
base_url, and CreateRelease/UploadAssets/Check inject GITLAB_HOST when
base_url targets a non-default host. CI autologin is skipped for
self-hosted instances in favor of the configured token.Roadmap:docs/tasks/roadmap.md → T84
📚 Documentation
-
(adr) Add ADR-0025, supersede ADR-0020 (multi-instance platforms) - (b3ae621) by @bchatard
ADR-0025 documents the lifted base_url gate, per-platform CLI host
targeting (GH_HOST/GITLAB_HOST/GH_ENTERPRISE_TOKEN), the required
unique name field, and the restructured heraut check runtime
Platforms section delivered by T83-T86. Spec 05 gains the self-hosted
/ multi-instance subsection and the name field in both platform
examples.Roadmap:docs/tasks/roadmap.md → T87
-
(app) Clarify Platforms section dispatch order in RuntimeCheck - (e47b250) by @bchatard
The previous comment described the old fixed glab→gh dispatch order,
which T86 replaced with one row per configured release.platforms entry
(falling back to the binary-only probe only when none are configured). -
(plans) Add multi-instance platforms implementation plan - (4f9eb70) by @bchatard
Implementation plan for T83-T87 (ADR-0025, multi-instance
same-platform releases), executed via subagent-driven development.Roadmap:docs/tasks/roadmap.md → T83-T87
-
Design spec for multi-instance same-platform releases - (2b3e99b) by @bchatard
Adds a future-ideas entry and design spec covering name-based platform
disambiguation, lifting the ADR-0020 base_url gate, and per-invocation
GH_HOST/GITLAB_HOST targeting for self-hosted instances.
🎨 Styling
-
(app) Drop unneeded loop variable copy in check.go - (60b3e9d) by @bchatard
Go 1.22+ gives each for-range iteration its own variable, so the
bin := bin copy added by T86 was redundant.
Commit Statistics
- 9 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 9 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
v0.30.2
🐛 Bug Fixes
-
(deps) Bump forge to v0.16.0 - (56d38f7) by @bchatard
Pulls in forge's whatsnew rendering fixes: dropped glamour's
terminal-querying "auto" style (which fell back to raw markdown when
the terminal didn't answer), added $PAGER support, and fixed a
double-print bug when the pager exits non-zero.
Commit Statistics
- 1 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 1 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
- 1 day(s) passed between releases.
v0.30.1
🎨 Styling
-
Gofmt -s on calver parser_test - (e5ec535) by @bchatard
Struct-field alignment that gofmt -s wants but golangci-lint (CI) doesn't enforce —
the lone pre-existing go_fmt failure surfaced by 'hk check --all', a prerequisite for
adding the hk lint gate to CI.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
⚙️ Miscellaneous Tasks
-
Run the full hk linter set in CI (hadolint, actionlint, typos, …) - (0906de5) by @bchatard
The reusable ci job only runs golangci-lint; hk's other linters (hadolint,
actionlint, yamlfmt, typos, pkl, go fmt) were enforced only by the local pre-commit
hook (staged files, bypassable). Add an hk job running 'hk check --all --check
--skip-step golangci_lint' so they're enforced server-side. hk's per-step file
selection scopes each linter — hadolint only touches the Dockerfile, so it runs only
when relevant without a fragile required-check path filter.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
Fix shellcheck findings in release.yml run blocks - (c8cb125) by @bchatard
The new hk CI job (actionlint -> shellcheck) flagged unquoted variable
expansions in release.yml. Quote $FRESH_BIN, $GITHUB_ENV, and
$GITHUB_OUTPUT (SC2086). The imagetools create command intentionally
relies on word splitting / globbing for multiple -t tags and digest
files, so suppress SC2046 there with an explanatory comment.Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
Commit Statistics
- 3 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 3 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
v0.30.0
🚀 Features
-
(app) Propagate tickets config onto content drivers - (10410fa) by @bchatard
withEnvDerivations now carries cfg.Tickets onto the changelog/release-notes driver
clones (the same clone point as remote_metadata), so the gitcliff generator can
inject link_parsers. Part of T80.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(config) Add tickets field for issue-tracker links - (770c318) by @bchatard
Top-level tickets list ([]Ticket{Pattern, URL}) parsed from .heraut.yml, plus the
programmatic ContentDriver.Tickets carrier the app layer will populate. Part of T79.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(config) Validate tickets (regex, {ticket} url, git-cliff only) - (a159801) by @bchatard
validateTickets:each pattern compiles as a regex, each url is an absolute http(s)
URL containing {ticket}, and tickets require the git-cliff generator (the only one
with a link mechanism). Part of T79. Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com -
(config) Add tickets to schema + sample + fixtures - (0de6706) by @bchatard
Expose the tickets array in schema.json (pattern + url, both required), document
it in docs/heraut.sample.yml, and add valid + invalid schema fixtures (the invalid
one omits the required url). Part of T82.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(generators/gitcliff) Inject ticket link_parsers into effective config - (cc1925d) by @bchatard
effectiveConfig now chains injectLinkParsers after the heading postprocessor: each
ticket becomes a git-cliff { pattern, href } entry — pattern wrapped in a capture
group only when it has none (so {ticket}->$1 is the URL value), appended to any
existing [git].link_parsers. Part of T80.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(generators/gitcliff) Render ticket links in changelog and release notes - (98f83e1) by @bchatard
Both print_commit macros append commit.links after the PR segment as
( TICKET ). Verified against the real git-cliff: subject and footer (Refs:)
tickets both render with clean whitespace, location-independent. Part of T81.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
📚 Documentation
-
(plans) Add ticket-linking design spec - (6dee113) by @bchatard
Approved brainstorming design: first-class .heraut.yml ticket linking via a
top-level tickets list, injected into git-cliff's link_parsers (location-
independent — subject/body/footer), rendered in both changelog and release notes.
git-cliff only; append-only; {ticket} maps to the first capture group (or full
match) so label vs URL value can differ (e.g. GH-123 → /issues/123).Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(plans) Add ticket-linking implementation plan - (d33f307) by @bchatard
Seven TDD tasks (config field, validation, link_parsers injection, driver
propagation, both templates, schema/sample/fixtures, ADR/spec/roadmap) for T79,
each with failing test, implementation, and commit steps.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(roadmap) Add Phase 15 — ticket linking (T79–T82) - (dfc44c5) by @bchatard
New phase tracking the ticket-linking feature: config surface + validation (T79),
link_parsers injection + driver propagation (T80), template rendering (T81), and
schema/sample/ADR/spec (T82).Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
ADR-0024 ticket linking; document tickets; complete T79–T82 - (485c07a) by @bchatard
Record the link_parsers-over-commit_preprocessors decision (ADR-0024), document the
tickets config in spec 02, and flip Phase 15 (T79–T82) to done with completion notes.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
Commit Statistics
- 10 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 10 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
v0.29.0
🚀 Features
-
(cmd) Add --build to heraut release for build-id release flows - (280b29d) by @bchatard
Mirror heraut changelog --build: --build requires --version, the value is
validated via app.ValidateBuildID, and it is passed to NewResolver, which renders
{build} into the tag and returns a StaticResolver. The release pipeline consumes
result.Tag unchanged, so no pipeline/resolver change is needed — the build path
already existed (deferred from T52). Build-id teams can now run a full release
(changelog -> tag -> publish) per CI build. release-per-build is allowed freely:
passing both --version and --build is already a deliberate, scripted opt-in.Closes T57.
Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
🐛 Bug Fixes
-
(generators/gitcliff) Render New Contributors from any platform's remote - (316ce84) by @bchatard
The embedded release-notes template only read gitlab.contributors, so non-GitLab
repos never rendered the New Contributors section. Extract a print_contributors
macro and call it once over the first-time contributors concat'd across all five
remote namespaces (gitlab/github/gitea/bitbucket/azure_devops). The single call
over a merged list keeps git-cliff's proven single-block whitespace — verified
against the real CLI for the empty, single-platform, and multi-platform cases (no
blank-line regression).Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
📚 Documentation
-
(roadmap) Mark T68 done (checkbox lag; work landed in ADR-0021) - (7061e89) by @bchatard
T68's decision and PoC were completed and documented in its Done note (the
context-injection shape resolved in ADR-0021, dependents T69/T71a/T71b already
done) — only the heading checkbox was never flipped. Flip it. T57 is now the
single open roadmap task.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(roadmap) Complete T57 (heraut release --build) - (d86c09b) by @bchatard
Flip T57 to done with a completion note: mirrored changelog --build, no
pipeline change (resolver already handled build), release-per-build allowed
freely. Roadmap is now fully resolved — no open tasks.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(specs) Document heraut release --build (T57) - (3e8e37a) by @bchatard
Flip the {build} support table — heraut release --build is now supported, not
changelog-only — add the release example, the --build flag to the release command
reference, and note that release-per-build (one platform release per build) is
intentional and unguarded.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
🎨 Styling
-
(generators/gitcliff) Drop redundant version heading from release notes - (c977f61) by @bchatard
Release notes are attached to a GitHub/GitLab release whose header already shows
the tag/version and date, so the '## [version] - date' line in the body was pure
duplication. Drop it (the changelog template keeps its heading — that file
accumulates every release). Also pack the macro definitions (whitespace-only).
Verified against the real git-cliff: config accepted, contributors render across
all platforms, no output regression (one leading blank line is git-cliff
structural with an empty header, and invisible on the rendered release page).Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
⚙️ Miscellaneous Tasks
-
Keep CHANGELOG.md in Docker build context for the whatsnew embed - (acac7b6) by @bchatard
changelog.go embeds CHANGELOG.md into the binary (//go:embed, 09fe57c) for the
whatsnew offline fallback, so the Dockerfile's COPY . . + go build needs the file
present. The .dockerignore '*.md' rule was excluding it, breaking the image build
with 'pattern CHANGELOG.md: no matching files found'. Add a !CHANGELOG.md
exception; other .md files stay ignored.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
Commit Statistics
- 7 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 7 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
- 1 day(s) passed between releases.
v0.28.0
[0.28.0] - 2026-06-10
🚀 Features
-
(whatsnew) Embed CHANGELOG.md as the offline fallback - (09fe57c) by @bchatard
Adds a root package embedding CHANGELOG.md into a string (the embed must live
at the repo root to reach the file) and passes it to WhatsNewConfig.Changelog,
so whatsnew renders the bundled changelog when GitHub is unreachable and the
cache is cold (forge ADR-0012 tier D).Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
💼 Other
-
(deps) Bump forge to v0.15.0 - (93cee93) by @bchatard
Brings WhatsNewConfig.Changelog (forge ADR-0012 tier D) for the embedded
changelog offline fallback.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
Commit Statistics
- 2 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 2 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
v0.27.0
[0.27.0] - 2026-06-10
🚀 Features
-
(cmd) Add whatsnew command, adopt forge's shared hint wiring - (9457530) by @bchatard
Registers updatecheck.WhatsNewCommand (heraut whatsnew shows the release-note
span newer than the running build), and collapses the update-hint PostRun to a
single updatecheck.Hinter{…}.PostRun() using the shared CacheFile("heraut") —
dropping the hand-rolled timeout/cache-path block (forge M11/ADR-0012).Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
💼 Other
-
(deps) Bump forge to v0.13.0 - (6a4f278) by @bchatard
Brings updatecheck.WhatsNewCommand (forge ADR-0012 tier C) for the whatsnew
wiring, plus the tier A changelog pointer in the upgrade hint.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(deps) Bump forge to v0.14.0 - (b36f93a) by @bchatard
Brings updatecheck.CacheFile + Hinter.PostRun (forge M11) for the shared
update-hint wiring, alongside WhatsNewCommand for the whatsnew command.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
Commit Statistics
- 3 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 3 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
v0.26.0
[0.26.0] - 2026-06-10
🚀 Features
-
(app) Propagate remote_metadata policy + report cliff degrade - (a465871) by @bchatard
withEnvDerivations now carries the top-level remote_metadata policy onto the
changelog/release-notes drivers so the pipeline generators honour it. CheckCliff
gains the policy (applied to a driver copy, never mutating the caller's) and
returns whether it degraded to --offline; heraut check surfaces that in the
cliff detail line (valid → valid (offline — remote metadata unavailable)).
Part of T78.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(cmd) Add --offline flag forcing remote_metadata: disabled - (2dffbe0) by @bchatard
Persistent --offline flag overrides the configured remote_metadata policy to
disabled for a single run (no remote PR/MR metadata API calls). Wired into
release, changelog, and the check / check cliff commands via applyOfflineOverride
after config load. Part of T78.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(config) Add remote_metadata policy field + validation - (b9a467c) by @bchatard
Top-level remote_metadata governs whether content generators fetch PR/MR
metadata (author handle, PR number) from the platform API to enrich
changelog/release-notes: required | optional | disabled, empty resolving to
optional. Enum-validated. A programmatic ContentDriver.RemoteMetadata field
carries the effective policy onto each driver for the generator to honour
(set by the app layer, mirroring HeadingVersionPattern). Part of T78.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(config) Add remote_metadata to schema.json + sample + fixtures - (7aa259f) by @bchatard
Expose the remote_metadata enum (required | optional | disabled, default
optional) in schema.json for IDE validation, document it in docs/heraut.sample.yml,
and add valid + invalid schema fixtures (the invalid one asserts the enum is
enforced). Keeps the schema/sample/field in sync per the config rules. Part of T78.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(generators/gitcliff) Honor remote_metadata policy via --offline - (e14c020) by @bchatard
git-cliff fetches PR metadata (and panics on failure) whenever the templates
reference commit.remote.*. Route Generate and CheckCliff through a policy-aware
runCliff: 'disabled' always passes --offline; 'required' never does (a remote
failure stays fatal); 'optional' (default) tries online then retries with
--offline on any failure, exposing Degraded() so callers can warn. If the
offline retry also fails the original online error surfaces, so a genuine
config error still bubbles up. Part of T78.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(pipeline) Surface remote-metadata degrade as a step sub-result - (7c682e1) by @bchatard
When a generator falls back to --offline because the remote metadata fetch
failed (remote_metadata: optional), the changelog/release-notes step now carries
a 'remote metadata unavailable — PR authors/numbers omitted' sub-result, so the
omission is visible during release/changelog runs. Generators report it via an
optional Degraded() interface the pipeline type-asserts, keeping the pipeline
decoupled from the concrete generator. Part of T78.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
📚 Documentation
-
(adr) Add ADR-0023 remote-metadata policy; complete roadmap T78 - (fb22f0a) by @bchatard
Record the remote_metadata decision (top-level tri-state, default optional,
backed by git-cliff --offline, retry-on-failure for optional, --offline flag) and
its reconciliation with ADR-0022. Index it in the ADR README and flip T78 to done
with a completion note.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(adr) Record why the CLI override is boolean --offline (ADR-0023) - (e93cb06) by @bchatard
Capture the decision to keep --offline as a boolean escape hatch rather than a
--remote-metadata mirror of the config key (git-cliff precedent + heraut's
runtime-flag convention + YAGNI), so it is not re-litigated later.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
-
(roadmap) Add T78 — remote_metadata policy for git-cliff enrichment - (9680617) by @bchatard
Captures the durable opt-out for git-cliff's remote-metadata fetch: a
top-level tri-state policy (required | optional | disabled, default optional)
governing both changelog and release-notes generation, backed by git-cliff's
--offline flag. The optional default degrades + warns on fetch failure, fixing
the tokenless-panic residual out of the box. Follows the ci: GITHUB_TOKEN patch
that authenticates the fetch in CI.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
⚙️ Miscellaneous Tasks
-
Authenticate git-cliff GitHub API calls in release workflow - (cc8f128) by @bchatard
heraut's changelog/release-notes generation shells out to git-cliff, which
fetches PR metadata from the GitHub API to populate commit.remote.username and
commit.remote.pr_number. git-cliff reads GITHUB_TOKEN, not GH_TOKEN (which only
gh/glab consume), so the Preflight and Release steps were calling the API
unauthenticated — hitting GitHub's 60/hr shared-IP rate limit and panicking with
a 403 (exit 101). Export GITHUB_TOKEN to both steps so the calls authenticate
against the 1000/hr limit.Co-Authored-By:Claude Opus 4.8 noreply@anthropic.com
Commit Statistics
- 10 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 10 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
v0.25.1
[0.25.1] - 2026-06-10
🐛 Bug Fixes
💼 Other
-
(deps) Bump forge to v0.11.1 - (82dd26c) by @bchatard
Tracks the latest forge tag (carries forge's own golang.org/x/sys
v0.45.0 CVE bump; heraut already pinned x/sys v0.45.0 directly, so no
effective change there). go.mod/go.sum only.Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
🚜 Refactor
-
Align forge/log import alias to forgelog - (14750f4) by @bchatard
Rename the forge/log alias flog → forgelog so it matches the family's
forge convention (forgeui, forgeexec) and the alias bifrost uses.
No behaviour change.Co-Authored-By:Claude Sonnet 4.6 noreply@anthropic.com
Commit Statistics
- 3 commit(s) contributed to the release.
- 0 day(s) passed between the first and last commit.
- 3 commit(s) parsed as conventional.
- 0 linked issue(s) detected in commits.
- 1 day(s) passed between releases.