88# scripts/bump-objectui.sh --no-changeset # skip the @objectstack/console changeset
99#
1010# Env:
11- # CONSOLE_BUMP=minor|patch # force the changeset bump type (default: auto —
12- # # `minor` if the objectui range has any feat, else patch)
11+ # CONSOLE_BUMP=major|minor|patch # force the changeset bump type (default: auto —
12+ # # the HIGHEST level objectui itself declared in the
13+ # # changesets added over the range; see #4731)
14+ # CONSOLE_CHANGES_MAX=<n> # cap the rendered list (default 100). A cap that
15+ # # fires says so, with the real count — never silently.
1316#
1417# Assumes sibling layout:
1518# ~/work/objectui
2730# the objectui commit range, routing the frontend delta through the SAME
2831# changesets pipeline as the backend: it lands in @objectstack/console's
2932# CHANGELOG and rolls up into the platform version + the curated release notes.
33+ #
34+ # WHAT GOES IN THE LIST — DECLARED, NOT GUESSED (#4731)
35+ # The list used to be a GUESS off the commit subject (`grep -iE '^- (feat|fix)'`
36+ # + `head -40`), and the bump level another (`grep -ciE '^feat'`). Both were
37+ # measured wrong on one real range: every `refactor(...)!` — the BREAKING class,
38+ # the one that must never vanish from a release record — was structurally unable
39+ # to appear, `head -40` truncated in silence, and `fix(ci)` commits that release
40+ # nothing were pulled in. objectui already DECLARES which commits ship: every
41+ # releasing PR carries a `.changeset/*.md`, and an empty frontmatter block is
42+ # changesets' own "release-nothing". So `objectui-changeset-digest.mjs` reads the
43+ # changesets added over the range — package names decide inclusion, the declared
44+ # level decides the bump. Nothing is inferred from a subject line.
3045
3146set -euo pipefail
3247
@@ -41,7 +56,7 @@ for arg in "$@"; do
4156 --no-commit) NO_COMMIT=1 ;;
4257 --no-changeset) NO_CHANGESET=1 ;;
4358 -h|--help)
44- sed -n ' 2,20p ' " $0 " | sed ' s/^# \{0,1\}//'
59+ sed -n ' 2,19p ' " $0 " | sed ' s/^# \{0,1\}//'
4560 exit 0
4661 ;;
4762 * ) EXPLICIT_SHA=" $arg " ;;
@@ -85,52 +100,60 @@ SUBJECT_LINE="$(git -C "$OBJECTUI_ROOT" log -1 --format=%s "$NEW_SHA")"
85100CS_FILE=" "
86101if [[ " $NO_CHANGESET " -eq 0 ]]; then
87102 # Can we walk the OLD..NEW range in the objectui checkout? (A shallow clone or
88- # a first-ever pin may not have OLD reachable — degrade to the tip subject.)
103+ # a first-ever pin may not have OLD reachable — degrade to the tip subject,
104+ # and SAY SO in the artifact: a degraded list and a complete one must never
105+ # look alike, #4731.)
89106 RANGE_OK=0
90107 if [[ " $OLD_SHA " != " <none>" ]] && git -C " $OBJECTUI_ROOT " cat-file -e " ${OLD_SHA} ^{commit}" 2> /dev/null; then
91108 RANGE_OK=1
92109 fi
93110
94- CHANGES=" "
111+ CS_FILE=" ${FRAMEWORK_ROOT} /.changeset/console-${SHORT} .md"
112+ DIGEST_OK=0
113+ BUMP=" "
95114 if [[ " $RANGE_OK " -eq 1 ]]; then
96- CHANGES=" $( git -C " $OBJECTUI_ROOT " log --no-merges --format=' - %s' " ${OLD_SHA} ..${NEW_SHA} " \
97- | grep -iE ' ^- (feat|fix)' | head -40 || true) "
98- fi
99- [[ -z " $CHANGES " ]] && CHANGES=" - ${SUBJECT_LINE} "
100-
101- BUMP=" ${CONSOLE_BUMP:- } "
102- if [[ -z " $BUMP " ]]; then
103- # NOTE: count, don't `grep -q`. Under `set -o pipefail`, `grep -q` exits on
104- # the first match and the still-writing `git log` takes SIGPIPE, so the
105- # pipeline returns 141 and this test ALWAYS took the else branch — every
106- # refresh was silently stamped `patch`, feature ranges included. `grep -c`
107- # drains its input, so no signal and a truthful count.
108- FEAT_COUNT=0
109- if [[ " $RANGE_OK " -eq 1 ]]; then
110- FEAT_COUNT=" $( git -C " $OBJECTUI_ROOT " log --format=%s " ${OLD_SHA} ..${NEW_SHA} " | grep -ciE ' ^feat' || true) "
111- fi
112- if [[ " $FEAT_COUNT " -gt 0 ]]; then
113- BUMP=minor
114- else
115- BUMP=patch
115+ # The digest reads objectui's OWN declarations (.changeset/*.md added over
116+ # the range) — inclusion and level both come from there, nothing is guessed
117+ # off a commit subject. It writes the whole changeset file and echoes the
118+ # resolved bump level.
119+ if BUMP=" $( node " ${FRAMEWORK_ROOT} /scripts/objectui-changeset-digest.mjs" \
120+ --objectui-root " $OBJECTUI_ROOT " \
121+ --framework-root " $FRAMEWORK_ROOT " \
122+ --from " $OLD_SHA " --to " $NEW_SHA " \
123+ --max " ${CONSOLE_CHANGES_MAX:- 100} " \
124+ --bump-override " ${CONSOLE_BUMP:- } " \
125+ --out " $CS_FILE " ) " ; then
126+ DIGEST_OK=1
116127 fi
117128 fi
118129
119- RANGE_LABEL=" ${OLD_SHA: 0: 12} ...${NEW_SHA: 0: 12} "
120- [[ " $OLD_SHA " == " <none>" ]] && RANGE_LABEL=" (initial pin) → ${NEW_SHA: 0: 12} "
121-
122- CS_FILE=" ${FRAMEWORK_ROOT} /.changeset/console-${SHORT} .md"
123- cat > " $CS_FILE " << EOF
130+ if [[ " $DIGEST_OK " -eq 0 ]]; then
131+ # Degraded path: no walkable range (initial pin, shallow clone, or the
132+ # digest could not run). Emit the tip subject ONLY, labelled as degraded —
133+ # the reader must be able to tell this list from a derived one.
134+ BUMP=" ${CONSOLE_BUMP:- patch} "
135+ RANGE_LABEL=" ${OLD_SHA: 0: 12} ...${NEW_SHA: 0: 12} "
136+ WHY=" the range \` ${RANGE_LABEL} \` could not be walked in this objectui checkout"
137+ if [[ " $OLD_SHA " == " <none>" ]]; then
138+ RANGE_LABEL=" (initial pin) → ${NEW_SHA: 0: 12} "
139+ WHY=" this is the initial pin, so there is no previous SHA to walk from"
140+ fi
141+ cat > " $CS_FILE " << EOF
124142---
125143"@objectstack/console": ${BUMP}
126144---
127145
128146Console (objectui) refreshed to \` ${SHORT} \` . Frontend changes in this range:
129147
130- ${CHANGES}
148+ ⚠️ **Degraded list** — ${WHY} , so this entry could not be derived from the
149+ changesets objectui declared. It names the tip commit only and is NOT a
150+ complete account of the range:
151+
152+ - ${SUBJECT_LINE}
131153
132154objectui range: \` ${RANGE_LABEL} \`
133155EOF
156+ fi
134157 echo " → wrote changeset $( basename " $CS_FILE " ) (@objectstack/console: ${BUMP} )"
135158fi
136159
0 commit comments