diff --git a/scripts/native/cicd/controller-one-shot.sh b/scripts/native/cicd/controller-one-shot.sh index 59c004f8..a7f8825e 100644 --- a/scripts/native/cicd/controller-one-shot.sh +++ b/scripts/native/cicd/controller-one-shot.sh @@ -3,8 +3,6 @@ set -eu cd /work rm -rf /work/unidesk -started_at=$(date -Iseconds) -echo "branch-follower one-shot started ${started_at}" >&2 /etc/unidesk-cicd-branch-follower/sync-source.sh \ "${UNIDESK_CONTROLLER_SOURCE_REPOSITORY}" \ @@ -16,6 +14,34 @@ git clone --branch "${UNIDESK_CONTROLLER_SOURCE_BRANCH}" "/cache/${UNIDESK_CONTR cp /etc/unidesk-cicd-branch-follower/cicd-branch-followers.yaml /work/unidesk/config/cicd-branch-followers.yaml cd /work/unidesk -"$@" +machine_output=false +for arg in "$@"; do + case "$arg" in + --json|--raw|json) + machine_output=true + ;; + esac +done -echo "branch-follower one-shot finished $(date -Iseconds)" >&2 +if [ "${machine_output}" = true ]; then + output_file=$(mktemp) + if "$@" >"${output_file}"; then + node - "${output_file}" <<'NODE' +const { readFileSync } = require("node:fs"); +const path = process.argv[2]; +const text = readFileSync(path, "utf8").trim(); +if (text.length === 0) process.exit(0); +try { + process.stdout.write(JSON.stringify(JSON.parse(text))); +} catch { + process.stdout.write(text); +} +NODE + else + status=$? + cat "${output_file}" + exit "${status}" + fi +else + "$@" +fi diff --git a/scripts/src/cicd-branch-follower.ts b/scripts/src/cicd-branch-follower.ts index 6616291c..20689382 100644 --- a/scripts/src/cicd-branch-follower.ts +++ b/scripts/src/cicd-branch-follower.ts @@ -2862,16 +2862,39 @@ function parseJsonObject(text: string): Record | null { const parsed = JSON.parse(trimmed) as unknown; return asOptionalRecord(parsed); } catch { - const start = trimmed.indexOf("{"); - const end = trimmed.lastIndexOf("}"); - if (start < 0 || end <= start) return null; - try { - const parsed = JSON.parse(trimmed.slice(start, end + 1)) as unknown; - return asOptionalRecord(parsed); - } catch { - return null; + return parseFirstJsonObject(trimmed); + } +} + +function parseFirstJsonObject(text: string): Record | null { + const start = text.indexOf("{"); + if (start < 0) return null; + let depth = 0; + let inString = false; + let escaped = false; + for (let index = start; index < text.length; index += 1) { + const char = text[index]; + if (inString) { + if (escaped) escaped = false; + else if (char === "\\") escaped = true; + else if (char === "\"") inString = false; + continue; + } + if (char === "\"") inString = true; + else if (char === "{") depth += 1; + else if (char === "}") { + depth -= 1; + if (depth === 0) { + try { + const parsed = JSON.parse(text.slice(start, index + 1)) as unknown; + return asOptionalRecord(parsed); + } catch { + return null; + } + } } } + return null; } function recordAt(root: Record, path: string[]): Record | null {