Skip to content

Commit 2ff99bc

Browse files
committed
refactor: Option C — single-source versioning (devstack only)
1 parent ec90d8c commit 2ff99bc

4 files changed

Lines changed: 174 additions & 144 deletions

File tree

.githooks/commit-msg

Lines changed: 3 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,5 @@
11
#!/bin/bash
2-
# Auto-increment patch version on every commit (unless [skip-version])
3-
# Increments VERSION across all stack repos and auto-commits with [skip-version]
4-
# Does NOT touch package.json versions (kept at original fork versions)
5-
6-
COMMIT_MSG_FILE="$1"
7-
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
8-
9-
# [skip-version] → no bump, just pass through
10-
if echo "$COMMIT_MSG" | grep -q '\[skip-version\]'; then
11-
exit 0
12-
fi
13-
14-
# Find devstack dir by searching upward from the git working tree
15-
DEVSTACK_DIR="$(git rev-parse --show-toplevel 2>/dev/null)"
16-
[ -z "$DEVSTACK_DIR" ] && DEVSTACK_DIR="$PWD"
17-
18-
[ ! -f "$DEVSTACK_DIR/VERSION" ] && exit 0
19-
20-
VERSION=$(cat "$DEVSTACK_DIR/VERSION" 2>/dev/null || echo "0.0.0-lpb")
21-
BASE=$(echo "$VERSION" | sed 's/^[0-9]*\.[0-9]*\.[0-9]*//')
22-
PATCH=$(echo "$VERSION" | sed 's/^[0-9]*\.[0-9]*\.\([0-9]*\).*/\1/')
23-
NEW_PATCH=$((PATCH + 1))
24-
NEW_VERSION="0.0.${NEW_PATCH}${BASE}"
25-
26-
# Update VERSION in all stack repos
27-
REPOS=(
28-
"$DEVSTACK_DIR/workspace/pi"
29-
"/home/lpb/.pi/agent/git/github.com/localpibox/lemonade-pi-plugin"
30-
"/home/lpb/workspace/localpibox/config"
31-
"/home/lpb/workspace/localpibox/lpb-memory"
32-
"/home/lpb/.pi/agent/git/github.com/localpibox/pi-subagents"
33-
)
34-
35-
echo ""
36-
echo "=== Auto-bump VERSION ==="
37-
echo " $VERSION$NEW_VERSION"
38-
39-
echo "$NEW_VERSION" > "$DEVSTACK_DIR/VERSION"
40-
41-
for repo in "${REPOS[@]}"; do
42-
[ -f "$repo/VERSION" ] && echo "$NEW_VERSION" > "$repo/VERSION"
43-
done
44-
45-
# Update lpb.stack.env
46-
if [ -f "$DEVSTACK_DIR/lpb.stack.env" ]; then
47-
sed -i "s/^LPB_PI_REF=.*/LPB_PI_REF=$NEW_VERSION/" "$DEVSTACK_DIR/lpb.stack.env"
48-
fi
49-
50-
# Auto-commit VERSION in each repo (with [skip-version] to avoid infinite loop)
51-
for repo in "${REPOS[@]}"; do
52-
repo_name=$(basename "$repo")
53-
[ -d "$repo" ] || continue
54-
[ -f "$repo/VERSION" ] || continue
55-
# Stage and commit if VERSION is the only staged change
56-
(cd "$repo" && git add VERSION 2>/dev/null)
57-
staged=$(cd "$repo" && git diff --cached --name-only 2>/dev/null)
58-
if [ "$staged" = "VERSION" ]; then
59-
(cd "$repo" && git commit -m "chore: bump VERSION $NEW_VERSION [skip-version]" --no-verify 2>/dev/null) && \
60-
echo "$repo_name: $NEW_VERSION" || \
61-
echo " ⚠️ $repo_name: version updated on disk, not committed"
62-
fi
63-
done
64-
65-
# Auto-commit VERSION in devstack
66-
(cd "$DEVSTACK_DIR" && git add VERSION lpb.stack.env 2>/dev/null)
67-
staged=$(cd "$DEVSTACK_DIR" && git diff --cached --name-only 2>/dev/null)
68-
if echo "$staged" | grep -q "VERSION"; then
69-
(cd "$DEVSTACK_DIR" && git commit -m "chore: bump VERSION $NEW_VERSION [skip-version]" --no-verify 2>/dev/null) && \
70-
echo " ✅ devstack: $NEW_VERSION"
71-
fi
72-
2+
# commit-msg hook — No-op
3+
# Version bumping is handled by CI (bump-version job after tests pass)
4+
# Git hooks do NOT touch VERSION files or cross-repo state.
735
exit 0

.githooks/pre-commit

Lines changed: 41 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
#!/bin/bash
2-
# pre-commit hook — Validate & sync all stack repos before commit
2+
# pre-commit hook — Validate devstack state before commit
33
#
44
# Validates:
5-
# 1. All VERSION files in sync
5+
# 1. VERSION file format (devstack only)
66
# 2. lpb.stack.env LPB_PI_REF matches VERSION
77
# 3. settings.json pins match VERSION
88
# 4. All repos clean (except VERSION/env)
9-
# 5. Auto-stage + auto-commit VERSION across all repos
109
#
1110
# Exit non-zero to abort commit.
1211

@@ -20,6 +19,12 @@ while [ "$check_dir" != "/" ]; do
2019
done
2120
[ -z "$DEVSTACK_DIR" ] && DEVSTACK_DIR="$PWD"
2221

22+
# If we can't find devstack, do a local-only validation
23+
NOT_IN_DEVSTACK=false
24+
if [ ! -f "$DEVSTACK_DIR/VERSION" ] || [ ! -f "$DEVSTACK_DIR/lpb.stack.env" ]; then
25+
NOT_IN_DEVSTACK=true
26+
fi
27+
2328
ERRORS=0
2429
CURRENT_VERSION=$(cat "$DEVSTACK_DIR/VERSION" 2>/dev/null || echo "NOT FOUND")
2530

@@ -31,42 +36,32 @@ declare -a REPOS=(
3136
"/home/lpb/.pi/agent/git/github.com/localpibox/pi-subagents"
3237
)
3338

34-
check_repo_version() {
35-
local repo_path="$1"
36-
local repo_name="$2"
37-
[ -d "$repo_path" ] || return 0
38-
[ -f "$repo_path/VERSION" ] || return 0
39-
local repo_version
40-
repo_version=$(cat "$repo_path/VERSION")
41-
if [ "$repo_version" != "$CURRENT_VERSION" ]; then
42-
error "$repo_name: VERSION=$repo_version (expected $CURRENT_VERSION)"
43-
else
44-
info "$repo_name: $repo_version"
45-
fi
46-
}
47-
4839
SETTINGS_JSON="/home/lpb/.pi/agent/settings.json"
4940

5041
info() { echo "$*"; }
5142
warn() { echo " ⚠️ $*"; }
5243
error() { echo "$*"; ERRORS=$((ERRORS + 1)); }
5344

54-
# 1. Validate VERSION files
55-
echo "=== Stack Version Sync ==="
56-
for repo in "${REPOS[@]}"; do
57-
repo_name=$(basename "$repo")
58-
check_repo_version "$repo" "$repo_name"
59-
done
60-
61-
# 2. Validate lpb.stack.env
45+
# 1. Validate VERSION file format (devstack only)
46+
echo "=== Stack Version ==="
47+
if [ "$NOT_IN_DEVSTACK" = true ]; then
48+
info "(running outside devstack — skipping version check)"
49+
else
50+
if echo "$CURRENT_VERSION" | grep -qE '^0\.[0-9]+\.[0-9]+-lpb$'; then
51+
info "VERSION=$CURRENT_VERSION (valid)"
52+
else
53+
error "VERSION='$CURRENT_VERSION' does not match 0.x.y-lpb format"
54+
fi
55+
fi
6256
echo ""
6357
echo "=== Environment Sync ==="
64-
if [ -f "$DEVSTACK_DIR/lpb.stack.env" ]; then
58+
if [ "$NOT_IN_DEVSTACK" = true ]; then
59+
info "(skipped — not in devstack)"
60+
elif [ -f "$DEVSTACK_DIR/lpb.stack.env" ]; then
6561
PI_REF=$(grep '^LPB_PI_REF=' "$DEVSTACK_DIR/lpb.stack.env" | cut -d= -f2)
6662
if [ "$PI_REF" != "$CURRENT_VERSION" ]; then
6763
error "lpb.stack.env: LPB_PI_REF=$PI_REF (expected $CURRENT_VERSION)"
68-
sed -i "s/^LPB_PI_REF=.*/LPB_PI_REF=$CURRENT_VERSION/" "$DEVSTACK_DIR/lpb.stack.env"
69-
echo " 🔧 Fixed LPB_PI_REF to $CURRENT_VERSION"
64+
echo " 🔧 Hint: CI bumps VERSION + updates LPB_PI_REF automatically"
7065
else
7166
info "LPB_PI_REF=$PI_REF"
7267
fi
@@ -75,7 +70,9 @@ fi
7570
# 3. Validate settings.json pins
7671
echo ""
7772
echo "=== Extension Pins ==="
78-
if [ -f "$SETTINGS_JSON" ]; then
73+
if [ "$NOT_IN_DEVSTACK" = true ]; then
74+
info "(skipped — not in devstack)"
75+
elif [ -f "$SETTINGS_JSON" ]; then
7976
for repo in lemonade-pi-plugin lpb-memory pi-subagents; do
8077
if python3 -c "
8178
import json, sys
@@ -104,33 +101,24 @@ fi
104101

105102
# 4. Check repo cleanliness
106103
echo ""
107-
echo "=== Unstaged Changes ==="
108-
check_unstaged() {
109-
local repo_path="$1"
110-
local repo_name="$2"
111-
[ -d "$repo_path" ] || return 0
112-
local dirty
113-
dirty=$(cd "$repo_path" && git diff --name-only 2>/dev/null | grep -vE '^$' | grep -vE 'VERSION|lpb\.stack\.env|lpb\.conf\.env|\.githooks/' | grep -c . || true)
114-
[ "$dirty" -gt 0 ] && error "$repo_name: $dirty unstaged change(s)" || info "$repo_name: clean"
115-
}
116-
117-
for repo in "${REPOS[@]}"; do
118-
check_unstaged "$repo" "$(basename "$repo")"
119-
done
120-
121-
check_unstaged "$DEVSTACK_DIR" "devstack"
104+
echo "=== Clean State ==="
105+
if [ "$NOT_IN_DEVSTACK" = true ]; then
106+
info "(skipped — not in devstack)"
107+
else
108+
check_unstaged() {
109+
local repo_path="$1"
110+
local repo_name="$2"
111+
[ -d "$repo_path" ] || return 0
112+
local dirty
113+
dirty=$(cd "$repo_path" && git diff --name-only 2>/dev/null | grep -vE '^$' | grep -vE 'VERSION|lpb\.stack\.env|lpb\.conf\.env|\.githooks/' | grep -c . || true)
114+
[ "$dirty" -gt 0 ] && error "$repo_name: $dirty unstaged change(s)" || info "$repo_name: clean"
115+
}
122116

123-
# 5. Auto-stage VERSION + env changes (commit-msg auto-commits after)
124-
if [ $ERRORS -eq 0 ] && [ "$CURRENT_VERSION" != "NOT FOUND" ]; then
125-
echo ""
126-
echo "=== Auto-stage VERSION ==="
127-
cd "$DEVSTACK_DIR" && git add VERSION lpb.stack.env 2>/dev/null
128117
for repo in "${REPOS[@]}"; do
129-
repo_name=$(basename "$repo")
130-
[ -d "$repo" ] || continue
131-
[ -f "$repo/VERSION" ] && (cd "$repo" && git add VERSION 2>/dev/null)
118+
check_unstaged "$repo" "$(basename "$repo")"
132119
done
133-
info "VERSION files staged (auto-commit by commit-msg hook)"
120+
121+
check_unstaged "$DEVSTACK_DIR" "devstack"
134122
fi
135123

136124
# Result

0 commit comments

Comments
 (0)