Skip to content
This repository was archived by the owner on Apr 5, 2026. It is now read-only.

Commit b6985cd

Browse files
HerbHallclaude
andauthored
feat: add release standardization templates and ADR-0015 (#160)
Templates for standardizing versioning and changelog management across all DevSpace projects using release-please + git-cliff + VERSION file. - release-please-config.json: default simple release type with changelog sections - release-please-manifest.json: starter manifest for new projects - release-please.yml: GitHub Actions workflow template - cliff.toml: git-cliff config for Phase 2 changelog enhancement - ADR-0015: documents decision and rollout plan Co-authored-by: Claude <noreply@anthropic.com>
1 parent 1520046 commit b6985cd

7 files changed

Lines changed: 277 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Added
6+
7+
- **Release standardization templates** (ADR-0015): release-please config, manifest, workflow, and git-cliff templates in `project-templates/`
8+
- **ADR-0015**: Documents the decision to standardize on release-please + git-cliff + VERSION file across all projects
9+
310
## v2.3.0 -- 2026-03-01
411

512
Rules reconciliation, drift detection, and project settings enforcement.

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ Setup creates symlinks from `~/.claude/` to the DevKit clone (or copies files in
4444
| `claude/settings.template.json` | User-level Claude Code settings — broad permissions, hooks, plugins |
4545
| `project-templates/settings.json` | Project-level Claude Code permissions — commit to repo for collaborators |
4646
| `project-templates/workspace-claude-md-template.md` | Workspace CLAUDE.md template — fill in your projects |
47+
| `project-templates/release-please-config.json` | release-please config — set `release-type` per stack (see ADR-0015) |
48+
| `project-templates/release-please-manifest.json` | release-please manifest — set current version on first setup |
49+
| `project-templates/release-please.yml` | GitHub Actions workflow — copy to `.github/workflows/` |
50+
| `project-templates/cliff.toml` | git-cliff changelog template — Phase 2 enhancement |
4751
| `mcp/memory-seeds.md` | MCP Memory bootstrap — replace with your profile |
4852
| `mcp/claude-desktop.template.json` | MCP server config — fill in tokens and paths |
4953

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
# ADR-0015: Release Standardization
2+
3+
## Status
4+
5+
Accepted
6+
7+
## Date
8+
9+
2026-03-02
10+
11+
## Context
12+
13+
10 projects under DevSpace have fragmented version tracking and inconsistent
14+
changelog practices:
15+
16+
- **Version source of truth** varies: `VERSION` file (3 projects), `Cargo.toml`
17+
(1), Dockerfile ARG (1), git tags only (1), nothing (4).
18+
- **Changelog practices** are inconsistent: manual Keep a Changelog (3), GoReleaser
19+
auto-generated (1), none (6).
20+
- **Release automation** exists for 3 projects (SubNetree, Runbooks, DigitalRain)
21+
but each uses a different pattern. The other 7 have no release infrastructure.
22+
- **Version drift** between files is a known risk (KG#82) -- Runbooks had version
23+
in Dockerfile ARG but not in package.json.
24+
25+
All projects already use conventional commits, which is the prerequisite for
26+
automated versioning.
27+
28+
## Decision
29+
30+
Standardize all projects on three components:
31+
32+
### 1. VERSION File as Single Source of Truth
33+
34+
Every project has a plain-text `VERSION` file at the repo root containing
35+
`X.Y.Z`. Stack-native files (package.json, Cargo.toml, Dockerfile ARG) are
36+
synced from it by the release tool.
37+
38+
### 2. release-please for Automated Release Management
39+
40+
[release-please](https://github.com/googleapis/release-please) (Google, v4
41+
GitHub Action) creates and maintains a Release PR on every push to main:
42+
43+
- Analyzes conventional commits to determine the next semver version
44+
- Updates `VERSION`, `CHANGELOG.md`, and stack-native files in a PR
45+
- Human merges the Release PR (one-click review gate)
46+
- Creates a git tag and GitHub Release on merge
47+
- The tag triggers existing `release.yml` workflows (GoReleaser, Docker, cargo)
48+
49+
release-please is chosen over semantic-release because:
50+
51+
- Works with standard `GITHUB_TOKEN` (no branch protection workaround needed)
52+
- The Release PR provides a human review gate (aligns with core principle #3)
53+
- Native support for Go, Rust, and Node.js release types
54+
- Existing tag-triggered release.yml workflows are unchanged
55+
- No Node.js dependency in CI (runs as a GitHub Action)
56+
57+
### 3. git-cliff for Changelog Generation (Phase 2)
58+
59+
[git-cliff](https://github.com/orhun/git-cliff) generates high-quality
60+
changelogs from conventional commits using Tera templates. It replaces
61+
release-please's built-in changelog with customizable output.
62+
63+
git-cliff is deferred to Phase 2 to avoid debugging two new tools simultaneously.
64+
Initial rollout uses release-please's built-in changelog.
65+
66+
### Release-Type Mapping
67+
68+
| Stack | release-type | Files Managed |
69+
|-------|-------------|---------------|
70+
| Go | `go` | VERSION, CHANGELOG.md |
71+
| Rust | `rust` | VERSION, Cargo.toml, CHANGELOG.md |
72+
| Node.js / React | `node` | VERSION, package.json, CHANGELOG.md |
73+
| Docker extensions | `node` + extra-files | VERSION, package.json, Dockerfile, CHANGELOG.md |
74+
| C# / .NET | `simple` + extra-files | VERSION, .csproj, CHANGELOG.md |
75+
| PowerShell / generic | `simple` | VERSION, CHANGELOG.md |
76+
77+
### Release Flow
78+
79+
```text
80+
Feature PRs merge to main (conventional commits)
81+
-> release-please detects new commits
82+
-> Creates/updates Release PR ("chore(main): release X.Y.Z")
83+
-> Human merges Release PR
84+
-> release-please creates git tag (vX.Y.Z) + GitHub Release
85+
-> Tag triggers existing release.yml (GoReleaser, Docker, cargo)
86+
```
87+
88+
### Per-Project Configuration
89+
90+
Each project gets three files:
91+
92+
- `release-please-config.json` -- release type, version file path, changelog sections
93+
- `.release-please-manifest.json` -- current version (set manually on first setup)
94+
- `.github/workflows/release-please.yml` -- GitHub Actions workflow
95+
96+
Templates for all three are in `project-templates/`.
97+
98+
## Alternatives Considered
99+
100+
### semantic-release
101+
102+
Fully headless automation (every qualifying push to main triggers a release).
103+
Rejected because:
104+
105+
- Cannot push version/changelog commits back to protected branches without a
106+
GitHub App token -- operational burden with our enforced branch protection
107+
- No human review gate before releases
108+
- Requires Node.js in CI even for Go/Rust/C# projects
109+
- Monorepo support is effectively abandoned
110+
111+
### Manual Tagging (status quo)
112+
113+
Human decides when to release, manually creates tags and GitHub Releases.
114+
Rejected because:
115+
116+
- Inconsistent across projects (some have it, most don't)
117+
- VERSION files drift from tags
118+
- No automated changelog generation
119+
- Releases are skipped because the manual process is tedious
120+
121+
### git-cliff Standalone
122+
123+
Changelog generator only -- no version management or release automation.
124+
Not rejected, but insufficient alone. Adopted as a Phase 2 complement to
125+
release-please for higher-quality changelog output.
126+
127+
## Consequences
128+
129+
### Positive
130+
131+
- Every project has a consistent release process
132+
- VERSION file is the single source of truth -- no more drift
133+
- Changelogs are auto-generated from conventional commits
134+
- Release PRs provide a review checkpoint before publishing
135+
- Existing release.yml workflows (GoReleaser, Docker, cargo) are unchanged
136+
- New projects get release infrastructure from day 1 via devkit templates
137+
138+
### Negative
139+
140+
- release-please adds a "chore: release" commit to main on every release
141+
- C#/.NET support requires workarounds (not a first-class release type)
142+
- The Release PR must be manually merged (intentional, but adds a step)
143+
- git-cliff integration (Phase 2) requires coordinating two tools
144+
145+
### Risks
146+
147+
- release-please is maintained by Google but could be deprecated
148+
- `extra-files` marker syntax (`x-release-please-version`) is mildly invasive
149+
- Projects with irregular commit history may generate noisy first changelogs
150+
(mitigated with `bootstrap-sha` to exclude ancient history)
151+
152+
## Rollout Plan
153+
154+
1. **Phase 1**: DevKit templates and this ADR
155+
2. **Phase 2**: Projects with existing releases (SubNetree, Runbooks, DigitalRain)
156+
3. **Phase 3**: Projects with some infrastructure (DevKit, Samverk, RunNotes, DockPulse)
157+
4. **Phase 4**: Greenfield projects (CLI-Play, IPScan, PacketDeck)
158+
5. **Phase 5** (future): git-cliff integration for enhanced changelogs
159+
160+
Each phase is independent. Phases 2-4 can run in parallel once templates are ready.

project-templates/cliff.toml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
[changelog]
2+
header = """
3+
# Changelog
4+
5+
All notable changes to this project will be documented in this file.
6+
7+
"""
8+
body = """
9+
{%- macro remote_url() -%}
10+
https://github.com/HerbHall/{{ remote.github.owner }}/{{ remote.github.repo }}
11+
{%- endmacro -%}
12+
13+
{% if version -%}
14+
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
15+
{% else -%}
16+
## [Unreleased]
17+
{% endif -%}
18+
19+
{% for group, commits in commits | group_by(attribute="group") %}
20+
### {{ group | striptags | trim | upper_first }}
21+
{% for commit in commits -%}
22+
- {% if commit.scope %}*({{ commit.scope }})* {% endif -%}
23+
{% if commit.breaking %}[**breaking**] {% endif -%}
24+
{{ commit.message | upper_first }}
25+
{% endfor %}
26+
{% endfor -%}
27+
"""
28+
footer = ""
29+
trim = true
30+
31+
[git]
32+
conventional_commits = true
33+
filter_unconventional = true
34+
split_commits = false
35+
commit_parsers = [
36+
{ message = "^feat", group = "Features" },
37+
{ message = "^fix", group = "Bug Fixes" },
38+
{ message = "^perf", group = "Performance" },
39+
{ message = "^refactor", group = "Refactoring" },
40+
{ message = "^doc", group = "Documentation" },
41+
{ message = "^test", group = "Testing" },
42+
{ message = "^style", group = "Styling" },
43+
{ message = "^chore", group = "Miscellaneous" },
44+
{ message = "^ci", group = "CI/CD" },
45+
{ message = "^revert", group = "Reverts" },
46+
]
47+
filter_commits = true
48+
tag_pattern = "v[0-9].*"
49+
ignore_tags = ""
50+
topo_order = false
51+
sort_commits = "newest"
52+
53+
[bump]
54+
features_always_bump_minor = true
55+
breaking_always_bump_major = true
56+
initial_tag = "0.1.0"
57+
58+
[remote.github]
59+
owner = "HerbHall"
60+
repo = "REPO_NAME"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
3+
"packages": {
4+
".": {
5+
"release-type": "simple",
6+
"version-file": "VERSION",
7+
"changelog-path": "CHANGELOG.md",
8+
"bump-minor-pre-major": true,
9+
"bump-patch-for-minor-pre-major": true
10+
}
11+
},
12+
"changelog-sections": [
13+
{ "type": "feat", "section": "Features" },
14+
{ "type": "fix", "section": "Bug Fixes" },
15+
{ "type": "perf", "section": "Performance" },
16+
{ "type": "refactor", "section": "Code Refactoring", "hidden": true },
17+
{ "type": "docs", "section": "Documentation", "hidden": true },
18+
{ "type": "chore", "section": "Miscellaneous", "hidden": true },
19+
{ "type": "test", "section": "Tests", "hidden": true }
20+
]
21+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
".": "0.1.0"
3+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Release Please
2+
3+
on:
4+
push:
5+
branches: [main]
6+
7+
permissions:
8+
contents: write
9+
pull-requests: write
10+
11+
jobs:
12+
release-please:
13+
runs-on: ubuntu-latest
14+
outputs:
15+
release_created: ${{ steps.release.outputs.release_created }}
16+
tag_name: ${{ steps.release.outputs.tag_name }}
17+
version: ${{ steps.release.outputs.version }}
18+
steps:
19+
- uses: googleapis/release-please-action@v4
20+
id: release
21+
with:
22+
token: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)