#!/usr/bin/env bash # sync-theme.sh — pull a theme from the web_themes repo into this consumer. # # Usage: # bash scripts/sync-theme.sh [theme-name] # # Environment overrides: # WEB_THEMES_REPO git URL of the web_themes repo. # Default: git@tangled.org:psingletary.com/web_themes # (SSH — requires a Tangled key at build time). For CI or # machines without a key, use the HTTPS form: # WEB_THEMES_REPO=https://tangled.org/psingletary.com/web_themes # THEME_DEST destination dir relative to repo root (default: src/styles/theme) # THEME_CONTRACT 0 to skip the post-sync contract check (default: 1) # # Strategy (build-time pull): shallow-clone the themes repo into a per-user # cache (~/.cache/web_themes), then copy the requested theme's files into the # consumer's src tree. After copying, the theme contract is enforced (every # var() token in the consumer's CSS must resolve) so a breaking theme change # fails the consumer build at the commit that broke it. Consumers wire this # as a prebuild step: # # "build": "npm run sync:theme && react-scripts build" # # Requires SSH access to Tangled at build time (Apple Keychain on this Mac) # unless WEB_THEMES_REPO is overridden to HTTPS. set -euo pipefail THEME_NAME="${1:-witchsky-cyan}" REPO="${WEB_THEMES_REPO:-git@tangled.org:psingletary.com/web_themes}" DEST="${THEME_DEST:-src/styles/theme}" CACHE_DIR="${HOME}/.cache/web_themes" if [ -d "${CACHE_DIR}/.git" ]; then # Cache must track the requested repo even if it was cloned from # a different URL before (e.g. a local path during testing). if [ "$(git -C "${CACHE_DIR}" config --get remote.origin.url)" != "${REPO}" ]; then git -C "${CACHE_DIR}" remote set-url origin "${REPO}" fi git -C "${CACHE_DIR}" fetch --quiet --depth 1 origin main git -C "${CACHE_DIR}" reset --quiet --hard origin/main else git clone --quiet --depth 1 --branch main "${REPO}" "${CACHE_DIR}" fi mkdir -p "${DEST}" cp "${CACHE_DIR}/themes/${THEME_NAME}/theme.css" "${DEST}/theme.css" cp "${CACHE_DIR}/themes/${THEME_NAME}/index.css" "${DEST}/index.css" echo "synced web_themes/${THEME_NAME} -> ${DEST}/" # Contract check: fail the build if the consumer's CSS uses a token the # theme (or the consumer's own CSS) does not define. Skip with THEME_CONTRACT=0. if [ "${THEME_CONTRACT:-1}" = "1" ]; then HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT="$(cd "${HERE}/.." && pwd)" if [ -x "${HERE}/theme-contract.sh" ]; then bash "${HERE}/theme-contract.sh" --consumer "${ROOT}/src" "${ROOT}/${DEST}/theme.css" else echo "sync-theme: theme-contract.sh not found next to sync-theme.sh — copy both scripts from web_themes" >&2 exit 1 fi fi