-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathbuild-console.sh
More file actions
executable file
·194 lines (172 loc) · 8.84 KB
/
Copy pathbuild-console.sh
File metadata and controls
executable file
·194 lines (172 loc) · 8.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#!/usr/bin/env bash
# Build @object-ui/console at the SHA pinned in .objectui-sha and copy
# its dist/ into packages/console/ so @objectstack/console can publish
# a version-matched, prebuilt Console SPA alongside the framework.
#
# Resolution order for the objectui source tree:
# 1. $OBJECTUI_ROOT (if set and a git repo) — explicit override
# 2. ../objectui sibling checkout — local dev layout
# 3. Shallow clone into .cache/objectui at the SHA — CI / fresh machines
#
# In modes 1 and 2 the script does NOT mutate the developer's checkout —
# it creates a git worktree at the pinned SHA so the dev tree is left alone.
# Mode 3 fetches just the pinned commit.
#
# Always rebuilds the dist (no `if exists, skip` shortcut) so a stale
# tree can't mask a bad SHA in CI.
#
# Usage:
# scripts/build-console.sh
#
# Env:
# OBJECTUI_ROOT override path to objectui checkout
# OBJECTUI_REPO_URL override clone URL (default: https://github.com/objectstack-ai/objectui.git)
# OBJECTUI_DEPS_BUILD_CMD override deps build (default: pnpm exec turbo run build --filter=@object-ui/console^...)
# OBJECTUI_BUILD_CMD override console build (default: pnpm --filter @object-ui/console run build)
# CONSOLE_BUNDLE_CANARY literal asserted in the built assets (default: import/jobs)
set -euo pipefail
FRAMEWORK_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SHA_FILE="${FRAMEWORK_ROOT}/.objectui-sha"
if [[ ! -f "$SHA_FILE" ]]; then
echo "✗ ${SHA_FILE} is missing — cannot determine which objectui commit to build."
exit 1
fi
PINNED_SHA="$(tr -d '[:space:]' < "$SHA_FILE")"
if [[ -z "$PINNED_SHA" ]]; then
echo "✗ ${SHA_FILE} is empty."
exit 1
fi
REPO_URL="${OBJECTUI_REPO_URL:-https://github.com/objectstack-ai/objectui.git}"
# The console app itself must NOT build through turbo: turbo v2 runs tasks in
# strict env mode and strips undeclared vars, so OBJECTSTACK_CLIENT_DIST
# (exported below) never reaches vite unless the pinned objectui SHA happens
# to declare it in turbo.json. Build the workspace deps through turbo
# (cacheable, env-independent), then invoke the console's own build script
# directly so the env survives.
DEPS_BUILD_CMD="${OBJECTUI_DEPS_BUILD_CMD:-pnpm exec turbo run build --filter=@object-ui/console^...}"
BUILD_CMD="${OBJECTUI_BUILD_CMD:-pnpm --filter @object-ui/console run build}"
# Post-build canary: a literal that only exists in an up-to-date bundled
# client. Guards against any future mechanism (turbo env stripping, a removed
# vite hook, chunking changes) silently shipping a stale client again.
BUNDLE_CANARY="${CONSOLE_BUNDLE_CANARY:-import/jobs}"
# Resolve a source checkout of objectui.
SOURCE_ROOT=""
if [[ -n "${OBJECTUI_ROOT:-}" && -d "${OBJECTUI_ROOT}/.git" ]]; then
SOURCE_ROOT="$OBJECTUI_ROOT"
elif [[ -d "${FRAMEWORK_ROOT}/../objectui/.git" ]]; then
SOURCE_ROOT="$(cd "${FRAMEWORK_ROOT}/../objectui" && pwd)"
fi
# Worktree path we'll build from. Always under framework so cleanup is local.
BUILD_ROOT="${FRAMEWORK_ROOT}/.cache/objectui-${PINNED_SHA:0:12}"
mkdir -p "${FRAMEWORK_ROOT}/.cache"
if [[ -n "$SOURCE_ROOT" ]]; then
echo "→ Using objectui source at ${SOURCE_ROOT}"
# Fetch the pinned commit if missing locally, so dev laptops with a
# stale checkout still work.
if ! git -C "$SOURCE_ROOT" cat-file -e "${PINNED_SHA}^{commit}" 2>/dev/null; then
echo "→ Pinned commit ${PINNED_SHA:0:12} not present locally — fetching from origin..."
git -C "$SOURCE_ROOT" fetch --no-tags origin "$PINNED_SHA" || \
git -C "$SOURCE_ROOT" fetch --no-tags origin
fi
# Reuse worktree if it already points at the right commit; otherwise
# remove and recreate so we always build the pinned tree.
if [[ -d "$BUILD_ROOT" ]]; then
CURRENT="$(git -C "$BUILD_ROOT" rev-parse HEAD 2>/dev/null || echo '')"
if [[ "$CURRENT" != "$PINNED_SHA" ]]; then
git -C "$SOURCE_ROOT" worktree remove --force "$BUILD_ROOT" 2>/dev/null || rm -rf "$BUILD_ROOT"
fi
fi
if [[ ! -d "$BUILD_ROOT" ]]; then
git -C "$SOURCE_ROOT" worktree add --detach "$BUILD_ROOT" "$PINNED_SHA"
fi
else
echo "→ No local objectui checkout — shallow-cloning ${REPO_URL} at ${PINNED_SHA:0:12}"
if [[ -d "$BUILD_ROOT/.git" ]]; then
CURRENT="$(git -C "$BUILD_ROOT" rev-parse HEAD 2>/dev/null || echo '')"
if [[ "$CURRENT" != "$PINNED_SHA" ]]; then
rm -rf "$BUILD_ROOT"
fi
fi
if [[ ! -d "$BUILD_ROOT/.git" ]]; then
rm -rf "$BUILD_ROOT"
mkdir -p "$BUILD_ROOT"
git -C "$BUILD_ROOT" init -q
git -C "$BUILD_ROOT" remote add origin "$REPO_URL"
git -C "$BUILD_ROOT" fetch --depth=1 origin "$PINNED_SHA"
git -C "$BUILD_ROOT" checkout --detach FETCH_HEAD
fi
fi
# Verify HEAD matches the pin.
ACTUAL="$(git -C "$BUILD_ROOT" rev-parse HEAD)"
if [[ "$ACTUAL" != "$PINNED_SHA" ]]; then
echo "✗ Worktree HEAD ${ACTUAL:0:12} does not match pin ${PINNED_SHA:0:12}"
exit 1
fi
echo "→ Building @object-ui/console at ${PINNED_SHA:0:12}..."
# ── Bundle THIS framework's client ───────────────────────────────────
# The console SPA inlines @objectstack/client. Left to itself, the objectui
# build resolves the client from objectui's own lockfile — which lags the
# framework whenever a release adds new client APIs (the lockfile can't point
# at a client that isn't published yet). That shipped 11.5.0 with the new
# import UI bundled against client 11.2.0, so the console threw "does not
# support async import jobs" at runtime. Alias the build to the client in
# THIS tree instead: the bundled client then always matches the framework
# release being published, with no objectui pin-bump round-trip.
# objectui honors OBJECTSTACK_CLIENT_DIST in apps/console/vite.config.ts;
# fail hard if the pinned SHA predates that hook rather than silently drift.
CLIENT_PKG="${FRAMEWORK_ROOT}/packages/client"
if ! grep -q "OBJECTSTACK_CLIENT_DIST" "${BUILD_ROOT}/apps/console/vite.config.ts"; then
echo "✗ objectui@${PINNED_SHA:0:12} has no OBJECTSTACK_CLIENT_DIST hook in apps/console/vite.config.ts —"
echo " the bundled client would come from objectui's lockfile, not this framework."
echo " Bump .objectui-sha to a commit that includes the hook."
exit 1
fi
if [[ ! -f "${CLIENT_PKG}/dist/index.mjs" ]]; then
echo "→ @objectstack/client dist missing — building it first..."
(cd "$CLIENT_PKG" && pnpm build)
fi
export OBJECTSTACK_CLIENT_DIST="$CLIENT_PKG"
echo "→ Console will bundle @objectstack/client from ${CLIENT_PKG}"
pushd "$BUILD_ROOT" > /dev/null
# objectui's root package.json may pin packages that aren't available on
# every mirror. Fall back to the public registry just for this install.
NPM_CONFIG_REGISTRY_OVERRIDE="${OBJECTUI_NPM_REGISTRY:-https://registry.npmjs.org}"
npm_config_registry="$NPM_CONFIG_REGISTRY_OVERRIDE" \
pnpm install --frozen-lockfile --prefer-offline --prod=false
# Build the console's workspace deps via turbo, then the SPA itself directly
# (see DEPS_BUILD_CMD/BUILD_CMD above for why these are split).
eval "$DEPS_BUILD_CMD"
eval "$BUILD_CMD"
popd > /dev/null
CONSOLE_DIST="${BUILD_ROOT}/apps/console/dist"
if [[ ! -f "${CONSOLE_DIST}/index.html" ]]; then
echo "✗ Build did not produce ${CONSOLE_DIST}/index.html"
exit 1
fi
TARGET="${FRAMEWORK_ROOT}/packages/console/dist"
echo "→ Copying dist → ${TARGET}"
rm -rf "$TARGET"
mkdir -p "$(dirname "$TARGET")"
cp -R "$CONSOLE_DIST" "$TARGET"
# Provenance stamp: record which objectui SHA this dist was built from, so
# `pnpm check:console-sha` and the CLI serve-time guard can detect drift when
# .objectui-sha later moves ahead of this gitignored, locally-built dist
# (which `turbo run build` does NOT rebuild). Travels inside dist/ so a
# cloud/objectos Docker overlay that replaces dist/ restamps it too.
echo "$PINNED_SHA" > "${TARGET}/.objectui-sha"
# Assert the injected client actually landed in the bundle (see BUNDLE_CANARY).
if ! grep -rq "$BUNDLE_CANARY" "${TARGET}/assets"; then
echo "✗ Built console dist does not contain '${BUNDLE_CANARY}' — the bundled"
echo " @objectstack/client is stale (OBJECTSTACK_CLIENT_DIST injection failed)."
exit 1
fi
echo "✓ Bundle canary '${BUNDLE_CANARY}' present — framework client is in the bundle."
BYTES="$(du -sk "$TARGET" 2>/dev/null | awk '{print $1}')"
echo "✓ @objectstack/console dist ready (${BYTES} KB) from objectui@${PINNED_SHA:0:12}"
# ADR-0080/0081: the public-tier SDUI manifest and the spec↔frontend react-block
# conformance ratchet are intentionally NOT generated here — they require a real
# browser (Playwright) to enumerate the console registry, and the console build
# must not drag in a browser dependency. Regenerate them on demand instead:
# pnpm sdui:manifest (see scripts/gen-sdui-manifest.sh)
echo "ℹ SDUI manifest + conformance ratchet are decoupled from the console build."
echo " Run 'pnpm sdui:manifest' on demand to regenerate (requires Playwright)."