Skip to content

Commit d1148f3

Browse files
authored
add stable release command (#21)
## Summary - make `just release stable` the canonical one-command stable release entrypoint - keep `just release tag vX.Y.Z` for explicit version tags, but make it push the tag too - update release docs to point at the just command instead of manual git steps ## Validation - `just release` - `just release current` - `just release check` ## Note - this PR does not create a release tag; it only makes the release flow consistent and discoverable
2 parents 957988c + c710925 commit d1148f3

2 files changed

Lines changed: 109 additions & 7 deletions

File tree

.justfiles/release.just

Lines changed: 102 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,20 @@
22

33
[private]
44
default:
5-
@just --list --unsorted --justfile {{source_file()}}
5+
#!/usr/bin/env bash
6+
echo "camp-graph release commands"
7+
echo ""
8+
echo "Primary:"
9+
echo " just release stable [patch|minor|major]"
10+
echo ""
11+
echo "Support:"
12+
echo " just release current"
13+
echo " just release check"
14+
echo " just release snapshot"
15+
echo " just release tag v0.1.0"
616
717
goreleaser := "go run github.com/goreleaser/goreleaser/v2@v2.15.2"
18+
repo := "Obedience-Corp/camp-graph"
819

920
# Validate GoReleaser configuration
1021
[no-cd]
@@ -21,7 +32,86 @@ snapshot:
2132
version:
2233
@go run ./cmd/camp-graph version
2334

24-
# Tag a release (usage: just release tag v0.1.0)
35+
# Show current stable release tag
36+
[no-cd]
37+
current:
38+
#!/usr/bin/env bash
39+
set -euo pipefail
40+
git fetch --prune --prune-tags origin '+refs/tags/*:refs/tags/*' >/dev/null 2>&1 || true
41+
latest=$(git tag -l --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1 || true)
42+
echo "${latest:-none}"
43+
44+
# Create and push the next stable release tag (usage: just release stable [patch|minor|major])
45+
[no-cd]
46+
stable level="patch":
47+
#!/usr/bin/env bash
48+
set -euo pipefail
49+
50+
level="{{level}}"
51+
case "$level" in
52+
patch|minor|major) ;;
53+
*)
54+
echo "Unknown level: $level (use patch, minor, or major)"
55+
exit 1
56+
;;
57+
esac
58+
59+
if [ -n "$(git status --porcelain)" ]; then
60+
echo "ERROR: repo has uncommitted changes"
61+
git status --short
62+
exit 1
63+
fi
64+
65+
branch="$(git rev-parse --abbrev-ref HEAD)"
66+
if [ "$branch" != "main" ]; then
67+
echo "ERROR: releases must be cut from main (current: $branch)"
68+
exit 1
69+
fi
70+
71+
git fetch --prune --prune-tags origin '+refs/tags/*:refs/tags/*' '+refs/heads/main:refs/remotes/origin/main'
72+
73+
if [ "$(git rev-parse HEAD)" != "$(git rev-parse origin/main)" ]; then
74+
echo "ERROR: local main is not in sync with origin/main"
75+
echo "Run: git pull --ff-only origin main"
76+
exit 1
77+
fi
78+
79+
just --justfile {{source_file()}} check
80+
81+
latest=$(git tag -l --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1 || true)
82+
83+
if [ -z "$latest" ]; then
84+
next="v0.1.0"
85+
else
86+
nums="${latest#v}"
87+
IFS='.' read -r major minor patch <<< "$nums"
88+
89+
case "$level" in
90+
major) major=$((major + 1)); minor=0; patch=0 ;;
91+
minor) minor=$((minor + 1)); patch=0 ;;
92+
patch) patch=$((patch + 1)) ;;
93+
esac
94+
95+
next="v${major}.${minor}.${patch}"
96+
fi
97+
98+
if git tag -l "$next" | grep -q .; then
99+
echo "ERROR: tag $next already exists locally"
100+
exit 1
101+
fi
102+
103+
if [ -n "$(git ls-remote --tags origin "refs/tags/${next}")" ]; then
104+
echo "ERROR: tag $next already exists on origin"
105+
exit 1
106+
fi
107+
108+
echo "Creating stable release: $next"
109+
git tag -a "$next" -m "Release $next"
110+
git push origin "$next"
111+
echo "Pushed $next"
112+
echo "Release workflow should now start on GitHub."
113+
114+
# Create and push an explicit release tag (usage: just release tag v0.1.0)
25115
[no-cd]
26116
tag VERSION:
27117
#!/usr/bin/env bash
@@ -30,6 +120,14 @@ tag VERSION:
30120
echo "Version must start with 'v' (e.g., v0.1.0)"
31121
exit 1
32122
fi
33-
echo "Tagging {{VERSION}}..."
123+
if [ -n "$(git status --porcelain)" ]; then
124+
echo "ERROR: repo has uncommitted changes"
125+
git status --short
126+
exit 1
127+
fi
128+
just --justfile {{source_file()}} check
129+
echo "Creating release tag {{VERSION}}..."
34130
git tag -a "{{VERSION}}" -m "Release {{VERSION}}"
35-
echo "Tagged {{VERSION}}. Push with: git push origin {{VERSION}}"
131+
git push origin "{{VERSION}}"
132+
echo "Pushed {{VERSION}}"
133+
echo "Release workflow should now start on GitHub."

docs/releasing.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ The release workflow fails early if either secret is missing.
2121
## Release steps
2222

2323
```bash
24-
just test unit
25-
just release tag v0.1.0
26-
git push origin v0.1.0
24+
just release stable
2725
```
2826

2927
GitHub Actions then:
@@ -34,6 +32,12 @@ GitHub Actions then:
3432
4. updates `Obedience-Corp/homebrew-tap`
3533
5. updates the AUR package repo
3634

35+
If you need an explicit version instead of the next computed stable tag:
36+
37+
```bash
38+
just release tag v0.1.0
39+
```
40+
3741
## Reuse for future `camp-*` plugins
3842

3943
Copy this file set into the new plugin repo:

0 commit comments

Comments
 (0)