initial
This commit is contained in:
Executable
+110
@@ -0,0 +1,110 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Build an installable WordPress plugin ZIP for Reservair.
|
||||
#
|
||||
# Produces dist/reservair-<version>.zip containing a single top-level
|
||||
# `reservair/` directory with ONLY the runtime files: the compiled Gutenberg
|
||||
# block assets and production-only Composer dependencies.
|
||||
#
|
||||
# The build runs in an isolated temp directory, so it never touches your
|
||||
# working-tree vendor/ or node_modules/ — safe to run locally or in CI.
|
||||
#
|
||||
# Usage:
|
||||
# ./bin/build-zip.sh
|
||||
#
|
||||
# Environment overrides:
|
||||
# OUTPUT_DIR directory the final zip is written to (default: <repo>/dist)
|
||||
# SKIP_JS "1" to reuse the existing build/ dir (default: build fresh)
|
||||
# KEEP_TMP "1" to keep the temp build dir for debug (default: removed)
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
# --- locate repo root (this script lives in <root>/bin) ----------------------
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
SLUG="reservair"
|
||||
OUTPUT_DIR="${OUTPUT_DIR:-$ROOT_DIR/dist}"
|
||||
|
||||
log() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
|
||||
die() { printf '\033[1;31mERROR:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
# --- prerequisites -----------------------------------------------------------
|
||||
need() { command -v "$1" >/dev/null 2>&1 || die "'$1' is required but not installed"; }
|
||||
need composer
|
||||
need zip
|
||||
need rsync
|
||||
[ "${SKIP_JS:-0}" = "1" ] || need npm
|
||||
|
||||
# --- read version from the plugin header (single source of truth) ------------
|
||||
# `read` consumes only the first match and avoids a `| head` pipe (which would
|
||||
# SIGPIPE the upstream sed under `pipefail` and abort the script with code 141).
|
||||
VERSION=""
|
||||
read -r VERSION < <(sed -n 's/^[[:space:]]*\*\{0,1\}[[:space:]]*Version:[[:space:]]*\([^[:space:]]*\).*/\1/p' "$ROOT_DIR/$SLUG.php") || true
|
||||
[ -n "$VERSION" ] || die "could not read 'Version:' header from $SLUG.php"
|
||||
log "Packaging $SLUG version $VERSION"
|
||||
|
||||
# --- isolated build dir (never touches your working vendor/ or node_modules) -
|
||||
TMP_DIR="$(mktemp -d)"
|
||||
BUILD_DIR="$TMP_DIR/src"
|
||||
STAGE_DIR="$TMP_DIR/stage/$SLUG"
|
||||
cleanup() { [ "${KEEP_TMP:-0}" = "1" ] || rm -rf "$TMP_DIR"; }
|
||||
trap cleanup EXIT
|
||||
mkdir -p "$BUILD_DIR" "$STAGE_DIR"
|
||||
|
||||
# --- copy the source tree into the isolated build dir ------------------------
|
||||
log "Copying source into isolated build dir"
|
||||
rsync -a \
|
||||
--exclude='.git/' \
|
||||
--exclude='node_modules/' \
|
||||
--exclude='vendor/' \
|
||||
--exclude='build/' \
|
||||
--exclude='dist/' \
|
||||
--exclude='.wp-env.json' \
|
||||
./ "$BUILD_DIR/"
|
||||
|
||||
# --- compile the Gutenberg block (src/ -> build/) ----------------------------
|
||||
if [ "${SKIP_JS:-0}" = "1" ]; then
|
||||
[ -d "$ROOT_DIR/build" ] || die "SKIP_JS=1 but no build/ exists — run 'npm run build' first"
|
||||
log "SKIP_JS=1 — reusing existing build/"
|
||||
cp -R "$ROOT_DIR/build" "$BUILD_DIR/build"
|
||||
else
|
||||
log "Installing JS deps and building block assets"
|
||||
( cd "$BUILD_DIR" && npm ci && npm run build )
|
||||
fi
|
||||
|
||||
# --- install production-only PHP deps + regenerate autoloader ----------------
|
||||
# This strips psalm/phpstan/wordpress-core etc. and rebuilds the classmap that
|
||||
# loads the plugin's own includes/ classes — vendor/ is required at runtime.
|
||||
log "Installing production Composer dependencies"
|
||||
( cd "$BUILD_DIR" && composer install \
|
||||
--no-dev --optimize-autoloader --classmap-authoritative \
|
||||
--no-interaction --no-progress )
|
||||
|
||||
# --- stage only the runtime files -------------------------------------------
|
||||
log "Staging runtime files"
|
||||
RUNTIME=( "$SLUG.php" admin.php uninstall.php readme.txt includes modules build assets vendor )
|
||||
for item in "${RUNTIME[@]}"; do
|
||||
if [ -e "$BUILD_DIR/$item" ]; then
|
||||
cp -R "$BUILD_DIR/$item" "$STAGE_DIR/"
|
||||
else
|
||||
log " (skipping missing $item)"
|
||||
fi
|
||||
done
|
||||
|
||||
# --- fail loudly if anything essential is missing ----------------------------
|
||||
for required in "$SLUG.php" vendor/autoload.php build/block.json; do
|
||||
[ -e "$STAGE_DIR/$required" ] || die "packaging incomplete: missing $required"
|
||||
done
|
||||
|
||||
# --- zip it ------------------------------------------------------------------
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
ZIP_PATH="$OUTPUT_DIR/${SLUG}-${VERSION}.zip"
|
||||
rm -f "$ZIP_PATH"
|
||||
log "Creating $ZIP_PATH"
|
||||
( cd "$TMP_DIR/stage" && zip -rq "$ZIP_PATH" "$SLUG" -x '*.DS_Store' )
|
||||
|
||||
log "Done → $ZIP_PATH"
|
||||
# `|| true` keeps an early-closing `head` (SIGPIPE) from failing the script.
|
||||
unzip -l "$ZIP_PATH" | tail -n +2 | head -n 12 || true
|
||||
Reference in New Issue
Block a user