#!/usr/bin/env bash # Cut a client-ready branch out of main: .env.example defaults set to only # that client's licensed features, internal-only files stripped. # # Usage: # scripts/export_client.sh [--push ] # # Flags are the VITE_ALLOW_ACCESS_ suffixes already used in # .env.example: EFFICIENCY, PFI, RELIABILITY, RISK_MATRIX, LCCA, RBD, OH, # IRCFA, AHM. auth/dashboard/admin/ops-dock have no flag and always ship. # # Example: # scripts/export_client.sh client-a EFFICIENCY,PFI # scripts/export_client.sh client-a EFFICIENCY,PFI --push git@gitlab.client-a.com/fe-digitaltwin-v2.git # # Unlike the backend, this does NOT remove any src/features or src/pages # folders — router/index.tsx statically imports every page regardless of # flags (they're still code-split via lazy(), just all reachable by direct # URL). Flags only hide nav entries. See GIT_BRANCHES.md for what that # does and doesn't protect. set -euo pipefail cd "$(dirname "${BASH_SOURCE[0]}")/.." ALL_FLAGS=(EFFICIENCY PFI RELIABILITY RISK_MATRIX LCCA RBD OH IRCFA AHM) CLIENT_SLUG="${1:-}" FLAGS_CSV="${2:-}" PUSH_REMOTE="" if [ "${3:-}" = "--push" ]; then PUSH_REMOTE="${4:-}" fi if [ -z "$CLIENT_SLUG" ] || [ -z "$FLAGS_CSV" ]; then echo "Usage: $0 [--push ]" echo "Available flags: ${ALL_FLAGS[*]}" exit 1 fi if [ -n "$(git status --porcelain)" ]; then echo "Working tree isn't clean. Commit or stash before exporting." exit 1 fi BRANCH="client/${CLIENT_SLUG}" IFS=',' read -ra SELECTED_FLAGS <<< "$FLAGS_CSV" for f in "${SELECTED_FLAGS[@]}"; do known=false for a in "${ALL_FLAGS[@]}"; do [ "$f" = "$a" ] && known=true; done if [ "$known" = false ]; then echo "Unknown flag '${f}'. Available: ${ALL_FLAGS[*]}" exit 1 fi done echo "==> Building ${BRANCH} from main with flags: ${FLAGS_CSV}" git checkout -q -B "$BRANCH" main # --- 1. Set .env.example defaults so a plain `cp .env.example .env` on the # client's side turns on only what they licensed. Does not touch a # real .env — that's gitignored and never part of any branch. --- FLAGS_CSV="$FLAGS_CSV" python3 - <<'PYEOF' import os import re selected = set(os.environ["FLAGS_CSV"].split(",")) path = ".env.example" with open(path) as f: content = f.read() def set_flag(match): key = match.group(1) value = "true" if key in selected else "false" return f"VITE_ALLOW_ACCESS_{key}={value}" content = re.sub(r"VITE_ALLOW_ACCESS_(\w+)=\w+", set_flag, content) with open(path, "w") as f: f.write(content) PYEOF # --- 2. Internal-only files that don't belong in a client's pipeline --- [ -f Jenkinsfile ] && { git rm -q Jenkinsfile || rm -f Jenkinsfile; } [ -d memory ] && { git rm -rq memory || rm -rf memory; } # dev notes, migration log [ -d ref ] && { git rm -rq ref || rm -rf ref; } # PRD docs, reference screenshots [ -d scripts ] && { git rm -rq scripts 2>/dev/null || rm -rf scripts; } true git add -A git commit -q -m "Export for ${CLIENT_SLUG}: ${FLAGS_CSV}" # --- 3. Merge in this client's permanent overlay branch, if one exists --- # See GIT_BRANCHES.md — overlay/ is an orphan branch, no shared # history with main, holding only what's unique to this client: routes # under src/router/overlay/, or other new files. Kept to additions only. OVERLAY_BRANCH="overlay/${CLIENT_SLUG}" if git show-ref --verify --quiet "refs/heads/${OVERLAY_BRANCH}"; then echo "==> Merging ${OVERLAY_BRANCH}" if ! git merge --no-edit --allow-unrelated-histories -m "Merge ${OVERLAY_BRANCH} into ${BRANCH}" "$OVERLAY_BRANCH"; then echo echo "Merging ${OVERLAY_BRANCH} conflicted — that means it touched a file" echo "the base export also generates or already ships, which defeats the" echo "point of an overlay. Resolve it here (or 'git merge --abort'), then" echo "keep the overlay to new files only going forward." exit 1 fi fi # --- 4. Guard: same idea as be-digitaltwin's — catch a leaked engine # mention. Not a load-bearing check here (this repo talks to the # engine only indirectly, through the backend's API), but cheap # and consistent to keep. --- if git grep -niE '\baimo\b' -- . ; then echo "^^ literal mention found — this must stay generic." exit 1 fi # --- 5. Non-fatal: known gap this script does not fix. See GIT_BRANCHES.md. --- if git grep -lqiE 'Logo_PLN|logo-tjb' -- src public 2>/dev/null; then echo echo "NOTE: this export still ships PLN/TJB-specific branding assets and" echo "hardcoded references (logos, plant names). That's a real content" echo "change, not something this script attempts — see GIT_BRANCHES.md." fi echo echo "==> ${BRANCH} is ready ($(git rev-parse --short HEAD))." if [ -n "$PUSH_REMOTE" ]; then echo "==> Pushing to ${PUSH_REMOTE}" git push "$PUSH_REMOTE" "${BRANCH}:main" else echo "Push manually when ready, e.g.:" echo " git push ${BRANCH}:main" fi git checkout -q main