container-superposition 0.1.6 → 0.1.7
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/dist/scripts/init.js +7 -4
- package/dist/scripts/init.js.map +1 -1
- package/dist/tool/commands/adopt.d.ts.map +1 -1
- package/dist/tool/commands/adopt.js +1 -27
- package/dist/tool/commands/adopt.js.map +1 -1
- package/dist/tool/commands/doctor.d.ts +3 -0
- package/dist/tool/commands/doctor.d.ts.map +1 -1
- package/dist/tool/commands/doctor.js +932 -69
- package/dist/tool/commands/doctor.js.map +1 -1
- package/dist/tool/commands/explain.d.ts.map +1 -1
- package/dist/tool/commands/explain.js +9 -0
- package/dist/tool/commands/explain.js.map +1 -1
- package/dist/tool/questionnaire/composer.d.ts.map +1 -1
- package/dist/tool/questionnaire/composer.js +212 -11
- package/dist/tool/questionnaire/composer.js.map +1 -1
- package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
- package/dist/tool/schema/overlay-loader.js +1 -0
- package/dist/tool/schema/overlay-loader.js.map +1 -1
- package/dist/tool/schema/project-config.d.ts +1 -1
- package/dist/tool/schema/project-config.d.ts.map +1 -1
- package/dist/tool/schema/project-config.js +94 -25
- package/dist/tool/schema/project-config.js.map +1 -1
- package/dist/tool/schema/types.d.ts +85 -11
- package/dist/tool/schema/types.d.ts.map +1 -1
- package/dist/tool/utils/merge.d.ts.map +1 -1
- package/dist/tool/utils/merge.js +9 -0
- package/dist/tool/utils/merge.js.map +1 -1
- package/docs/creating-overlays.md +151 -2
- package/docs/overlay-imports.md +125 -102
- package/docs/overlays.md +49 -6
- package/docs/quick-reference.md +99 -0
- package/docs/specs/003-mkdocs2-overlay/spec.md +114 -0
- package/docs/specs/004-doctor-fix/spec.md +70 -0
- package/docs/specs/005-cuda-overlay/spec.md +101 -0
- package/docs/specs/006-rocm-overlay/spec.md +109 -0
- package/overlays/.shared/README.md +80 -21
- package/overlays/.shared/compose/common-healthchecks.md +60 -0
- package/overlays/.shared/vscode/recommended-extensions.json +15 -11
- package/overlays/alertmanager/setup.sh +4 -19
- package/overlays/alertmanager/verify.sh +8 -9
- package/overlays/all/README.md +43 -0
- package/overlays/all/devcontainer.patch.json +6 -0
- package/overlays/all/overlay.yml +14 -0
- package/overlays/amp/setup.sh +5 -0
- package/overlays/bun/setup.sh +10 -1
- package/overlays/bun/verify.sh +6 -1
- package/overlays/claude-code/setup.sh +5 -0
- package/overlays/cloudflared/setup.sh +9 -12
- package/overlays/codex/README.md +9 -6
- package/overlays/codex/devcontainer.patch.json +7 -1
- package/overlays/codex/setup.sh +5 -0
- package/overlays/codex/verify.sh +8 -0
- package/overlays/commitlint/setup.sh +5 -0
- package/overlays/cuda/README.md +179 -0
- package/overlays/cuda/devcontainer.patch.json +7 -0
- package/overlays/cuda/overlay.yml +17 -0
- package/overlays/cuda/setup.sh +32 -0
- package/overlays/cuda/verify.sh +38 -0
- package/overlays/devcontainer-cli/README.md +50 -0
- package/overlays/devcontainer-cli/devcontainer.patch.json +13 -0
- package/overlays/devcontainer-cli/overlay.yml +16 -0
- package/overlays/devcontainer-cli/setup.sh +14 -0
- package/overlays/direnv/devcontainer.patch.json +6 -0
- package/overlays/direnv/setup.sh +7 -6
- package/overlays/dotnet/setup.sh +14 -7
- package/overlays/duckdb/devcontainer.patch.json +1 -2
- package/overlays/gcloud/devcontainer.patch.json +0 -6
- package/overlays/gcloud/setup.sh +51 -0
- package/overlays/gemini-cli/setup.sh +5 -0
- package/overlays/git-helpers/devcontainer.patch.json +2 -1
- package/overlays/go/setup.sh +15 -14
- package/overlays/jaeger/overlay.yml +2 -0
- package/overlays/just/setup.sh +5 -17
- package/overlays/keycloak/docker-compose.yml +6 -4
- package/overlays/keycloak/verify.sh +4 -3
- package/overlays/kind/devcontainer.patch.json +1 -2
- package/overlays/kind/setup.sh +8 -17
- package/overlays/minio/setup.sh +10 -18
- package/overlays/mkdocs/overlay.yml +2 -1
- package/overlays/mkdocs2/README.md +135 -0
- package/overlays/mkdocs2/devcontainer.patch.json +19 -0
- package/overlays/mkdocs2/overlay.yml +17 -0
- package/overlays/mkdocs2/setup.sh +67 -0
- package/overlays/mkdocs2/verify.sh +35 -0
- package/overlays/modern-cli-tools/devcontainer.patch.json +7 -1
- package/overlays/modern-cli-tools/setup.sh +21 -71
- package/overlays/mongodb/devcontainer.patch.json +0 -6
- package/overlays/mongodb/setup.sh +59 -0
- package/overlays/mysql/verify.sh +4 -3
- package/overlays/nats/.env.example +1 -1
- package/overlays/nats/README.md +1 -1
- package/overlays/nats/docker-compose.yml +1 -1
- package/overlays/ngrok/setup.sh +9 -6
- package/overlays/nodejs/setup.sh +5 -0
- package/overlays/openapi-tools/devcontainer.patch.json +1 -2
- package/overlays/openapi-tools/setup.sh +9 -8
- package/overlays/opencode/setup.sh +5 -0
- package/overlays/otel-collector/overlay.yml +2 -0
- package/overlays/otel-collector/setup.sh +3 -16
- package/overlays/otel-demo-nodejs/verify.sh +8 -9
- package/overlays/otel-demo-python/verify.sh +16 -10
- package/overlays/pandoc/README.md +22 -15
- package/overlays/pandoc/devcontainer.patch.json +6 -2
- package/overlays/pandoc/setup.sh +217 -18
- package/overlays/pandoc/verify.sh +16 -4
- package/overlays/playwright/devcontainer.patch.json +3 -1
- package/overlays/playwright/setup.sh +37 -0
- package/overlays/postgres/docker-compose.yml +6 -0
- package/overlays/powershell/setup.sh +49 -13
- package/overlays/pre-commit/setup.sh +12 -3
- package/overlays/prometheus/overlay.yml +2 -0
- package/overlays/promtail/verify.sh +16 -10
- package/overlays/pulumi/devcontainer.patch.json +1 -1
- package/overlays/python/setup.sh +28 -9
- package/overlays/python/verify.sh +4 -2
- package/overlays/redpanda/docker-compose.yml +3 -5
- package/overlays/rocm/README.md +227 -0
- package/overlays/rocm/devcontainer.patch.json +4 -0
- package/overlays/rocm/overlay.yml +17 -0
- package/overlays/rocm/setup.sh +45 -0
- package/overlays/rocm/verify.sh +47 -0
- package/overlays/rust/setup.sh +11 -18
- package/overlays/spec-kit/setup.sh +7 -3
- package/overlays/sqlite/setup.sh +14 -14
- package/overlays/sqlserver/docker-compose.yml +3 -3
- package/overlays/sqlserver/verify.sh +22 -5
- package/overlays/tempo/verify.sh +16 -10
- package/overlays/tilt/devcontainer.patch.json +1 -2
- package/overlays/tilt/setup.sh +14 -4
- package/overlays/windsurf-cli/setup.sh +27 -4
- package/overlays/windsurf-cli/verify.sh +13 -3
- package/package.json +2 -1
- package/templates/scripts/setup-utils.sh +228 -0
- package/tool/schema/config.schema.json +110 -8
- package/tool/schema/overlay-manifest.schema.json +5 -0
- package/overlays/.shared/compose/common-healthchecks.yml +0 -38
- /package/overlays/otel-demo-nodejs/{Dockerfile-otel-demo-nodejs → Dockerfile} +0 -0
- /package/overlays/otel-demo-nodejs/{package-otel-demo-nodejs.json → package.json} +0 -0
- /package/overlays/otel-demo-nodejs/{server-otel-demo-nodejs.js → server.js} +0 -0
- /package/overlays/otel-demo-nodejs/{tracing-otel-demo-nodejs.js → tracing.js} +0 -0
- /package/overlays/otel-demo-python/{Dockerfile-otel-demo-python → Dockerfile} +0 -0
- /package/overlays/otel-demo-python/{app-otel-demo-python.py → app.py} +0 -0
- /package/overlays/otel-demo-python/{requirements-otel-demo-python.txt → requirements.txt} +0 -0
package/overlays/pandoc/setup.sh
CHANGED
|
@@ -4,18 +4,23 @@
|
|
|
4
4
|
set -e
|
|
5
5
|
|
|
6
6
|
echo "📦 Refreshing font cache..."
|
|
7
|
-
sudo fc-cache -
|
|
7
|
+
sudo fc-cache -f
|
|
8
8
|
|
|
9
9
|
echo "📦 Installing Pandoc (latest release)..."
|
|
10
10
|
PANDOC_VERSION="3.6.4"
|
|
11
11
|
|
|
12
|
+
# Source shared setup utilities
|
|
13
|
+
# shellcheck source=setup-utils.sh
|
|
14
|
+
source "$(dirname "${BASH_SOURCE[0]}")/setup-utils.sh"
|
|
15
|
+
load_nvm
|
|
16
|
+
|
|
12
17
|
if command -v apt-get > /dev/null 2>&1; then
|
|
13
18
|
# Debian/Ubuntu — install official .deb from GitHub releases
|
|
14
19
|
ARCH=$(dpkg --print-architecture)
|
|
15
20
|
PANDOC_DEB="pandoc-${PANDOC_VERSION}-1-${ARCH}.deb"
|
|
16
21
|
curl -fsSL "https://github.com/jgm/pandoc/releases/download/${PANDOC_VERSION}/${PANDOC_DEB}" \
|
|
17
22
|
-o "/tmp/${PANDOC_DEB}"
|
|
18
|
-
sudo dpkg -i "/tmp/${PANDOC_DEB}"
|
|
23
|
+
with_apt_lock sudo dpkg -i "/tmp/${PANDOC_DEB}"
|
|
19
24
|
rm "/tmp/${PANDOC_DEB}"
|
|
20
25
|
elif command -v apk > /dev/null 2>&1; then
|
|
21
26
|
# Alpine Linux — install via apk (version may differ from pinned release)
|
|
@@ -26,7 +31,50 @@ else
|
|
|
26
31
|
exit 1
|
|
27
32
|
fi
|
|
28
33
|
|
|
29
|
-
|
|
34
|
+
if [ -x /usr/bin/pandoc ]; then
|
|
35
|
+
PANDOC_REAL_BIN="/usr/bin/pandoc"
|
|
36
|
+
elif [ -x /usr/local/bin/pandoc ] && [ ! -L /usr/local/bin/pandoc ]; then
|
|
37
|
+
PANDOC_REAL_BIN="/usr/local/bin/pandoc"
|
|
38
|
+
else
|
|
39
|
+
PANDOC_REAL_BIN="$(type -P pandoc || true)"
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
if [ -z "$PANDOC_REAL_BIN" ] || [ ! -x "$PANDOC_REAL_BIN" ]; then
|
|
43
|
+
echo "❌ Could not resolve the real pandoc binary."
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
if [ "$PANDOC_REAL_BIN" = "/usr/local/bin/pandoc" ] && [ -f /usr/local/bin/pandoc ]; then
|
|
48
|
+
if grep -q 'DEFAULTS_FILE="\${HOME}/.pandoc/pandoc.yaml"' /usr/local/bin/pandoc 2>/dev/null; then
|
|
49
|
+
echo "❌ Refusing to wrap /usr/local/bin/pandoc because it is already the pandoc wrapper."
|
|
50
|
+
exit 1
|
|
51
|
+
fi
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
echo "✓ pandoc $("$PANDOC_REAL_BIN" --version | head -1)"
|
|
55
|
+
|
|
56
|
+
echo "📦 Installing pandoc wrapper with default PDF settings..."
|
|
57
|
+
sudo tee /usr/local/bin/pandoc > /dev/null <<EOF
|
|
58
|
+
#!/bin/sh
|
|
59
|
+
REAL_PANDOC="${PANDOC_REAL_BIN}"
|
|
60
|
+
DEFAULTS_FILE="\${HOME}/.pandoc/pandoc.yaml"
|
|
61
|
+
|
|
62
|
+
for arg in "\$@"; do
|
|
63
|
+
case "\$arg" in
|
|
64
|
+
-d|--defaults|--defaults=*)
|
|
65
|
+
exec "\${REAL_PANDOC}" "\$@"
|
|
66
|
+
;;
|
|
67
|
+
esac
|
|
68
|
+
done
|
|
69
|
+
|
|
70
|
+
if [ -f "\${DEFAULTS_FILE}" ]; then
|
|
71
|
+
exec "\${REAL_PANDOC}" --defaults "\${DEFAULTS_FILE}" "\$@"
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
exec "\${REAL_PANDOC}" "\$@"
|
|
75
|
+
EOF
|
|
76
|
+
sudo chmod +x /usr/local/bin/pandoc
|
|
77
|
+
echo "✓ pandoc wrapper installed: /usr/local/bin/pandoc -> ${PANDOC_REAL_BIN}"
|
|
30
78
|
|
|
31
79
|
echo "📦 Installing diagram.lua Lua filter..."
|
|
32
80
|
mkdir -p "$HOME/.pandoc/filters"
|
|
@@ -34,17 +82,167 @@ curl -fsSL \
|
|
|
34
82
|
"https://raw.githubusercontent.com/pandoc-ext/diagram/main/_extensions/diagram/diagram.lua" \
|
|
35
83
|
-o "$HOME/.pandoc/filters/diagram.lua"
|
|
36
84
|
|
|
85
|
+
echo "📦 Writing emoji fallback Lua filter..."
|
|
86
|
+
cat > "$HOME/.pandoc/filters/emoji-fallback.lua" <<'EOF'
|
|
87
|
+
-- Replace emoji and flag glyphs that XeLaTeX commonly cannot render.
|
|
88
|
+
--
|
|
89
|
+
-- * BMP symbols (Miscellaneous Symbols U+2600-U+26FF, Dingbats U+2700-U+27BF)
|
|
90
|
+
-- are routed to the fallback font via \textfallback{} so they render as
|
|
91
|
+
-- real glyphs using Noto Sans Symbols 2 (declared by pandoc's fallbackfont
|
|
92
|
+
-- variable in pandoc.yaml).
|
|
93
|
+
--
|
|
94
|
+
-- * High-plane emoji (U+1F000-U+1FAFF: 🎉 🚀 etc.) are replaced with the
|
|
95
|
+
-- plain-text marker [emoji] because no common PDF font covers them fully.
|
|
96
|
+
--
|
|
97
|
+
-- * Flag sequences (pairs of regional-indicator letters: 🇺🇸 etc.) are
|
|
98
|
+
-- replaced with the two-letter country code in brackets, e.g. [US].
|
|
99
|
+
--
|
|
100
|
+
-- The filter is a no-op for all non-LaTeX output formats.
|
|
101
|
+
|
|
102
|
+
local REGIONAL_INDICATOR_A = 0x1F1E6
|
|
103
|
+
local REGIONAL_INDICATOR_Z = 0x1F1FF
|
|
104
|
+
|
|
105
|
+
local function is_regional_indicator(cp)
|
|
106
|
+
return cp >= REGIONAL_INDICATOR_A and cp <= REGIONAL_INDICATOR_Z
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
-- High-plane emoji that no standard PDF font renders reliably.
|
|
110
|
+
local function is_high_plane_emoji(cp)
|
|
111
|
+
return cp >= 0x1F000 and cp <= 0x1FAFF
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
-- BMP symbol blocks absent from Carlito (and most body fonts).
|
|
115
|
+
-- Characters in these ranges are routed to the \textfallback font instead.
|
|
116
|
+
local function is_bmp_symbol(cp)
|
|
117
|
+
return (cp >= 0x2600 and cp <= 0x26FF) -- Miscellaneous Symbols (⚠ ☀ ⛔ …)
|
|
118
|
+
or (cp >= 0x2700 and cp <= 0x27BF) -- Dingbats (✅ ❌ ✓ …)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
-- Parse text into a list of pandoc inline elements, applying substitutions.
|
|
122
|
+
-- Returns nil when no substitutions are needed.
|
|
123
|
+
local function text_to_inlines(text)
|
|
124
|
+
if FORMAT ~= 'latex' then return nil end
|
|
125
|
+
|
|
126
|
+
-- Quick scan: skip AST work when there is nothing to process.
|
|
127
|
+
local needs_processing = false
|
|
128
|
+
for _, cp in utf8.codes(text) do
|
|
129
|
+
if is_regional_indicator(cp) or is_high_plane_emoji(cp) or is_bmp_symbol(cp)
|
|
130
|
+
or cp == 0x200D or cp == 0x20E3 or cp == 0xFE0F then
|
|
131
|
+
needs_processing = true
|
|
132
|
+
break
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
if not needs_processing then return nil end
|
|
136
|
+
|
|
137
|
+
local codepoints = {}
|
|
138
|
+
for _, cp in utf8.codes(text) do table.insert(codepoints, cp) end
|
|
139
|
+
|
|
140
|
+
local inlines = {}
|
|
141
|
+
local buf = {}
|
|
142
|
+
|
|
143
|
+
local function flush_buf()
|
|
144
|
+
if #buf > 0 then
|
|
145
|
+
table.insert(inlines, pandoc.Str(table.concat(buf)))
|
|
146
|
+
buf = {}
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
local i = 1
|
|
151
|
+
while i <= #codepoints do
|
|
152
|
+
local cp = codepoints[i]
|
|
153
|
+
|
|
154
|
+
-- Variation selectors / zero-width joiners / combining enclosing keycap
|
|
155
|
+
if cp == 0x200D or cp == 0x20E3 or cp == 0xFE0F then
|
|
156
|
+
i = i + 1
|
|
157
|
+
|
|
158
|
+
-- Flag sequences: two consecutive regional-indicator letters → [XX]
|
|
159
|
+
elseif is_regional_indicator(cp)
|
|
160
|
+
and i < #codepoints
|
|
161
|
+
and is_regional_indicator(codepoints[i + 1]) then
|
|
162
|
+
flush_buf()
|
|
163
|
+
local a = string.char((cp - REGIONAL_INDICATOR_A) + string.byte('A'))
|
|
164
|
+
local b = string.char((codepoints[i + 1] - REGIONAL_INDICATOR_A) + string.byte('A'))
|
|
165
|
+
table.insert(inlines, pandoc.Str('[' .. a .. b .. ']'))
|
|
166
|
+
i = i + 2
|
|
167
|
+
|
|
168
|
+
-- High-plane emoji → [emoji] text marker
|
|
169
|
+
elseif is_high_plane_emoji(cp) then
|
|
170
|
+
flush_buf()
|
|
171
|
+
table.insert(inlines, pandoc.Str('[emoji]'))
|
|
172
|
+
i = i + 1
|
|
173
|
+
-- Collapse consecutive emoji into one marker
|
|
174
|
+
while i <= #codepoints
|
|
175
|
+
and (is_high_plane_emoji(codepoints[i])
|
|
176
|
+
or codepoints[i] == 0xFE0F
|
|
177
|
+
or codepoints[i] == 0x200D) do
|
|
178
|
+
i = i + 1
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
-- BMP symbols → \textfallback{char} (renders with Noto Sans Symbols 2)
|
|
182
|
+
elseif is_bmp_symbol(cp) then
|
|
183
|
+
flush_buf()
|
|
184
|
+
table.insert(inlines, pandoc.RawInline('latex',
|
|
185
|
+
'\\textfallback{' .. utf8.char(cp) .. '}'))
|
|
186
|
+
i = i + 1
|
|
187
|
+
-- Skip trailing variation selector-16 (e.g. U+FE0F after ⚠)
|
|
188
|
+
if i <= #codepoints and codepoints[i] == 0xFE0F then i = i + 1 end
|
|
189
|
+
|
|
190
|
+
else
|
|
191
|
+
table.insert(buf, utf8.char(cp))
|
|
192
|
+
i = i + 1
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
flush_buf()
|
|
196
|
+
|
|
197
|
+
-- If result is a single identical Str, nothing actually changed.
|
|
198
|
+
if #inlines == 1 and inlines[1].t == 'Str' and inlines[1].text == text then
|
|
199
|
+
return nil
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
return inlines
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
function Str(el)
|
|
206
|
+
local inlines = text_to_inlines(el.text)
|
|
207
|
+
if inlines == nil then return nil end
|
|
208
|
+
return inlines
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
-- In code spans / code blocks we cannot use \textfallback (verbatim context),
|
|
212
|
+
-- so we simply drop the offending characters to prevent XeLaTeX warnings.
|
|
213
|
+
local function strip_unsupported(el)
|
|
214
|
+
if FORMAT ~= 'latex' then return nil end
|
|
215
|
+
local changed = false
|
|
216
|
+
local out = {}
|
|
217
|
+
for _, cp in utf8.codes(el.text) do
|
|
218
|
+
if is_high_plane_emoji(cp) or is_bmp_symbol(cp)
|
|
219
|
+
or cp == 0x200D or cp == 0x20E3 or cp == 0xFE0F then
|
|
220
|
+
changed = true
|
|
221
|
+
else
|
|
222
|
+
table.insert(out, utf8.char(cp))
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
if not changed then return nil end
|
|
226
|
+
el.text = table.concat(out)
|
|
227
|
+
return el
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
function Code(el) return strip_unsupported(el) end
|
|
231
|
+
function CodeBlock(el) return strip_unsupported(el) end
|
|
232
|
+
EOF
|
|
233
|
+
|
|
37
234
|
echo "📦 Installing Mermaid CLI (requires Node.js)..."
|
|
38
235
|
if command -v npm &>/dev/null; then
|
|
39
|
-
npm install -g @mermaid-js/mermaid-cli
|
|
40
|
-
#
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
236
|
+
run_spinner "Mermaid CLI" npm install -g @mermaid-js/mermaid-cli
|
|
237
|
+
# Create a chromium wrapper that always passes --no-sandbox (required in containers).
|
|
238
|
+
# This is more robust than configuring mmdc/puppeteer individually — any tool
|
|
239
|
+
# that launches chromium via PUPPETEER_EXECUTABLE_PATH gets the sandbox flags.
|
|
240
|
+
sudo tee /usr/local/bin/chromium-no-sandbox > /dev/null <<'WRAPPER'
|
|
241
|
+
#!/bin/sh
|
|
242
|
+
exec /usr/bin/chromium --no-sandbox --disable-setuid-sandbox "$@"
|
|
243
|
+
WRAPPER
|
|
244
|
+
sudo chmod +x /usr/local/bin/chromium-no-sandbox
|
|
245
|
+
echo "✓ chromium-no-sandbox wrapper installed"
|
|
48
246
|
if command -v mmdc >/dev/null 2>&1; then
|
|
49
247
|
echo "✓ Mermaid CLI installed: $(command -v mmdc)"
|
|
50
248
|
else
|
|
@@ -56,8 +254,12 @@ fi
|
|
|
56
254
|
|
|
57
255
|
echo "📦 Writing default pandoc.yaml..."
|
|
58
256
|
mkdir -p "$HOME/.pandoc"
|
|
257
|
+
PANDOC_FILTERS_DIR="$HOME/.pandoc/filters"
|
|
59
258
|
cat > "$HOME/.pandoc/pandoc.yaml" <<'EOF'
|
|
60
259
|
pdf-engine: xelatex
|
|
260
|
+
filters:
|
|
261
|
+
- __PANDOC_FILTERS_DIR__/emoji-fallback.lua
|
|
262
|
+
- __PANDOC_FILTERS_DIR__/diagram.lua
|
|
61
263
|
|
|
62
264
|
variables:
|
|
63
265
|
mainfont: "Carlito"
|
|
@@ -82,13 +284,10 @@ variables:
|
|
|
82
284
|
# toc: true
|
|
83
285
|
# toc-depth: 3
|
|
84
286
|
# number-sections: true
|
|
85
|
-
|
|
86
|
-
# Uncomment to enable Mermaid/diagram rendering (requires nodejs overlay):
|
|
87
|
-
# lua-filter:
|
|
88
|
-
# - ~/.pandoc/filters/diagram.lua
|
|
89
287
|
EOF
|
|
288
|
+
sed -i "s|__PANDOC_FILTERS_DIR__|${PANDOC_FILTERS_DIR}|g" "$HOME/.pandoc/pandoc.yaml"
|
|
90
289
|
|
|
91
290
|
echo ""
|
|
92
291
|
echo "✓ pandoc overlay setup complete"
|
|
93
|
-
echo "ℹ️ Build a PDF:
|
|
94
|
-
echo "ℹ️ With Mermaid: pandoc
|
|
292
|
+
echo "ℹ️ Build a PDF: pandoc doc.md -o doc.pdf"
|
|
293
|
+
echo "ℹ️ With Mermaid diagrams: pandoc doc.md -o doc.pdf (diagram.lua enabled by default)"
|
|
@@ -3,11 +3,23 @@ set -e
|
|
|
3
3
|
command -v pandoc || { echo "✗ pandoc not found"; exit 1; }
|
|
4
4
|
command -v xelatex || { echo "✗ xelatex not found"; exit 1; }
|
|
5
5
|
[ -f "$HOME/.pandoc/filters/diagram.lua" ] || { echo "✗ diagram.lua not found"; exit 1; }
|
|
6
|
-
[ -f "$HOME/.pandoc/
|
|
6
|
+
[ -f "$HOME/.pandoc/filters/emoji-fallback.lua" ] || { echo "✗ emoji-fallback.lua not found"; exit 1; }
|
|
7
|
+
[ -f "$HOME/.pandoc/pandoc.yaml" ] || { echo "✗ pandoc.yaml not found"; exit 1; }
|
|
7
8
|
|
|
8
|
-
# Smoke test: render a
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
# Smoke test: render a PDF that includes generic emoji and flag sequences
|
|
10
|
+
# which XeLaTeX can reject without the fallback filter.
|
|
11
|
+
printf '%s\n' \
|
|
12
|
+
'# Unicode Smoke Test' \
|
|
13
|
+
'' \
|
|
14
|
+
'Status icons: ✅ ⚠️ ❌' \
|
|
15
|
+
'Activity emoji: 🎉 🚀 🧪' \
|
|
16
|
+
'Flag emoji: 🇺🇸 🇯🇵 🇧🇷' \
|
|
17
|
+
'Mixed sample: Unicode check 😀' |
|
|
18
|
+
pandoc -o /tmp/pandoc-verify-test.pdf &&
|
|
19
|
+
echo "✓ pandoc Unicode PDF smoke test passed" || {
|
|
20
|
+
echo "✗ pandoc Unicode PDF render failed"
|
|
21
|
+
exit 1
|
|
22
|
+
}
|
|
11
23
|
|
|
12
24
|
rm -f /tmp/pandoc-verify-test.pdf
|
|
13
25
|
echo "✓ pandoc overlay: OK"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Playwright setup script — Install Chromium browser + system dependencies
|
|
3
|
+
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
# Source shared setup utilities (provides load_nvm, acquire_apt_lock)
|
|
7
|
+
# shellcheck source=setup-utils.sh
|
|
8
|
+
source "$(dirname "${BASH_SOURCE[0]}")/setup-utils.sh"
|
|
9
|
+
load_nvm
|
|
10
|
+
|
|
11
|
+
echo "🎭 Setting up Playwright..."
|
|
12
|
+
|
|
13
|
+
# Suppress Playwright's "WARNING: no project dependencies" banner, apt output,
|
|
14
|
+
# and download progress bars.
|
|
15
|
+
export DEBIAN_FRONTEND=noninteractive
|
|
16
|
+
export CI=1 # suppresses interactive warnings inside playwright install
|
|
17
|
+
|
|
18
|
+
# Install Chromium and its system dependencies.
|
|
19
|
+
# playwright install --with-deps calls apt-get internally; we must hold the
|
|
20
|
+
# shared apt lock so it does not race with other parallel setup scripts.
|
|
21
|
+
acquire_apt_lock
|
|
22
|
+
npx -y playwright install --with-deps chromium 2>&1 \
|
|
23
|
+
| grep -vEe '^[╔║╚]' \
|
|
24
|
+
-e '^\|[[:space:]■]*\|' \
|
|
25
|
+
-e '^(Get:|Fetched|Reading|Building dependency|Processing triggers|Setting up|Preparing to|Selecting previously|Unpacking|Need to get|After this operation|The following )' \
|
|
26
|
+
-e '(is already the newest version|set to manually installed|npm notice|debconf:|update-alternatives:)' \
|
|
27
|
+
-e '^\(Reading database'
|
|
28
|
+
rc=${PIPESTATUS[0]}
|
|
29
|
+
release_apt_lock
|
|
30
|
+
|
|
31
|
+
if [ "$rc" -ne 0 ]; then
|
|
32
|
+
echo "❌ Playwright browser installation failed (exit $rc)"
|
|
33
|
+
exit "$rc"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
echo "✓ Playwright setup complete"
|
|
37
|
+
echo "ℹ️ Run 'npx playwright test' to execute tests"
|
|
@@ -14,6 +14,12 @@ services:
|
|
|
14
14
|
- '${POSTGRES_PORT:-5432}:5432'
|
|
15
15
|
networks:
|
|
16
16
|
- devnet
|
|
17
|
+
healthcheck:
|
|
18
|
+
test: ['CMD-SHELL', 'pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-devdb}']
|
|
19
|
+
interval: 10s
|
|
20
|
+
timeout: 5s
|
|
21
|
+
retries: 5
|
|
22
|
+
start_period: 10s
|
|
17
23
|
|
|
18
24
|
volumes:
|
|
19
25
|
postgres-data:
|
|
@@ -5,25 +5,61 @@ set -e
|
|
|
5
5
|
|
|
6
6
|
echo "🔧 Setting up PowerShell development environment..."
|
|
7
7
|
|
|
8
|
-
# Verify PowerShell is installed
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
else
|
|
8
|
+
# Verify PowerShell is installed and responds within 10 s.
|
|
9
|
+
# If pwsh doesn't respond quickly (e.g. shared library issue, slow startup),
|
|
10
|
+
# there is no point proceeding — all subsequent pwsh calls would also hang.
|
|
11
|
+
if ! command -v pwsh &>/dev/null; then
|
|
13
12
|
echo "⚠️ PowerShell not found"
|
|
14
13
|
exit 1
|
|
15
14
|
fi
|
|
16
15
|
|
|
17
|
-
#
|
|
18
|
-
|
|
16
|
+
# --kill-after ensures pwsh child processes are SIGKILL-ed after grace period.
|
|
17
|
+
PWSH_VERSION=$(timeout --kill-after=5s 10s \
|
|
18
|
+
pwsh -NoProfile -NonInteractive -Command '$PSVersionTable.PSVersion.ToString()' \
|
|
19
|
+
2>/dev/null) || true
|
|
20
|
+
|
|
21
|
+
if [ -z "$PWSH_VERSION" ]; then
|
|
22
|
+
echo "⚠️ pwsh did not respond within 10 s — skipping module installation"
|
|
23
|
+
echo "✓ PowerShell setup complete (modules skipped)"
|
|
24
|
+
exit 0
|
|
25
|
+
fi
|
|
19
26
|
|
|
20
|
-
|
|
21
|
-
|
|
27
|
+
echo "✓ PowerShell found: v$PWSH_VERSION"
|
|
28
|
+
|
|
29
|
+
# Trust PSGallery non-interactively.
|
|
30
|
+
# PowerShell 7+ bundles the NuGet provider — Install-PackageProvider is not
|
|
31
|
+
# needed and will fail with "No match found" on PS7. Call it only on PS5.
|
|
32
|
+
echo "🔧 Configuring PSGallery..."
|
|
33
|
+
timeout --kill-after=5s 60s \
|
|
34
|
+
pwsh -NoProfile -NonInteractive -Command '
|
|
35
|
+
$major = $PSVersionTable.PSVersion.Major
|
|
36
|
+
if ($major -lt 7) {
|
|
37
|
+
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -Scope CurrentUser | Out-Null
|
|
38
|
+
}
|
|
39
|
+
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
|
|
40
|
+
' || echo "⚠️ Failed to configure PSGallery (network may be unavailable) — skipping modules"
|
|
41
|
+
|
|
42
|
+
# Install common PowerShell modules.
|
|
43
|
+
# Each module runs in its own pwsh call with a per-module timeout so a slow
|
|
44
|
+
# PSGallery download doesn't block the remaining modules.
|
|
45
|
+
echo "📦 Installing PowerShell modules..."
|
|
22
46
|
|
|
23
|
-
|
|
24
|
-
|
|
47
|
+
_install_psmodule() {
|
|
48
|
+
local name="$1"; shift # remaining args passed as extra Install-Module params
|
|
49
|
+
local extra="$*"
|
|
50
|
+
timeout --kill-after=5s 90s \
|
|
51
|
+
pwsh -NoProfile -NonInteractive -Command "
|
|
52
|
+
try {
|
|
53
|
+
Install-Module -Name '$name' -Force -Scope CurrentUser -AllowClobber -Repository PSGallery $extra -ErrorAction Stop
|
|
54
|
+
Write-Host ' ✓ $name'
|
|
55
|
+
} catch {
|
|
56
|
+
Write-Host ' ⚠️ $name failed: ' + \$_
|
|
57
|
+
}
|
|
58
|
+
" 2>/dev/null || echo " ⚠️ $name timed out"
|
|
59
|
+
}
|
|
25
60
|
|
|
26
|
-
|
|
27
|
-
|
|
61
|
+
_install_psmodule PSScriptAnalyzer
|
|
62
|
+
_install_psmodule Pester -SkipPublisherCheck
|
|
63
|
+
_install_psmodule PowerShellGet
|
|
28
64
|
|
|
29
65
|
echo "✓ PowerShell setup complete"
|
|
@@ -5,10 +5,19 @@ set -e
|
|
|
5
5
|
|
|
6
6
|
echo "🔍 Setting up pre-commit framework..."
|
|
7
7
|
|
|
8
|
-
# Install pre-commit
|
|
9
|
-
|
|
8
|
+
# Install pre-commit — prefer pipx (avoids --user conflicts inside virtualenvs)
|
|
9
|
+
if command -v pipx &> /dev/null; then
|
|
10
|
+
pipx install pre-commit
|
|
11
|
+
elif command -v pip3 &> /dev/null; then
|
|
12
|
+
pip3 install pre-commit 2>/dev/null || pip3 install --break-system-packages pre-commit
|
|
13
|
+
elif command -v pip &> /dev/null; then
|
|
14
|
+
pip install pre-commit 2>/dev/null || pip install --break-system-packages pre-commit
|
|
15
|
+
else
|
|
16
|
+
echo "✗ No pip/pipx found — cannot install pre-commit"
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
10
19
|
|
|
11
|
-
#
|
|
20
|
+
# pipx installs to ~/.local/bin
|
|
12
21
|
export PATH="$HOME/.local/bin:$PATH"
|
|
13
22
|
|
|
14
23
|
# Verify installation
|
|
@@ -6,19 +6,25 @@ echo "🔍 Verifying Promtail installation..."
|
|
|
6
6
|
# Track overall success
|
|
7
7
|
ALL_CHECKS_PASSED=true
|
|
8
8
|
|
|
9
|
-
#
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
# Wait for Promtail /ready endpoint (primary health signal).
|
|
10
|
+
# docker ps is informational only — not reliably accessible in all devcontainers.
|
|
11
|
+
PROMTAIL_READY=false
|
|
12
|
+
for i in {1..40}; do
|
|
13
|
+
if curl -s -o /dev/null -w "%{http_code}" http://promtail:3101/ready 2>/dev/null | grep -q "200"; then
|
|
14
|
+
echo "✓ Promtail is ready (HTTP /ready)"
|
|
15
|
+
PROMTAIL_READY=true
|
|
16
|
+
break
|
|
17
|
+
fi
|
|
18
|
+
sleep 3
|
|
19
|
+
done
|
|
20
|
+
if [ "$PROMTAIL_READY" = false ]; then
|
|
21
|
+
echo "✗ Promtail /ready endpoint not responding after 120 s (http://promtail:3101/ready)"
|
|
14
22
|
ALL_CHECKS_PASSED=false
|
|
15
23
|
fi
|
|
16
24
|
|
|
17
|
-
#
|
|
18
|
-
if docker
|
|
19
|
-
echo "✓ Promtail
|
|
20
|
-
else
|
|
21
|
-
echo "⚠️ Promtail cannot access Docker socket"
|
|
25
|
+
# Informational: check via docker ps if available.
|
|
26
|
+
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q promtail; then
|
|
27
|
+
echo "✓ Promtail container visible in docker ps"
|
|
22
28
|
fi
|
|
23
29
|
|
|
24
30
|
# Final result
|
package/overlays/python/setup.sh
CHANGED
|
@@ -13,6 +13,23 @@ WORKSPACE_ROOT="${PWD}"
|
|
|
13
13
|
VENV_DIR="${WORKSPACE_ROOT}/.venv"
|
|
14
14
|
|
|
15
15
|
# Create virtual environment if it doesn't exist
|
|
16
|
+
# Helper: validate that the venv's Python interpreter is actually executable.
|
|
17
|
+
# A stale .venv (e.g., leftover from a previous container build) can have a
|
|
18
|
+
# bin/python that is a dangling symlink, causing "cannot execute: required
|
|
19
|
+
# file not found" when pip or other venv scripts are invoked.
|
|
20
|
+
venv_is_valid() {
|
|
21
|
+
"${VENV_DIR}/bin/python" -c "import sys" &>/dev/null
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if [ -d "${VENV_DIR}" ]; then
|
|
25
|
+
if venv_is_valid; then
|
|
26
|
+
echo "✓ Virtual environment already exists at .venv"
|
|
27
|
+
else
|
|
28
|
+
echo "⚠️ Existing .venv is invalid (stale interpreter), recreating..."
|
|
29
|
+
rm -rf "${VENV_DIR}"
|
|
30
|
+
fi
|
|
31
|
+
fi
|
|
32
|
+
|
|
16
33
|
if [ ! -d "${VENV_DIR}" ]; then
|
|
17
34
|
echo "📦 Creating virtual environment at .venv..."
|
|
18
35
|
if ! command -v python3 >/dev/null 2>&1; then
|
|
@@ -21,49 +38,51 @@ if [ ! -d "${VENV_DIR}" ]; then
|
|
|
21
38
|
fi
|
|
22
39
|
python3 -m venv "${VENV_DIR}"
|
|
23
40
|
echo "✓ Virtual environment created"
|
|
24
|
-
else
|
|
25
|
-
echo "✓ Virtual environment already exists at .venv"
|
|
26
41
|
fi
|
|
27
42
|
|
|
28
|
-
#
|
|
43
|
+
# Use the venv's Python directly to invoke pip — this is more robust than
|
|
44
|
+
# calling the pip wrapper script, whose shebang can point to a stale path.
|
|
45
|
+
PYTHON="${VENV_DIR}/bin/python"
|
|
46
|
+
|
|
47
|
+
# Activate virtual environment for PATH and VIRTUAL_ENV
|
|
29
48
|
# shellcheck source=/dev/null
|
|
30
49
|
source "${VENV_DIR}/bin/activate"
|
|
31
50
|
|
|
32
51
|
# Upgrade pip, setuptools, and wheel inside the venv
|
|
33
52
|
echo "⬆️ Upgrading pip, setuptools, and wheel..."
|
|
34
|
-
pip install --upgrade pip setuptools wheel
|
|
53
|
+
"${PYTHON}" -m pip install --upgrade pip setuptools wheel
|
|
35
54
|
echo "✓ pip, setuptools, and wheel upgraded"
|
|
36
55
|
|
|
37
56
|
# Install overlay-specific packages (if requirements-overlay.txt exists)
|
|
38
57
|
if [ -f ".devcontainer/requirements-overlay-${OVERLAY_NAME}.txt" ]; then
|
|
39
58
|
echo "📦 Installing overlay packages from requirements-overlay-${OVERLAY_NAME}.txt..."
|
|
40
|
-
pip install -r ".devcontainer/requirements-overlay-${OVERLAY_NAME}.txt"
|
|
59
|
+
"${PYTHON}" -m pip install -r ".devcontainer/requirements-overlay-${OVERLAY_NAME}.txt"
|
|
41
60
|
echo "✓ Overlay packages installed"
|
|
42
61
|
fi
|
|
43
62
|
|
|
44
63
|
# Install from root requirements.txt (project production dependencies)
|
|
45
64
|
if [ -f "requirements.txt" ]; then
|
|
46
65
|
echo "📦 Installing dependencies from requirements.txt..."
|
|
47
|
-
pip install -r requirements.txt
|
|
66
|
+
"${PYTHON}" -m pip install -r requirements.txt
|
|
48
67
|
echo "✓ Dependencies installed from requirements.txt"
|
|
49
68
|
fi
|
|
50
69
|
|
|
51
70
|
# Install from requirements-dev.txt (project development dependencies)
|
|
52
71
|
if [ -f "requirements-dev.txt" ]; then
|
|
53
72
|
echo "📦 Installing dev dependencies from requirements-dev.txt..."
|
|
54
|
-
pip install -r requirements-dev.txt
|
|
73
|
+
"${PYTHON}" -m pip install -r requirements-dev.txt
|
|
55
74
|
echo "✓ Dev dependencies installed from requirements-dev.txt"
|
|
56
75
|
fi
|
|
57
76
|
|
|
58
77
|
# Install project in editable mode if pyproject.toml exists (modern Python projects)
|
|
59
78
|
if [ -f "pyproject.toml" ]; then
|
|
60
79
|
echo "📦 Found pyproject.toml, installing project in editable mode..."
|
|
61
|
-
pip install -e .
|
|
80
|
+
"${PYTHON}" -m pip install -e .
|
|
62
81
|
echo "✓ Project installed in editable mode"
|
|
63
82
|
elif [ -f "setup.py" ]; then
|
|
64
83
|
# Fallback for legacy Python projects
|
|
65
84
|
echo "📦 Found setup.py, installing project in editable mode..."
|
|
66
|
-
pip install -e .
|
|
85
|
+
"${PYTHON}" -m pip install -e .
|
|
67
86
|
echo "✓ Project installed in editable mode"
|
|
68
87
|
fi
|
|
69
88
|
|
|
@@ -18,10 +18,12 @@ else
|
|
|
18
18
|
fi
|
|
19
19
|
|
|
20
20
|
# Check pip is installed
|
|
21
|
+
# Use `python3 -m pip` instead of calling pip3 directly — the wrapper script
|
|
22
|
+
# inside a .venv has a shebang that can point to a stale interpreter path.
|
|
21
23
|
echo ""
|
|
22
24
|
echo "2️⃣ Checking pip..."
|
|
23
|
-
if
|
|
24
|
-
|
|
25
|
+
if python3 -m pip --version &> /dev/null; then
|
|
26
|
+
python3 -m pip --version
|
|
25
27
|
echo " ✅ pip found"
|
|
26
28
|
else
|
|
27
29
|
echo " ❌ pip not found"
|
|
@@ -43,15 +43,13 @@ services:
|
|
|
43
43
|
CONSOLE_CONFIG_FILE: |
|
|
44
44
|
kafka:
|
|
45
45
|
brokers: ["redpanda:9092"]
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
schemaRegistry:
|
|
47
|
+
enabled: true
|
|
48
|
+
urls: ["http://redpanda:8081"]
|
|
49
49
|
redpanda:
|
|
50
50
|
adminApi:
|
|
51
51
|
enabled: true
|
|
52
52
|
urls: ["http://redpanda:9644"]
|
|
53
|
-
connect:
|
|
54
|
-
enabled: false
|
|
55
53
|
ports:
|
|
56
54
|
- '${REDPANDA_CONSOLE_PORT:-8080}:8080'
|
|
57
55
|
networks:
|