From f9543ddd9cf120481de9075c5d4ba6a4dc681d7e Mon Sep 17 00:00:00 2001 From: danielmeppiel Date: Wed, 29 Apr 2026 12:57:52 +0200 Subject: [PATCH] fix(shared/apm): repair gh-aw \[a b\] import-input serialization PR #982 added a Compute APM credential-group matrix step that feeds `${{ github.aw.import-inputs.packages }}` to `jq --argjson`. gh-aw substitutes that template at compile time using Go's default slice formatter, which emits `[microsoft/apm#main]` (space-separated, no quotes) instead of valid JSON `["microsoft/apm#main"]`. jq rejects the malformed input and apm-prep fails, blocking every PR run of the review panel and every triage-panel labelled issue. The bug shipped latent in #982 (locks not regenerated) and surfaced in #1026 when the locks were recompiled. Pinning gh-aw does not help: the same compiler version (v0.68.3) produced both shapes -- the difference was the new compute step that started routing the substituted value through `--argjson`. Fix: add a small Bash+Python repair_string_array helper in shared/apm.md that detects malformed Go-slice strings and rewrites them as JSON before they reach jq. Already-valid JSON and 'null' pass through untouched. apps[] (object arrays) is not repairable this way -- consumers must use the legacy single-app inputs until upstream gh-aw exposes a JSON-encoding helper for import-inputs (paper-cut filed upstream). - shared/apm.md: add repair_string_array helper for AW_APM_PACKAGES - pr-review-panel.lock.yml + triage-panel.lock.yml: recompile Verified locally with the live shared/apm.md run-block against four inputs ([single], [multi space-separated], null, already-valid JSON); all produce a correctly-typed matrix.group.packages array. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/pr-review-panel.lock.yml | 20 ++++++++++++++++++++ .github/workflows/shared/apm.md | 20 ++++++++++++++++++++ .github/workflows/triage-panel.lock.yml | 20 ++++++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/.github/workflows/pr-review-panel.lock.yml b/.github/workflows/pr-review-panel.lock.yml index c34a37838..f428ba8dc 100644 --- a/.github/workflows/pr-review-panel.lock.yml +++ b/.github/workflows/pr-review-panel.lock.yml @@ -1019,6 +1019,26 @@ jobs: apps_json=${AW_APM_APPS:-null} legacy_id=${AW_APM_LEGACY_APP_ID:-} + # gh-aw substitutes `["microsoft/apm#main"]` at + # compile time using Go's default slice formatter, which emits + # `[a b c]` (space-separated, no quotes) instead of valid JSON. + # That breaks `jq --argjson` below. Repair string-array inputs + # in place; leave already-valid JSON untouched. apps[] (objects) + # is not repairable this way -- consumers must use the legacy + # single-app inputs until upstream gh-aw exposes a JSON-encoding + # helper for import-inputs. + repair_string_array() { + local raw="$1" + if [ -z "$raw" ] || [ "$raw" = "null" ]; then + echo "$raw"; return + fi + if printf '%s' "$raw" | jq -e 'type=="array"' >/dev/null 2>&1; then + echo "$raw"; return + fi + python3 -c 'import json, re, sys; s=sys.argv[1].strip(); s=s[1:-1] if s.startswith("[") and s.endswith("]") else s; print(json.dumps([t for t in re.split(r"[\s,]+", s) if t]))' "$raw" + } + packages_json=$(repair_string_array "$packages_json") + groups=$(jq -nc \ --argjson packages "$packages_json" \ --argjson apps "$apps_json" \ diff --git a/.github/workflows/shared/apm.md b/.github/workflows/shared/apm.md index d29523499..2e91fa8e1 100644 --- a/.github/workflows/shared/apm.md +++ b/.github/workflows/shared/apm.md @@ -158,6 +158,26 @@ jobs: apps_json=${AW_APM_APPS:-null} legacy_id=${AW_APM_LEGACY_APP_ID:-} + # gh-aw substitutes `${{ github.aw.import-inputs.packages }}` at + # compile time using Go's default slice formatter, which emits + # `[a b c]` (space-separated, no quotes) instead of valid JSON. + # That breaks `jq --argjson` below. Repair string-array inputs + # in place; leave already-valid JSON untouched. apps[] (objects) + # is not repairable this way -- consumers must use the legacy + # single-app inputs until upstream gh-aw exposes a JSON-encoding + # helper for import-inputs. + repair_string_array() { + local raw="$1" + if [ -z "$raw" ] || [ "$raw" = "null" ]; then + echo "$raw"; return + fi + if printf '%s' "$raw" | jq -e 'type=="array"' >/dev/null 2>&1; then + echo "$raw"; return + fi + python3 -c 'import json, re, sys; s=sys.argv[1].strip(); s=s[1:-1] if s.startswith("[") and s.endswith("]") else s; print(json.dumps([t for t in re.split(r"[\s,]+", s) if t]))' "$raw" + } + packages_json=$(repair_string_array "$packages_json") + groups=$(jq -nc \ --argjson packages "$packages_json" \ --argjson apps "$apps_json" \ diff --git a/.github/workflows/triage-panel.lock.yml b/.github/workflows/triage-panel.lock.yml index 762490886..c125e8d86 100644 --- a/.github/workflows/triage-panel.lock.yml +++ b/.github/workflows/triage-panel.lock.yml @@ -1067,6 +1067,26 @@ jobs: apps_json=${AW_APM_APPS:-null} legacy_id=${AW_APM_LEGACY_APP_ID:-} + # gh-aw substitutes `["microsoft/apm#main"]` at + # compile time using Go's default slice formatter, which emits + # `[a b c]` (space-separated, no quotes) instead of valid JSON. + # That breaks `jq --argjson` below. Repair string-array inputs + # in place; leave already-valid JSON untouched. apps[] (objects) + # is not repairable this way -- consumers must use the legacy + # single-app inputs until upstream gh-aw exposes a JSON-encoding + # helper for import-inputs. + repair_string_array() { + local raw="$1" + if [ -z "$raw" ] || [ "$raw" = "null" ]; then + echo "$raw"; return + fi + if printf '%s' "$raw" | jq -e 'type=="array"' >/dev/null 2>&1; then + echo "$raw"; return + fi + python3 -c 'import json, re, sys; s=sys.argv[1].strip(); s=s[1:-1] if s.startswith("[") and s.endswith("]") else s; print(json.dumps([t for t in re.split(r"[\s,]+", s) if t]))' "$raw" + } + packages_json=$(repair_string_array "$packages_json") + groups=$(jq -nc \ --argjson packages "$packages_json" \ --argjson apps "$apps_json" \