gowalk-cicd 1.0.179 → 1.0.181
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/README.md
CHANGED
|
@@ -284,11 +284,11 @@ Requirements on the consumer repo:
|
|
|
284
284
|
never bake secrets in. A generated `.env` (with `POSTGRES_PASSWORD`) is created
|
|
285
285
|
on the host on first deploy and preserved across deploys (rsync excludes it).
|
|
286
286
|
- Repo **secret** `BACKEND_DEPLOY_SSH_KEY` (a private key with access to the host).
|
|
287
|
-
- Repo **variable** `BACKEND_DEPLOY_KNOWN_HOSTS` (
|
|
287
|
+
- Repo **variable** `BACKEND_DEPLOY_KNOWN_HOSTS` (required): trusted `known_hosts` lines for the exact
|
|
288
288
|
host string the workflow connects to (`BACKEND_DEPLOY_HOST`, for example
|
|
289
|
-
`
|
|
290
|
-
(`StrictHostKeyChecking=yes`).
|
|
291
|
-
|
|
289
|
+
`backend.example.com ssh-ed25519 AAAA...`). Deploys require that key
|
|
290
|
+
(`StrictHostKeyChecking=yes`). Missing pins refuse with `backend_host_key_required` before SSH
|
|
291
|
+
or writing the private key; the action never discovers and trusts an unverified host key.
|
|
292
292
|
- Repo **secret** `BACKEND_RUNTIME_ENV` (optional): newline-delimited `KEY=value`
|
|
293
293
|
runtime secrets. The action writes it as mode 0600 on the host and passes it
|
|
294
294
|
to Compose without copying values into the repository or action log.
|
|
@@ -22,7 +22,8 @@ Non-fatal by design: any failure is reported as a ::warning:: and the action
|
|
|
22
22
|
continues. The TestFlight upload itself has already succeeded by this point.
|
|
23
23
|
|
|
24
24
|
Environment:
|
|
25
|
-
ASC_KEY_ID, ASC_ISSUER_ID
|
|
25
|
+
ASC_KEY_ID, ASC_ISSUER_ID -- App Store Connect API identity
|
|
26
|
+
ASC_KEY_PATH / ASC_KEY_P8_PATH -- existing or prepared key-file path
|
|
26
27
|
MARKETING_VERSION -- e.g. "1.2.3"
|
|
27
28
|
APP_STORE_VERSION_ID -- appStoreVersion id (REUSE or CREATE)
|
|
28
29
|
APP_STORE_WHATS_NEW_FILE -- path to file holding release notes
|
|
@@ -228,16 +229,10 @@ def _update_all_localizations(
|
|
|
228
229
|
token: str, version_id: str, version: str, whats_new: str, seed_locale: str,
|
|
229
230
|
only_if_empty: bool = False,
|
|
230
231
|
) -> int:
|
|
231
|
-
"""
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
When ``only_if_empty`` is set the text is a fallback backstop: any
|
|
236
|
-
localization that already has a non-blank whatsNew (e.g. notes a human
|
|
237
|
-
entered) is left untouched, and only empty ones are filled. This lets the
|
|
238
|
-
step run unconditionally without clobbering good content, while still
|
|
239
|
-
guaranteeing no locale ships with an empty "What's New" (which App Store
|
|
240
|
-
Connect rejects as "This field is required")."""
|
|
232
|
+
"""Write localized notes, creating one seed when no localizations exist.
|
|
233
|
+
Return the count written. ``only_if_empty`` preserves existing non-blank
|
|
234
|
+
notes and fills the empty text App Store Connect requires before review.
|
|
235
|
+
"""
|
|
241
236
|
locs = get_json(
|
|
242
237
|
f"/appStoreVersions/{version_id}/appStoreVersionLocalizations", token
|
|
243
238
|
)
|
|
@@ -306,7 +301,7 @@ def main() -> int:
|
|
|
306
301
|
token = make_jwt(
|
|
307
302
|
_require_env("ASC_KEY_ID"),
|
|
308
303
|
_require_env("ASC_ISSUER_ID"),
|
|
309
|
-
|
|
304
|
+
os.environ.get("ASC_KEY_PATH", "").strip() or _require_env("ASC_KEY_P8_PATH"),
|
|
310
305
|
)
|
|
311
306
|
|
|
312
307
|
ver = get_json(f"/appStoreVersions/{version_id}", token)
|
|
@@ -36,8 +36,8 @@ inputs:
|
|
|
36
36
|
known-hosts:
|
|
37
37
|
description: >
|
|
38
38
|
known_hosts lines pinning the deploy host's key (vars.BACKEND_DEPLOY_KNOWN_HOSTS).
|
|
39
|
-
|
|
40
|
-
required:
|
|
39
|
+
Required before SSH; missing pins refuse without network discovery.
|
|
40
|
+
required: true
|
|
41
41
|
default: ""
|
|
42
42
|
app-name:
|
|
43
43
|
description: Stable slug — the compose project and /opt/gowalk-backends/<app-name> dir.
|
|
@@ -160,15 +160,14 @@ runs:
|
|
|
160
160
|
set -euo pipefail
|
|
161
161
|
source "${{ github.action_path }}/deploy_evidence.sh"
|
|
162
162
|
BACKEND_DEPLOY_PHASE=configure_ssh
|
|
163
|
+
if [[ ! "${KNOWN_HOSTS:-}" =~ [^[:space:]] ]]; then
|
|
164
|
+
echo "::error title=backend_host_key_required::Configure the backend binding's trusted SSH host key"
|
|
165
|
+
exit 1
|
|
166
|
+
fi
|
|
163
167
|
mkdir -p ~/.ssh && chmod 700 ~/.ssh
|
|
164
168
|
printf '%s\n' "$DEPLOY_SSH_KEY" > ~/.ssh/backend_deploy
|
|
165
169
|
chmod 600 ~/.ssh/backend_deploy
|
|
166
|
-
|
|
167
|
-
printf '%s\n' "$KNOWN_HOSTS" > ~/.ssh/known_hosts
|
|
168
|
-
else
|
|
169
|
-
echo "::warning title=backend_host_key_unpinned::BACKEND_DEPLOY_KNOWN_HOSTS is empty; trusting the key ssh-keyscan returns"
|
|
170
|
-
ssh-keyscan -t ed25519,rsa,ecdsa "${{ inputs.host }}" >> ~/.ssh/known_hosts 2>/dev/null
|
|
171
|
-
fi
|
|
170
|
+
printf '%s\n' "$KNOWN_HOSTS" > ~/.ssh/known_hosts
|
|
172
171
|
chmod 644 ~/.ssh/known_hosts
|
|
173
172
|
|
|
174
173
|
- name: Sync backend to the host
|
|
@@ -16,6 +16,7 @@ OWNERS = Path('/var/lib/gowalk-backend-ownership')
|
|
|
16
16
|
APPS = Path('/opt/gowalk-backends')
|
|
17
17
|
INGRESS = Path('/opt/gowalk-backend-ingress')
|
|
18
18
|
ROOT_UID = 0
|
|
19
|
+
PLATFORM = ['docker', 'info', '--format', '{{.OSType}}/{{.Architecture}}']
|
|
19
20
|
READY = ('command -v docker >/dev/null && docker info >/dev/null 2>&1 '
|
|
20
21
|
'&& docker compose version >/dev/null 2>&1')
|
|
21
22
|
|
|
@@ -143,6 +144,15 @@ def readiness():
|
|
|
143
144
|
return 0
|
|
144
145
|
|
|
145
146
|
|
|
147
|
+
def platform():
|
|
148
|
+
result = subprocess.run(PLATFORM, capture_output=True, text=True, timeout=15, check=True)
|
|
149
|
+
value = result.stdout.strip()
|
|
150
|
+
if not re.fullmatch('[a-zA-Z0-9_-]+/[a-zA-Z0-9_-]+', value):
|
|
151
|
+
raise ValueError('ssh_platform_invalid')
|
|
152
|
+
print(value)
|
|
153
|
+
return 0
|
|
154
|
+
|
|
155
|
+
|
|
146
156
|
def main():
|
|
147
157
|
try:
|
|
148
158
|
os.umask(0o077)
|
|
@@ -151,6 +161,8 @@ def main():
|
|
|
151
161
|
command = os.environ.get('SSH_ORIGINAL_COMMAND', '')
|
|
152
162
|
if ' '.join(command.split()) in (READY, 'gowalk-backend readiness'):
|
|
153
163
|
return readiness()
|
|
164
|
+
if shlex.split(command) == PLATFORM:
|
|
165
|
+
return platform()
|
|
154
166
|
if policy.get('disabled', True):
|
|
155
167
|
raise ValueError('ssh_backend_disabled')
|
|
156
168
|
project, may_claim, arguments = plan(command)
|
package/docs/BACKEND_SSH_GATE.md
CHANGED
|
@@ -9,7 +9,7 @@ needed for the transport protocol below.
|
|
|
9
9
|
Each panel gets its own dedicated SSH key. Its `authorized_keys` entry uses `restrict` and a fixed owner:
|
|
10
10
|
|
|
11
11
|
```text
|
|
12
|
-
restrict,command="/usr/bin/python3 /opt/gowalk-cicd-runtime/1.0.
|
|
12
|
+
restrict,command="/usr/bin/python3 /opt/gowalk-cicd-runtime/1.0.180/backend-action/ssh_gate.py robot" ssh-ed25519 <key>
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
Keep operator and release credentials separate. Never install an unrestricted backend key as a fallback.
|
|
@@ -24,7 +24,7 @@ Create root-owned mode-0600 `/etc/gowalk-backend-ssh.json`:
|
|
|
24
24
|
}
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
`disabled: true` refuses every mutation while permitting the read-only readiness
|
|
27
|
+
`disabled: true` refuses every mutation while permitting the read-only readiness and platform probes. Keep it set
|
|
28
28
|
through migration and validation. Existing per-app runtime `disabled` profiles remain an independent
|
|
29
29
|
start fence when the global transport gate opens.
|
|
30
30
|
|
|
@@ -38,6 +38,7 @@ provisioning without a manual allowlist update; existing ownership and private d
|
|
|
38
38
|
The entry permits only:
|
|
39
39
|
|
|
40
40
|
- the panel's exact existing Docker/Compose readiness probe, or `gowalk-backend readiness`;
|
|
41
|
+
- exactly `docker info --format '{{.OSType}}/{{.Architecture}}'` for real deployment-platform discovery;
|
|
41
42
|
- scoped app-directory creation and the action's rsync **receiver** protocol inside that app;
|
|
42
43
|
- the standard private runtime environment and edge-input receive envelopes;
|
|
43
44
|
- the standard backend deploy invocation, redirected to the host-owned released helper;
|