|
|
@@ -41,9 +41,13 @@ DEV
|
|
|
appctl dev logs tail logs from the dev stack
|
|
|
|
|
|
PROD
|
|
|
- appctl prod start start prod stack detached
|
|
|
- appctl prod stop stop and remove prod containers
|
|
|
- appctl prod build rebuild prod images
|
|
|
+ appctl prod start start prod stack detached
|
|
|
+ appctl prod stop stop and remove prod containers
|
|
|
+ appctl prod build rebuild prod images
|
|
|
+ appctl prod upgrade [VER] stop, fetch, checkout VER, rebuild, start
|
|
|
+ VER defaults to the `latest` git tag;
|
|
|
+ `test` is a virtual keyword that resolves
|
|
|
+ to origin/main HEAD after fetch.
|
|
|
|
|
|
CHECKS (one-shot containers, no running stack required)
|
|
|
appctl lint php -l on src/ + tests/
|
|
|
@@ -127,15 +131,67 @@ cmd_dev() {
|
|
|
|
|
|
cmd_prod() {
|
|
|
local sub="${1:-}"
|
|
|
+ shift || true
|
|
|
case "$sub" in
|
|
|
- start) "${COMPOSE_PROD[@]}" up -d ;;
|
|
|
- stop) "${COMPOSE_PROD[@]}" down ;;
|
|
|
- build) "${COMPOSE_PROD[@]}" build ;;
|
|
|
+ start) "${COMPOSE_PROD[@]}" up -d ;;
|
|
|
+ stop) "${COMPOSE_PROD[@]}" down ;;
|
|
|
+ build) "${COMPOSE_PROD[@]}" build ;;
|
|
|
+ upgrade) cmd_prod_upgrade "$@" ;;
|
|
|
""|help|-h|--help) usage ;;
|
|
|
- *) die "unknown prod subcommand: $sub (try: start|stop|build)" ;;
|
|
|
+ *) die "unknown prod subcommand: $sub (try: start|stop|build|upgrade)" ;;
|
|
|
esac
|
|
|
}
|
|
|
|
|
|
+# Pinned redeploy. Resolves VER (default `latest` tag; `test` ⇒ origin/main
|
|
|
+# HEAD after fetch) to a commit, then runs: stop → fetch → checkout →
|
|
|
+# build → start. Dirty trees prompt before any destructive step.
|
|
|
+cmd_prod_upgrade() {
|
|
|
+ local version="${1:-latest}"
|
|
|
+
|
|
|
+ if [[ -n "$(git status --porcelain)" ]]; then
|
|
|
+ printf 'appctl: working tree has uncommitted changes:\n' >&2
|
|
|
+ git status --short >&2
|
|
|
+ printf '\nThe checkout step will fail or clobber these. Continue anyway? [y/N] ' >&2
|
|
|
+ local reply
|
|
|
+ read -r reply || reply=""
|
|
|
+ case "$reply" in
|
|
|
+ y|Y|yes|YES) ;;
|
|
|
+ *) die "aborted by user (working tree dirty)" ;;
|
|
|
+ esac
|
|
|
+ fi
|
|
|
+
|
|
|
+ printf 'appctl: git fetch --tags origin...\n'
|
|
|
+ git fetch --tags origin
|
|
|
+
|
|
|
+ local target_ref
|
|
|
+ if [[ "$version" == "test" ]]; then
|
|
|
+ target_ref="origin/main"
|
|
|
+ else
|
|
|
+ target_ref="$version"
|
|
|
+ fi
|
|
|
+
|
|
|
+ if ! git rev-parse --verify --quiet "${target_ref}^{commit}" >/dev/null; then
|
|
|
+ die "unknown version: '$version' (expected a release tag, 'latest', or 'test')"
|
|
|
+ fi
|
|
|
+ local target_sha
|
|
|
+ target_sha="$(git rev-parse --short "${target_ref}^{commit}")"
|
|
|
+ printf 'appctl: upgrading to %s (%s)\n' "$version" "$target_sha"
|
|
|
+
|
|
|
+ printf 'appctl: stopping prod stack...\n'
|
|
|
+ "${COMPOSE_PROD[@]}" down
|
|
|
+
|
|
|
+ printf 'appctl: git checkout --detach %s...\n' "$target_ref"
|
|
|
+ git checkout --detach "$target_ref"
|
|
|
+
|
|
|
+ printf 'appctl: building prod images...\n'
|
|
|
+ "${COMPOSE_PROD[@]}" build
|
|
|
+
|
|
|
+ printf 'appctl: starting prod stack...\n'
|
|
|
+ "${COMPOSE_PROD[@]}" up -d
|
|
|
+
|
|
|
+ printf 'appctl: upgrade to %s (%s) complete.\n' "$version" "$target_sha"
|
|
|
+}
|
|
|
+
|
|
|
cmd_lint() {
|
|
|
"${COMPOSE_DEV[@]}" --profile test run --rm tests \
|
|
|
sh -c 'find src tests -name "*.php" -print0 | xargs -0 -n1 -P 4 php -l > /dev/null && echo "lint: OK"'
|