From 36285e25ca4115700016b3a6a23bc0aebb92b610 Mon Sep 17 00:00:00 2001 From: mignot Date: Wed, 2 Sep 2026 17:01:18 +0200 Subject: [PATCH 1/5] fix(trigger-coolify-deploy): accept nanoid-style deployment_uuid MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Coolify's deployments API now returns nanoid-style ids (e.g. j9rlp1cg3qdsuqi8sqsvykpo) instead of canonical UUIDs for deployment_uuid. The format-validation regex in cancel_phantom_builds() only accepted UUIDs, so it warned and skipped every phantom build, leaving the still-running native build uncancelled and occupying the VPS's single build slot — the exact failure mode PR #144's fix was meant to prevent (confirmed in the-music-deck-admin PR #208 logs, both preview deploys timed out at 1800s). Widen the regex to accept both formats, bounded to 20-30 alphanumeric chars to preserve the shape check before the value is interpolated into a Coolify API URL and an SSH docker stop command. Add a standalone regression test for the regex plus a CI workflow to run it. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01LzDQzX3Uqv3qChoZyXx5hv --- .../actions/trigger-coolify-deploy/action.yml | 5 +-- .../tests/deployment_uuid_format.sh | 33 +++++++++++++++++++ .github/workflows/test-actions.yml | 16 +++++++++ 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100755 .github/actions/trigger-coolify-deploy/tests/deployment_uuid_format.sh create mode 100644 .github/workflows/test-actions.yml diff --git a/.github/actions/trigger-coolify-deploy/action.yml b/.github/actions/trigger-coolify-deploy/action.yml index 969d7e4..2870c5b 100644 --- a/.github/actions/trigger-coolify-deploy/action.yml +++ b/.github/actions/trigger-coolify-deploy/action.yml @@ -184,8 +184,9 @@ runs: # deployment_uuid comes from the Coolify API response — validate its shape # before using it in a URL or SSH command, in case Coolify ever returns - # something malformed. - if ! printf '%s' "$phantom_uuid" | grep -qiE '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$'; then + # something malformed. Accepts both the legacy UUID format and Coolify's + # newer nanoid-style ids (e.g. j9rlp1cg3qdsuqi8sqsvykpo). + if ! printf '%s' "$phantom_uuid" | grep -qiE '^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-z]{20,30})$'; then echo " WARNING: unexpected deployment_uuid format '${phantom_uuid}', skipping" continue fi diff --git a/.github/actions/trigger-coolify-deploy/tests/deployment_uuid_format.sh b/.github/actions/trigger-coolify-deploy/tests/deployment_uuid_format.sh new file mode 100755 index 0000000..8708266 --- /dev/null +++ b/.github/actions/trigger-coolify-deploy/tests/deployment_uuid_format.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# Regression test for the deployment_uuid/phantom_uuid format check in action.yml +# (cancel_phantom_builds). Keeps this in sync with the regex at that call site — +# if you change one, change both. +set -euo pipefail + +PATTERN='^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-z]{20,30})$' + +check() { + local value="$1" expect="$2" label="$3" + if printf '%s' "$value" | grep -qiE "$PATTERN"; then + actual=accept + else + actual=reject + fi + if [ "$actual" != "$expect" ]; then + echo "FAIL: $label — expected $expect, got $actual for '${value}'" + exit 1 + fi + echo "ok: $label" +} + +check "a1b2c3d4-e5f6-7890-abcd-ef1234567890" accept "legacy UUID" +check "A1B2C3D4-E5F6-7890-ABCD-EF1234567890" accept "legacy UUID, uppercase" +check "j9rlp1cg3qdsuqi8sqsvykpo" accept "Coolify nanoid-style id (24 chars)" +check "abcdefghijklmnopqrst" accept "nanoid-style id, 20 chars (lower bound)" +check "abcdefghijklmnopqrstuvwxyzabcd" accept "nanoid-style id, 30 chars (upper bound)" +check "not a valid id!" reject "garbage with spaces/punctuation" +check "" reject "empty string" +check "abc123" reject "too short to be a nanoid" +check "abcdefghijklmnopqrstuvwxyzabcde" reject "31 chars, over the bound" + +echo "All deployment_uuid format checks passed." diff --git a/.github/workflows/test-actions.yml b/.github/workflows/test-actions.yml new file mode 100644 index 0000000..6f00db7 --- /dev/null +++ b/.github/workflows/test-actions.yml @@ -0,0 +1,16 @@ +name: Test actions + +on: + push: + branches: [main, master] + pull_request: + +jobs: + trigger-coolify-deploy-tests: + name: trigger-coolify-deploy shell tests + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - name: Run deployment_uuid format tests + run: .github/actions/trigger-coolify-deploy/tests/deployment_uuid_format.sh From 23f041bc8894aa4dd808a96cff86ea9a09db5a68 Mon Sep 17 00:00:00 2001 From: mignot Date: Wed, 2 Sep 2026 17:06:32 +0200 Subject: [PATCH 2/5] fix(trigger-coolify-deploy): use bash regex for whole-string match grep -qiE matches per-line, so a newline embedded in phantom_uuid could let a later line slip past the ^...$ anchors even though the value is interpolated into a Coolify API URL and an SSH docker stop command. Switch to bash's [[ =~ ]] so the anchors apply to the whole string. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01LzDQzX3Uqv3qChoZyXx5hv --- .github/actions/trigger-coolify-deploy/action.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/actions/trigger-coolify-deploy/action.yml b/.github/actions/trigger-coolify-deploy/action.yml index 2870c5b..455672a 100644 --- a/.github/actions/trigger-coolify-deploy/action.yml +++ b/.github/actions/trigger-coolify-deploy/action.yml @@ -185,8 +185,9 @@ runs: # deployment_uuid comes from the Coolify API response — validate its shape # before using it in a URL or SSH command, in case Coolify ever returns # something malformed. Accepts both the legacy UUID format and Coolify's - # newer nanoid-style ids (e.g. j9rlp1cg3qdsuqi8sqsvykpo). - if ! printf '%s' "$phantom_uuid" | grep -qiE '^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-z]{20,30})$'; then + # newer nanoid-style ids (e.g. j9rlp1cg3qdsuqi8sqsvykpo). Uses a bash regex + # match (not grep) so ^...$ anchors the whole string, not per-line. + if ! [[ "$phantom_uuid" =~ ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|[0-9a-z]{20,30})$ ]]; then echo " WARNING: unexpected deployment_uuid format '${phantom_uuid}', skipping" continue fi From 779a7172664d61bc1489370133ed8aee991a1964 Mon Sep 17 00:00:00 2001 From: mignot Date: Wed, 2 Sep 2026 17:06:32 +0200 Subject: [PATCH 3/5] fix(trigger-coolify-deploy): align test with bash-regex validation Use bash's [[ =~ ]] instead of grep -qiE to match the fix in action.yml, and declare `actual` local so the test function stays self-contained under set -u. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01LzDQzX3Uqv3qChoZyXx5hv --- .../trigger-coolify-deploy/tests/deployment_uuid_format.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/trigger-coolify-deploy/tests/deployment_uuid_format.sh b/.github/actions/trigger-coolify-deploy/tests/deployment_uuid_format.sh index 8708266..f4ee2fd 100755 --- a/.github/actions/trigger-coolify-deploy/tests/deployment_uuid_format.sh +++ b/.github/actions/trigger-coolify-deploy/tests/deployment_uuid_format.sh @@ -4,11 +4,11 @@ # if you change one, change both. set -euo pipefail -PATTERN='^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-z]{20,30})$' +PATTERN='^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|[0-9a-z]{20,30})$' check() { - local value="$1" expect="$2" label="$3" - if printf '%s' "$value" | grep -qiE "$PATTERN"; then + local value="$1" expect="$2" label="$3" actual + if [[ "$value" =~ $PATTERN ]]; then actual=accept else actual=reject From 6dd04503573ba6a2d868ed7455a0b5fcda055315 Mon Sep 17 00:00:00 2001 From: mignot Date: Wed, 2 Sep 2026 17:10:26 +0200 Subject: [PATCH 4/5] fix(trigger-coolify-deploy): invoke test script via bash explicitly Running it as a bare file path depends on the executable bit surviving checkout; invoking via bash is robust regardless of file mode. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01LzDQzX3Uqv3qChoZyXx5hv --- .github/workflows/test-actions.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-actions.yml b/.github/workflows/test-actions.yml index 6f00db7..b143500 100644 --- a/.github/workflows/test-actions.yml +++ b/.github/workflows/test-actions.yml @@ -13,4 +13,4 @@ jobs: - uses: actions/checkout@v5 - name: Run deployment_uuid format tests - run: .github/actions/trigger-coolify-deploy/tests/deployment_uuid_format.sh + run: bash .github/actions/trigger-coolify-deploy/tests/deployment_uuid_format.sh From 5847cbd1c38a77c80c0ab64f17d4d3dbf8893975 Mon Sep 17 00:00:00 2001 From: mignot Date: Wed, 2 Sep 2026 17:10:26 +0200 Subject: [PATCH 5/5] fix(trigger-coolify-deploy): reference phantom_uuid, not deployment_uuid, in comment/log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The comment and warning message named deployment_uuid, but the variable actually being validated and logged is phantom_uuid — fix the naming to avoid confusion when debugging cancellations. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01LzDQzX3Uqv3qChoZyXx5hv --- .github/actions/trigger-coolify-deploy/action.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/trigger-coolify-deploy/action.yml b/.github/actions/trigger-coolify-deploy/action.yml index 455672a..596bcb0 100644 --- a/.github/actions/trigger-coolify-deploy/action.yml +++ b/.github/actions/trigger-coolify-deploy/action.yml @@ -182,13 +182,13 @@ runs: phantom_uuid=$(printf '%s' "$phantom" | jq -r '.deployment_uuid') phantom_status=$(printf '%s' "$phantom" | jq -r '.status') - # deployment_uuid comes from the Coolify API response — validate its shape + # phantom_uuid comes from the Coolify API response — validate its shape # before using it in a URL or SSH command, in case Coolify ever returns # something malformed. Accepts both the legacy UUID format and Coolify's # newer nanoid-style ids (e.g. j9rlp1cg3qdsuqi8sqsvykpo). Uses a bash regex # match (not grep) so ^...$ anchors the whole string, not per-line. if ! [[ "$phantom_uuid" =~ ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}|[0-9a-z]{20,30})$ ]]; then - echo " WARNING: unexpected deployment_uuid format '${phantom_uuid}', skipping" + echo " WARNING: unexpected phantom_uuid format '${phantom_uuid}', skipping" continue fi