gowalk-cicd 1.0.41 → 1.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CLAUDE.md CHANGED
@@ -64,6 +64,11 @@ workflow (`.github/workflows/publish.yml`):
64
64
  attach the `publish.yml` trusted-publisher relationship; the workflow
65
65
  supplies that token as a fallback and uses OIDC after trust is configured.
66
66
 
67
+ An explicitly dispatched run may publish a tested feature ref by setting its
68
+ `release` boolean input. The input defaults to false, so ordinary manual runs
69
+ remain test-only. Use this path when a deploy repair must ship without pushing
70
+ the feature branch directly to `main`.
71
+
67
72
  Manual publish (from repo root):
68
73
 
69
74
  ```bash
package/README.md CHANGED
@@ -68,6 +68,8 @@ The backend workflow runs on a GitHub-hosted runner and, on a push touching
68
68
  it rsyncs the backend dir to `/opt/gowalk-backends/<app>/`, runs
69
69
  `docker compose up -d --build`, auto-detects the published `127.0.0.1:<port>`,
70
70
  wires an nginx vhost + Let's Encrypt cert for the API domain, and health-checks.
71
+ Certificate issuance and the public health check are strict: a deploy fails if
72
+ the hostname cannot present a trusted matching certificate and reach the API.
71
73
 
72
74
  Requirements on the consumer repo:
73
75
 
@@ -84,7 +86,9 @@ Requirements on the consumer repo:
84
86
  - Repo **variables** (optional): `BACKEND_API_DOMAIN` (its DNS A record must point
85
87
  at the host for the cert; empty = deploy the container only, skip nginx/cert),
86
88
  `BACKEND_APP_NAME` (defaults to the repo name), `BACKEND_HEALTH_PATH`
87
- (default `/health`), `BACKEND_DEPLOY_HOST` (default `138.197.36.107`).
89
+ (default `/health`), `BACKEND_DEPLOY_HOST` (default `138.197.36.107`), and
90
+ `BACKEND_CERTBOT_ACCOUNT` (optional account ID for hosts with multiple ACME
91
+ accounts; otherwise the sole or host-created account is selected).
88
92
 
89
93
  The action directory is canonical here (like the iOS/Android actions): edit it in
90
94
  `backend-action/`, never in a consumer's vendored copy.
@@ -1 +1 @@
1
- 1.0.41
1
+ 1.0.42
@@ -1 +1 @@
1
- 1.0.41
1
+ 1.0.42
@@ -1 +1 @@
1
- 1.0.41
1
+ 1.0.42
@@ -39,6 +39,12 @@ inputs:
39
39
  description: Email for the Let's Encrypt registration.
40
40
  required: false
41
41
  default: "admin@gowalk.com"
42
+ certbot-account:
43
+ description: >
44
+ Optional Certbot account ID. When omitted, the deploy selects the sole
45
+ account or the account created on the current host.
46
+ required: false
47
+ default: ""
42
48
  runtime-env:
43
49
  description: >
44
50
  Optional newline-delimited KEY=value secrets written to a mode-0600
@@ -104,7 +110,8 @@ runs:
104
110
  $SSH "${{ inputs.ssh-user }}@${{ inputs.host }}" \
105
111
  "bash '$DEST/.remote_deploy.sh' \
106
112
  '${{ inputs.app-name }}' '${{ inputs.api-domain }}' \
107
- '${{ inputs.health-path }}' '${{ inputs.cert-email }}'"
113
+ '${{ inputs.health-path }}' '${{ inputs.cert-email }}' \
114
+ '${{ inputs.certbot-account }}'"
108
115
 
109
116
  - name: Cleanup key
110
117
  if: always()
@@ -8,11 +8,37 @@ APP="$1" # slug — compose project + dir name
8
8
  DOMAIN="${2:-}" # api.<app>.gowalk.com, or empty to skip nginx/cert
9
9
  HEALTH="${3:-/health}"
10
10
  CERT_EMAIL="${4:-admin@gowalk.com}"
11
+ CERT_ACCOUNT="${5:-}"
11
12
  DIR="/opt/gowalk-backends/$APP"
12
13
  cd "$DIR"
13
14
 
14
15
  log() { echo "[deploy $APP] $*"; }
15
16
 
17
+ select_certbot_account() {
18
+ [ -n "$CERT_ACCOUNT" ] && return
19
+ local accounts_root host account_dir creation_host
20
+ local -a accounts=()
21
+ accounts_root="/etc/letsencrypt/accounts/acme-v02.api.letsencrypt.org/directory"
22
+ [ -d "$accounts_root" ] || return
23
+ host="$(hostname)"
24
+ while IFS= read -r account_dir; do
25
+ accounts+=("$(basename "$account_dir")")
26
+ creation_host="$(sed -nE \
27
+ 's/.*"creation_host"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/p' \
28
+ "$account_dir/meta.json" 2>/dev/null | head -1)"
29
+ if [ "$creation_host" = "$host" ]; then
30
+ CERT_ACCOUNT="$(basename "$account_dir")"
31
+ fi
32
+ done < <(find "$accounts_root" -mindepth 1 -maxdepth 1 -type d | sort)
33
+ if [ -z "$CERT_ACCOUNT" ] && [ "${#accounts[@]}" -eq 1 ]; then
34
+ CERT_ACCOUNT="${accounts[0]}"
35
+ fi
36
+ if [ -z "$CERT_ACCOUNT" ] && [ "${#accounts[@]}" -gt 1 ]; then
37
+ log "ERROR: multiple Certbot accounts; set BACKEND_CERTBOT_ACCOUNT"
38
+ return 1
39
+ fi
40
+ }
41
+
16
42
  # ── secrets: generate a per-app .env once, then preserve it (rsync excludes it)
17
43
  if [ ! -f .env ]; then
18
44
  log "first deploy — generating .env (POSTGRES_PASSWORD)"
@@ -95,16 +121,20 @@ fi
95
121
  # ── Let's Encrypt cert (idempotent; certbot skips if current)
96
122
  if ! certbot certificates 2>/dev/null | grep -q "Domains: $DOMAIN\b"; then
97
123
  log "requesting LE cert for $DOMAIN"
124
+ select_certbot_account
125
+ CERTBOT_ARGS=()
126
+ if [ -n "$CERT_ACCOUNT" ]; then
127
+ log "using Certbot account ${CERT_ACCOUNT:0:4}…"
128
+ CERTBOT_ARGS+=(--account "$CERT_ACCOUNT")
129
+ fi
98
130
  certbot --nginx -d "$DOMAIN" --non-interactive --agree-tos \
99
- --email "$CERT_EMAIL" --redirect || log "warn: certbot failed (DNS not pointed yet?)"
131
+ --email "$CERT_EMAIL" --redirect "${CERTBOT_ARGS[@]}"
100
132
  else
101
133
  log "cert for $DOMAIN already present"
102
134
  fi
103
135
 
104
- # ── public health-check (best effort — cert/DNS may still be propagating)
105
- if curl -fsSk "https://$DOMAIN$HEALTH" >/dev/null 2>&1; then
106
- log "public https://$DOMAIN$HEALTH healthy"
107
- else
108
- log "warn: public URL not answering yet (DNS/cert propagation) — container is up on :$PORT"
109
- fi
136
+ # ── public health-check: validates DNS, certificate/SNI, routing and service.
137
+ curl -fsS --retry 6 --retry-all-errors --retry-delay 2 \
138
+ "https://$DOMAIN$HEALTH" >/dev/null
139
+ log "public https://$DOMAIN$HEALTH healthy with verified TLS"
110
140
  log "done"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gowalk-cicd",
3
- "version": "1.0.41",
3
+ "version": "1.0.42",
4
4
  "description": "Zero-config GitHub Actions delivery for iOS TestFlight and Android Google Play.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -39,4 +39,5 @@ jobs:
39
39
  api-domain: ${{ vars.BACKEND_API_DOMAIN }}
40
40
  backend-dir: ${{ steps.dir.outputs.path }}
41
41
  health-path: ${{ vars.BACKEND_HEALTH_PATH || '/health' }}
42
+ certbot-account: ${{ vars.BACKEND_CERTBOT_ACCOUNT }}
42
43
  runtime-env: ${{ secrets.BACKEND_RUNTIME_ENV }}
@@ -428,4 +428,5 @@ jobs:
428
428
  api-domain: ${{ vars.BACKEND_API_DOMAIN }}
429
429
  backend-dir: ${{ steps.dir.outputs.path }}
430
430
  health-path: ${{ vars.BACKEND_HEALTH_PATH || '/health' }}
431
+ certbot-account: ${{ vars.BACKEND_CERTBOT_ACCOUNT }}
431
432
  runtime-env: ${{ secrets.BACKEND_RUNTIME_ENV }}