Forráskód Böngészése

feat(appctl): add `upgrade` command for tag-based deploys

Resolves `latest` (moving release tag), `test` (virtual alias for
origin/main HEAD), or any release tag, then takes the stack down,
checks out the ref detached, rebuilds, and brings everything back up
with the scheduler sidecar in detached mode.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ClaudePriv@chiappa.zhdk.ch 7 órája
szülő
commit
3fa130cc4b
1 módosított fájl, 51 hozzáadás és 0 törlés
  1. 51 0
      bin/appctl

+ 51 - 0
bin/appctl

@@ -45,6 +45,12 @@ STACK (docker compose; canonical stack is api + ui + migrate)
   appctl ps                          list stack status (incl. scheduler if running)
   appctl migrate                     run the one-shot migrate container
 
+RELEASE
+  appctl upgrade [version]           stop, fetch, checkout, build, start -d --scheduler
+                                     version defaults to the `latest` tag; `test` is a
+                                     virtual tag resolving to origin/main HEAD; otherwise
+                                     pass a release tag like v0.9.
+
 CHECKS (ephemeral containers, no running stack required)
   appctl lint   [api|ui]             composer cs (php-cs-fixer --dry-run)
   appctl stan   [api|ui]             composer stan (phpstan)
@@ -244,6 +250,50 @@ cmd_ci() {
     exec scripts/ci.sh
 }
 
+# Upgrade flow: fetch, resolve the requested version to a ref, take the
+# stack down, check out the ref (detached — tags are not branches), rebuild
+# all images, and bring everything back up with the scheduler sidecar in
+# detached mode.
+#
+# `latest` is the moving release tag (set by maintainers); `test` is a
+# virtual alias for origin/main HEAD so operators can stage unreleased work
+# without us having to push a throw-away tag for every preview.
+cmd_upgrade() {
+    local version="${1:-latest}"
+    local ref
+
+    if [[ -n "$(git status --porcelain)" ]]; then
+        die "working tree not clean — commit or stash changes before upgrading"
+    fi
+
+    printf '[appctl] fetching refs from origin\n'
+    git fetch --all --tags --prune
+
+    if [[ "$version" == "test" ]]; then
+        ref="origin/main"
+    elif git rev-parse --verify --quiet "refs/tags/$version" >/dev/null; then
+        ref="refs/tags/$version"
+    else
+        die "unknown version: $version (try: latest, test, or a release tag like v0.9)"
+    fi
+
+    local target_sha
+    target_sha="$(git rev-parse --short "$ref")"
+    printf '[appctl] upgrading to %s (%s)\n' "$version" "$target_sha"
+
+    printf '[appctl] stopping stack\n'
+    compose_full down
+
+    printf '[appctl] checking out %s\n' "$ref"
+    git checkout --detach "$ref"
+
+    printf '[appctl] building images\n'
+    compose_full build
+
+    printf '[appctl] starting stack (--scheduler, detached)\n'
+    compose_full up -d
+}
+
 # --- dispatch ---------------------------------------------------------
 
 cmd="${1:-help}"
@@ -263,6 +313,7 @@ case "$cmd" in
     audit)              cmd_audit "$@" ;;
     check)              cmd_check "$@" ;;
     ci)                 cmd_ci ;;
+    upgrade)            cmd_upgrade "$@" ;;
     help|-h|--help|"")  usage ;;
     *) die "unknown command: $cmd (try: appctl help)" ;;
 esac