diff --git a/tools/export-github.sh b/tools/export-github.sh index 6cbf194d..2d13a5a0 100755 --- a/tools/export-github.sh +++ b/tools/export-github.sh @@ -265,42 +265,61 @@ git bundle create "$BUNDLE" HEAD "$BRANCH" --tags git bundle verify "$BUNDLE" >/dev/null echo "bundle: $BUNDLE" -# --- 6. optional per-instance dists (both bases: /ops = dev, /shopdb = prod) --- -# Two instances run on the box; each needs its own base-path build. Always -# rebuild BOTH so prod never ships a stale frontend. -# --dist IS MAIN ONLY. +# --- 6. the frontend dist for THIS branch's instance --------------------------- # -# These paths are not branch-qualified and cannot safely be: update-prod-server -# .cmd robocopies frontend-dist-subpath-shopdb onto the production server with -# /MIR, a full mirror, and has no idea which branch built it. So --dist from a -# site branch would replace production's frontend with unreleased work at the -# next deploy, silently, and the deploy script could not tell. +# ONE BRANCH, ONE INSTANCE, ONE DIST. The rule for this site: # -# Branch-qualifying the directory would leave the same trap for whoever pointed -# a deploy at the wrong one. Production runs the product; a site branch has no -# business producing the artefact production installs. -if [ "$BUILD_DIST" = 1 ] && [ "$BRANCH" != "main" ]; then +# wj -> /shopdb (WJ PRODUCTION) dist: frontend-dist-subpath-shopdb +# dev -> /ops (dev instance) dist: frontend-dist-subpath-ops +# main -> nothing (curated release other sites adopt) +# +# This used to build BOTH dists and refuse --dist unless you were on main, +# because production was assumed to install main. It does not: production +# installs wj. Under the old rule a wj export failed at this step and the +# dists on the share came from whichever main export happened to run next - +# so the code going to prod and the frontend going to prod came from different +# branches, silently, and the deploy scripts could not tell. +# +# Each dist now carries a .dist-source marker naming the branch, the commit and +# the time that built it. update-prod-server.cmd and update-dev-server.cmd read +# it and refuse a dist built from the wrong branch, so the trap the old comment +# worried about is closed by a check rather than by a convention. +case "$BRANCH" in + wj) DIST_BASE=shopdb ;; + dev) DIST_BASE=ops ;; + *) DIST_BASE='' ;; +esac + +if [ "$BUILD_DIST" = 1 ] && [ -z "$DIST_BASE" ]; then echo "REFUSED: --dist on branch '$BRANCH'." >&2 echo >&2 - echo "The dist directories are what update-prod-server.cmd mirrors onto the" >&2 - echo "production server, and they are not branch-qualified. Building them" >&2 - echo "from '$BRANCH' would put unreleased work on production at the next" >&2 - echo "deploy, with nothing to reveal it." >&2 + echo "Only a branch that a server actually runs builds a dist:" >&2 + echo " wj -> /shopdb (production)" >&2 + echo " dev -> /ops" >&2 echo >&2 - echo "Promote the commits to main and export from there:" >&2 - echo " tools/wj-status.sh" >&2 - echo " tools/promote-to-main.sh ..." >&2 + echo "'$BRANCH' deploys nowhere, so a dist built from it could only ever be" >&2 + echo "installed by mistake. Export it without --dist." >&2 exit 1 fi if [ "$BUILD_DIST" = 1 ]; then cd "$WORK/frontend" - for base in ops shopdb; do - VITE_BASE_PATH=/$base/ npm run build --silent - rm -rf "$OUT/frontend-dist-subpath-$base" - cp -r dist "$OUT/frontend-dist-subpath-$base" - echo "dist: $OUT/frontend-dist-subpath-$base/ (base /$base/)" - done + VITE_BASE_PATH=/$DIST_BASE/ npm run build --silent + rm -rf "$OUT/frontend-dist-subpath-$DIST_BASE" + cp -r dist "$OUT/frontend-dist-subpath-$DIST_BASE" + + # Provenance, read by the deploy scripts. A dist is a directory of hashed + # filenames with nothing in it that says where it came from, and robocopy + # /MIR will happily mirror the wrong one onto a correctly-identified server. + { + echo "branch=$BRANCH" + echo "commit=$(git -C "$WORK" rev-parse HEAD)" + echo "base=/$DIST_BASE/" + echo "built=$(date '+%Y-%m-%d %H:%M:%S %z')" + echo "host=$(hostname)" + } > "$OUT/frontend-dist-subpath-$DIST_BASE/.dist-source" + + echo "dist: $OUT/frontend-dist-subpath-$DIST_BASE/ (base /$DIST_BASE/, from $BRANCH)" fi cat <&2 + echo "Run fetch-wilm-branch.cmd on the work PC and copy it across." >&2 + exit 1 +fi + +if ! git bundle list-heads "$BUNDLE" | grep -q 'refs/remotes/origin/wilm'; then + echo "$BUNDLE does not contain origin/wilm." >&2 + echo "It is a bundle for something else - do not use it." >&2 + exit 1 +fi + +age_days=$(( ( $(date +%s) - $(stat -c %Y "$BUNDLE") ) / 86400 )) +echo "Bundle: $BUNDLE" +echo "Made: $(stat -c %y "$BUNDLE" | cut -d. -f1) (${age_days} day(s) ago)" +if [ "$age_days" -ge 2 ]; then + echo "WARNING: this bundle is ${age_days} days old. Whatever it pushes to" >&2 + echo "gitea will look current and will not be." >&2 +fi + +cd "$REPO" +git fetch "$BUNDLE" 'refs/remotes/origin/wilm:refs/heads/wilm' --force +echo "wilm is now $(git log --oneline -1 wilm)" + +# wilm sits on the PUBLICATION lineage (the scrubbed history that goes to +# GitHub), which shares no ancestor with our internal main/wj/dev. That is why +# the mirror is useful for reading and useless for merging: git will refuse to +# merge unrelated histories, and it is right to. +if ! git merge-base wilm main >/dev/null 2>&1; then + echo + echo "NOTE: wilm shares no ancestry with main/wj/dev in this repo - it is on" + echo " the publication lineage. Compare it in the publication repo" + echo " (/home/camp/projects/shopdb-flask-pub), not here." +fi + +"$REPO/tools/git-push.sh" wilm