Skip to content

Commit 120cfec

Browse files
committed
Add CALM json and generate mermaid and MD files for the architeture flow and the system diagram
Signed-off-by: Erick Bourgeois <erick@jeb.ca>
1 parent 39f7b88 commit 120cfec

28 files changed

Lines changed: 2060 additions & 512 deletions

.github/scripts/calm-args.bats

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
#!/usr/bin/env bats
2+
# Copyright (c) 2025 Erick Bourgeois, firestoned
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
# Unit tests for .github/scripts/calm-args.sh.
6+
# Install bats-core (brew install bats-core) and run:
7+
# bats .github/scripts/calm-args.bats
8+
9+
setup() {
10+
SCRIPT="${BATS_TEST_DIRNAME}/calm-args.sh"
11+
[ -x "$SCRIPT" ] || chmod +x "$SCRIPT"
12+
# Clear every env var the script reads so prior tests can't leak in.
13+
unset CMD ARCH PATTERN OUTPUT TEMPLATE TEMPLATE_DIR BUNDLE URL_MAP \
14+
SCHEMA_DIR HUB_URL CLEAR_OUT SCAFFOLD STRICT FORMAT VERBOSE EXTRA
15+
}
16+
17+
# ── Command validation ───────────────────────────────────────────────────────
18+
19+
@test "fails when CMD is unset" {
20+
run env -u CMD "$SCRIPT"
21+
[ "$status" -ne 0 ]
22+
[[ "$output" == *"CMD is required"* ]]
23+
}
24+
25+
@test "fails with exit 2 on unknown command" {
26+
run env CMD=deploy "$SCRIPT"
27+
[ "$status" -eq 2 ]
28+
[[ "$output" == *"Unsupported command"* ]]
29+
}
30+
31+
@test "accepts each supported command with no extra args" {
32+
for cmd in validate generate template docify; do
33+
run env CMD="$cmd" "$SCRIPT"
34+
[ "$status" -eq 0 ] || {
35+
echo "cmd=$cmd status=$status output=$output" >&2
36+
return 1
37+
}
38+
# No args emitted when nothing else is supplied.
39+
[ -z "$output" ]
40+
done
41+
}
42+
43+
# ── Flag mapping ─────────────────────────────────────────────────────────────
44+
45+
@test "architecture maps to -a" {
46+
run env CMD=template ARCH=arch.json "$SCRIPT"
47+
[ "$status" -eq 0 ]
48+
[ "${lines[0]}" = "-a" ]
49+
[ "${lines[1]}" = "arch.json" ]
50+
}
51+
52+
@test "pattern maps to -p" {
53+
run env CMD=generate PATTERN=pattern.json "$SCRIPT"
54+
[ "$status" -eq 0 ]
55+
[ "${lines[0]}" = "-p" ]
56+
[ "${lines[1]}" = "pattern.json" ]
57+
}
58+
59+
@test "output maps to -o" {
60+
run env CMD=generate OUTPUT=out.json "$SCRIPT"
61+
[ "$status" -eq 0 ]
62+
[ "${lines[0]}" = "-o" ]
63+
[ "${lines[1]}" = "out.json" ]
64+
}
65+
66+
@test "template single file maps to -t" {
67+
run env CMD=template TEMPLATE=mermaid.hbs "$SCRIPT"
68+
[ "$status" -eq 0 ]
69+
[ "${lines[0]}" = "-t" ]
70+
[ "${lines[1]}" = "mermaid.hbs" ]
71+
}
72+
73+
@test "template dir maps to -d" {
74+
run env CMD=template TEMPLATE_DIR=templates/mermaid "$SCRIPT"
75+
[ "$status" -eq 0 ]
76+
[ "${lines[0]}" = "-d" ]
77+
[ "${lines[1]}" = "templates/mermaid" ]
78+
}
79+
80+
@test "bundle maps to -b" {
81+
run env CMD=template BUNDLE=bundles/one-pager "$SCRIPT"
82+
[ "$status" -eq 0 ]
83+
[ "${lines[0]}" = "-b" ]
84+
[ "${lines[1]}" = "bundles/one-pager" ]
85+
}
86+
87+
@test "url-map maps to -u" {
88+
run env CMD=template URL_MAP=urlmap.json "$SCRIPT"
89+
[ "$status" -eq 0 ]
90+
[ "${lines[0]}" = "-u" ]
91+
[ "${lines[1]}" = "urlmap.json" ]
92+
}
93+
94+
@test "schema-directory maps to -s" {
95+
run env CMD=validate SCHEMA_DIR=./calm/release "$SCRIPT"
96+
[ "$status" -eq 0 ]
97+
[ "${lines[0]}" = "-s" ]
98+
[ "${lines[1]}" = "./calm/release" ]
99+
}
100+
101+
@test "calm-hub-url maps to -c" {
102+
run env CMD=validate HUB_URL=https://hub.example.com "$SCRIPT"
103+
[ "$status" -eq 0 ]
104+
[ "${lines[0]}" = "-c" ]
105+
[ "${lines[1]}" = "https://hub.example.com" ]
106+
}
107+
108+
# ── Boolean scoping ──────────────────────────────────────────────────────────
109+
110+
@test "clear-output maps to --clear-output-directory when true" {
111+
run env CMD=template CLEAR_OUT=true "$SCRIPT"
112+
[ "$status" -eq 0 ]
113+
[ "${lines[0]}" = "--clear-output-directory" ]
114+
}
115+
116+
@test "clear-output is omitted when false" {
117+
run env CMD=template CLEAR_OUT=false "$SCRIPT"
118+
[ "$status" -eq 0 ]
119+
[ -z "$output" ]
120+
}
121+
122+
@test "scaffold is emitted only for docify" {
123+
run env CMD=docify SCAFFOLD=true "$SCRIPT"
124+
[ "$status" -eq 0 ]
125+
[[ "$output" == *"--scaffold"* ]]
126+
127+
run env CMD=template SCAFFOLD=true "$SCRIPT"
128+
[ "$status" -eq 0 ]
129+
[[ "$output" != *"--scaffold"* ]]
130+
}
131+
132+
@test "strict is emitted only for validate" {
133+
run env CMD=validate STRICT=true "$SCRIPT"
134+
[ "$status" -eq 0 ]
135+
[[ "$output" == *"--strict"* ]]
136+
137+
run env CMD=generate STRICT=true "$SCRIPT"
138+
[ "$status" -eq 0 ]
139+
[[ "$output" != *"--strict"* ]]
140+
}
141+
142+
@test "format is emitted only for validate" {
143+
run env CMD=validate FORMAT=junit "$SCRIPT"
144+
[ "$status" -eq 0 ]
145+
# Find "-f" then "junit" as consecutive lines.
146+
found=0
147+
for i in "${!lines[@]}"; do
148+
if [ "${lines[$i]}" = "-f" ] && [ "${lines[$((i+1))]}" = "junit" ]; then
149+
found=1; break
150+
fi
151+
done
152+
[ "$found" -eq 1 ]
153+
154+
run env CMD=template FORMAT=junit "$SCRIPT"
155+
[ "$status" -eq 0 ]
156+
[[ "$output" != *"-f"* ]]
157+
}
158+
159+
@test "verbose maps to -v" {
160+
run env CMD=validate VERBOSE=true "$SCRIPT"
161+
[ "$status" -eq 0 ]
162+
[[ "$output" == *"-v"* ]]
163+
}
164+
165+
@test "verbose default (unset) emits nothing" {
166+
run env CMD=validate "$SCRIPT"
167+
[ "$status" -eq 0 ]
168+
[ -z "$output" ]
169+
}
170+
171+
# ── Extra args passthrough ───────────────────────────────────────────────────
172+
173+
@test "extra args are word-split and appended" {
174+
run env CMD=template EXTRA="--foo bar --baz" "$SCRIPT"
175+
[ "$status" -eq 0 ]
176+
[ "${lines[0]}" = "--foo" ]
177+
[ "${lines[1]}" = "bar" ]
178+
[ "${lines[2]}" = "--baz" ]
179+
}
180+
181+
# ── End-to-end compositions ──────────────────────────────────────────────────
182+
183+
@test "validate with architecture, strict, format, and verbose" {
184+
run env CMD=validate ARCH=arch.json STRICT=true FORMAT=pretty VERBOSE=true "$SCRIPT"
185+
[ "$status" -eq 0 ]
186+
[[ "$output" == *"-a"* ]]
187+
[[ "$output" == *"arch.json"* ]]
188+
[[ "$output" == *"--strict"* ]]
189+
[[ "$output" == *"-f"* ]]
190+
[[ "$output" == *"pretty"* ]]
191+
[[ "$output" == *"-v"* ]]
192+
}
193+
194+
@test "generate with pattern and output" {
195+
run env CMD=generate PATTERN=p.json OUTPUT=a.json "$SCRIPT"
196+
[ "$status" -eq 0 ]
197+
[[ "$output" == *"-p"* ]]
198+
[[ "$output" == *"p.json"* ]]
199+
[[ "$output" == *"-o"* ]]
200+
[[ "$output" == *"a.json"* ]]
201+
}
202+
203+
@test "template with architecture, template-dir, output, clear" {
204+
run env CMD=template ARCH=a.json TEMPLATE_DIR=tpl OUTPUT=out CLEAR_OUT=true "$SCRIPT"
205+
[ "$status" -eq 0 ]
206+
[[ "$output" == *"-a"* ]]
207+
[[ "$output" == *"-d"* ]]
208+
[[ "$output" == *"tpl"* ]]
209+
[[ "$output" == *"-o"* ]]
210+
[[ "$output" == *"out"* ]]
211+
[[ "$output" == *"--clear-output-directory"* ]]
212+
}
213+
214+
@test "docify scaffold mode" {
215+
run env CMD=docify ARCH=a.json OUTPUT=site SCAFFOLD=true "$SCRIPT"
216+
[ "$status" -eq 0 ]
217+
[[ "$output" == *"-a"* ]]
218+
[[ "$output" == *"a.json"* ]]
219+
[[ "$output" == *"-o"* ]]
220+
[[ "$output" == *"site"* ]]
221+
[[ "$output" == *"--scaffold"* ]]
222+
}
223+
224+
@test "values with spaces survive word-preservation for named flags" {
225+
# ARCH may include spaces; script must pass it through as a single arg.
226+
run env CMD=template ARCH="my arch.json" "$SCRIPT"
227+
[ "$status" -eq 0 ]
228+
[ "${lines[0]}" = "-a" ]
229+
[ "${lines[1]}" = "my arch.json" ]
230+
}
231+
232+
@test "output line count matches exactly for a minimal invocation" {
233+
run env CMD=validate ARCH=a.json "$SCRIPT"
234+
[ "$status" -eq 0 ]
235+
[ "${#lines[@]}" -eq 2 ]
236+
}

.github/scripts/calm-args.sh

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#!/usr/bin/env bash
2+
# Copyright (c) 2025 Erick Bourgeois, firestoned
3+
# SPDX-License-Identifier: Apache-2.0
4+
#
5+
# Builds the argument list for `calm <CMD>` from environment variables.
6+
# Prints one argument per line on stdout so callers can read into an array:
7+
#
8+
# mapfile -t args < <(CMD=validate ARCH=x.json calm-args.sh)
9+
# calm "$CMD" "${args[@]}"
10+
#
11+
# Exit codes:
12+
# 0 success
13+
# 2 CMD unset or not one of: validate | generate | template | docify
14+
#
15+
# Inputs (environment):
16+
# CMD required — validate | generate | template | docify
17+
# ARCH -a <path> (template, docify, validate)
18+
# PATTERN -p <file|url> (generate, validate)
19+
# OUTPUT -o <path> (all)
20+
# TEMPLATE -t <file> (template, docify)
21+
# TEMPLATE_DIR -d <dir> (template, docify)
22+
# BUNDLE -b <dir> (template)
23+
# URL_MAP -u <file> (template, docify)
24+
# SCHEMA_DIR -s <dir> (generate, validate)
25+
# HUB_URL -c <url> (generate, validate)
26+
# CLEAR_OUT "true" -> --clear-output-directory (template, docify)
27+
# SCAFFOLD "true" -> --scaffold (docify only)
28+
# STRICT "true" -> --strict (validate only)
29+
# FORMAT -f <json|junit|pretty> (validate only)
30+
# VERBOSE "true" -> -v
31+
# EXTRA raw additional args, word-split
32+
set -euo pipefail
33+
34+
: "${CMD:?CMD is required (validate | generate | template | docify)}"
35+
36+
case "$CMD" in
37+
validate|generate|template|docify) ;;
38+
*)
39+
echo "Unsupported command: $CMD (expected: validate, generate, template, docify)" >&2
40+
exit 2
41+
;;
42+
esac
43+
44+
declare -a args=()
45+
46+
[[ -n "${ARCH:-}" ]] && args+=(-a "$ARCH")
47+
[[ -n "${PATTERN:-}" ]] && args+=(-p "$PATTERN")
48+
[[ -n "${OUTPUT:-}" ]] && args+=(-o "$OUTPUT")
49+
[[ -n "${TEMPLATE:-}" ]] && args+=(-t "$TEMPLATE")
50+
[[ -n "${TEMPLATE_DIR:-}" ]] && args+=(-d "$TEMPLATE_DIR")
51+
[[ -n "${BUNDLE:-}" ]] && args+=(-b "$BUNDLE")
52+
[[ -n "${URL_MAP:-}" ]] && args+=(-u "$URL_MAP")
53+
[[ -n "${SCHEMA_DIR:-}" ]] && args+=(-s "$SCHEMA_DIR")
54+
[[ -n "${HUB_URL:-}" ]] && args+=(-c "$HUB_URL")
55+
56+
[[ "${CLEAR_OUT:-false}" == "true" ]] && args+=(--clear-output-directory)
57+
[[ "${SCAFFOLD:-false}" == "true" && "$CMD" == "docify" ]] && args+=(--scaffold)
58+
[[ "${STRICT:-false}" == "true" && "$CMD" == "validate" ]] && args+=(--strict)
59+
60+
if [[ "$CMD" == "validate" && -n "${FORMAT:-}" ]]; then
61+
args+=(-f "$FORMAT")
62+
fi
63+
64+
[[ "${VERBOSE:-false}" == "true" ]] && args+=(-v)
65+
66+
if [[ -n "${EXTRA:-}" ]]; then
67+
# shellcheck disable=SC2206
68+
extra_arr=($EXTRA)
69+
args+=("${extra_arr[@]}")
70+
fi
71+
72+
if [[ ${#args[@]} -gt 0 ]]; then
73+
printf '%s\n' "${args[@]}"
74+
fi

0 commit comments

Comments
 (0)