container-superposition 0.1.6 → 0.1.8

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.
Files changed (238) hide show
  1. package/README.md +24 -15
  2. package/dist/scripts/init.js +1 -1534
  3. package/dist/scripts/init.js.map +1 -1
  4. package/dist/tool/cli/args.d.ts +20 -0
  5. package/dist/tool/cli/args.d.ts.map +1 -0
  6. package/dist/tool/cli/args.js +325 -0
  7. package/dist/tool/cli/args.js.map +1 -0
  8. package/dist/tool/cli/run.d.ts +2 -0
  9. package/dist/tool/cli/run.d.ts.map +1 -0
  10. package/dist/tool/cli/run.js +318 -0
  11. package/dist/tool/cli/run.js.map +1 -0
  12. package/dist/tool/commands/adopt.d.ts.map +1 -1
  13. package/dist/tool/commands/adopt.js +1 -27
  14. package/dist/tool/commands/adopt.js.map +1 -1
  15. package/dist/tool/commands/doctor.d.ts +3 -0
  16. package/dist/tool/commands/doctor.d.ts.map +1 -1
  17. package/dist/tool/commands/doctor.js +1068 -70
  18. package/dist/tool/commands/doctor.js.map +1 -1
  19. package/dist/tool/commands/explain.d.ts.map +1 -1
  20. package/dist/tool/commands/explain.js +18 -0
  21. package/dist/tool/commands/explain.js.map +1 -1
  22. package/dist/tool/commands/migrate.d.ts +7 -0
  23. package/dist/tool/commands/migrate.d.ts.map +1 -0
  24. package/dist/tool/commands/migrate.js +52 -0
  25. package/dist/tool/commands/migrate.js.map +1 -0
  26. package/dist/tool/questionnaire/answers.d.ts +16 -0
  27. package/dist/tool/questionnaire/answers.d.ts.map +1 -0
  28. package/dist/tool/questionnaire/answers.js +102 -0
  29. package/dist/tool/questionnaire/answers.js.map +1 -0
  30. package/dist/tool/questionnaire/composer.d.ts +3 -3
  31. package/dist/tool/questionnaire/composer.d.ts.map +1 -1
  32. package/dist/tool/questionnaire/composer.js +902 -37
  33. package/dist/tool/questionnaire/composer.js.map +1 -1
  34. package/dist/tool/questionnaire/presets.d.ts +60 -0
  35. package/dist/tool/questionnaire/presets.d.ts.map +1 -0
  36. package/dist/tool/questionnaire/presets.js +164 -0
  37. package/dist/tool/questionnaire/presets.js.map +1 -0
  38. package/dist/tool/questionnaire/questionnaire.d.ts +10 -0
  39. package/dist/tool/questionnaire/questionnaire.d.ts.map +1 -0
  40. package/dist/tool/questionnaire/questionnaire.js +580 -0
  41. package/dist/tool/questionnaire/questionnaire.js.map +1 -0
  42. package/dist/tool/schema/manifest-migrations.d.ts +5 -0
  43. package/dist/tool/schema/manifest-migrations.d.ts.map +1 -1
  44. package/dist/tool/schema/manifest-migrations.js +45 -0
  45. package/dist/tool/schema/manifest-migrations.js.map +1 -1
  46. package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
  47. package/dist/tool/schema/overlay-loader.js +25 -0
  48. package/dist/tool/schema/overlay-loader.js.map +1 -1
  49. package/dist/tool/schema/project-config.d.ts +14 -2
  50. package/dist/tool/schema/project-config.d.ts.map +1 -1
  51. package/dist/tool/schema/project-config.js +277 -34
  52. package/dist/tool/schema/project-config.js.map +1 -1
  53. package/dist/tool/schema/target-rules.d.ts +78 -0
  54. package/dist/tool/schema/target-rules.d.ts.map +1 -0
  55. package/dist/tool/schema/target-rules.js +367 -0
  56. package/dist/tool/schema/target-rules.js.map +1 -0
  57. package/dist/tool/schema/types.d.ts +123 -12
  58. package/dist/tool/schema/types.d.ts.map +1 -1
  59. package/dist/tool/utils/merge.d.ts.map +1 -1
  60. package/dist/tool/utils/merge.js +9 -0
  61. package/dist/tool/utils/merge.js.map +1 -1
  62. package/dist/tool/utils/parameters.d.ts +76 -0
  63. package/dist/tool/utils/parameters.d.ts.map +1 -0
  64. package/dist/tool/utils/parameters.js +125 -0
  65. package/dist/tool/utils/parameters.js.map +1 -0
  66. package/dist/tool/utils/paths.d.ts +2 -0
  67. package/dist/tool/utils/paths.d.ts.map +1 -0
  68. package/dist/tool/utils/paths.js +31 -0
  69. package/dist/tool/utils/paths.js.map +1 -0
  70. package/docs/creating-overlays.md +151 -2
  71. package/docs/deployment-targets.md +88 -56
  72. package/docs/examples.md +20 -17
  73. package/docs/filesystem-contract.md +5 -0
  74. package/docs/minimal-and-editor.md +65 -5
  75. package/docs/overlay-imports.md +202 -101
  76. package/docs/overlays.md +162 -34
  77. package/docs/quick-reference.md +99 -0
  78. package/docs/specs/003-mkdocs2-overlay/spec.md +114 -0
  79. package/docs/specs/004-doctor-fix/spec.md +70 -0
  80. package/docs/specs/005-cuda-overlay/spec.md +101 -0
  81. package/docs/specs/006-rocm-overlay/spec.md +109 -0
  82. package/docs/specs/007-init-project-file/spec.md +66 -0
  83. package/docs/specs/007-target-aware-generation/spec.md +126 -0
  84. package/docs/specs/008-project-file-canonical/spec.md +83 -0
  85. package/docs/specs/009-project-env/spec.md +147 -0
  86. package/docs/specs/010-compose-env-materialization/spec.md +130 -0
  87. package/docs/specs/011-overlay-parameters/spec.md +235 -0
  88. package/overlays/.shared/README.md +105 -21
  89. package/overlays/.shared/compose/common-healthchecks.md +60 -0
  90. package/overlays/.shared/compose/nvidia-gpu-devcontainer.yml +22 -0
  91. package/overlays/.shared/vscode/recommended-extensions.json +15 -11
  92. package/overlays/alertmanager/setup.sh +4 -19
  93. package/overlays/alertmanager/verify.sh +8 -9
  94. package/overlays/all/README.md +43 -0
  95. package/overlays/all/devcontainer.patch.json +6 -0
  96. package/overlays/all/overlay.yml +14 -0
  97. package/overlays/amp/setup.sh +5 -0
  98. package/overlays/bun/setup.sh +10 -1
  99. package/overlays/bun/verify.sh +6 -1
  100. package/overlays/claude-code/setup.sh +5 -0
  101. package/overlays/cloudflared/setup.sh +9 -12
  102. package/overlays/codex/README.md +9 -6
  103. package/overlays/codex/devcontainer.patch.json +7 -1
  104. package/overlays/codex/setup.sh +5 -0
  105. package/overlays/codex/verify.sh +8 -0
  106. package/overlays/comfyui/.env.example +34 -0
  107. package/overlays/comfyui/README.md +342 -0
  108. package/overlays/comfyui/devcontainer.patch.json +15 -0
  109. package/overlays/comfyui/docker-compose.yml +39 -0
  110. package/overlays/comfyui/overlay.yml +20 -0
  111. package/overlays/comfyui/setup.sh +36 -0
  112. package/overlays/comfyui/verify.sh +103 -0
  113. package/overlays/commitlint/setup.sh +5 -0
  114. package/overlays/cuda/README.md +179 -0
  115. package/overlays/cuda/devcontainer.patch.json +7 -0
  116. package/overlays/cuda/overlay.yml +17 -0
  117. package/overlays/cuda/setup.sh +32 -0
  118. package/overlays/cuda/verify.sh +38 -0
  119. package/overlays/devcontainer-cli/README.md +50 -0
  120. package/overlays/devcontainer-cli/devcontainer.patch.json +13 -0
  121. package/overlays/devcontainer-cli/overlay.yml +16 -0
  122. package/overlays/devcontainer-cli/setup.sh +14 -0
  123. package/overlays/direnv/devcontainer.patch.json +6 -0
  124. package/overlays/direnv/setup.sh +7 -6
  125. package/overlays/dotnet/setup.sh +14 -7
  126. package/overlays/duckdb/devcontainer.patch.json +1 -2
  127. package/overlays/gcloud/devcontainer.patch.json +0 -6
  128. package/overlays/gcloud/setup.sh +51 -0
  129. package/overlays/gemini-cli/setup.sh +5 -0
  130. package/overlays/git-helpers/devcontainer.patch.json +2 -1
  131. package/overlays/go/setup.sh +15 -14
  132. package/overlays/jaeger/overlay.yml +2 -0
  133. package/overlays/just/setup.sh +5 -17
  134. package/overlays/k3d/README.md +201 -0
  135. package/overlays/k3d/devcontainer.patch.json +9 -0
  136. package/overlays/k3d/overlay.yml +19 -0
  137. package/overlays/k3d/setup.sh +34 -0
  138. package/overlays/k3d/verify.sh +38 -0
  139. package/overlays/keycloak/docker-compose.yml +6 -4
  140. package/overlays/keycloak/verify.sh +4 -3
  141. package/overlays/kind/devcontainer.patch.json +1 -2
  142. package/overlays/kind/setup.sh +8 -17
  143. package/overlays/minio/setup.sh +10 -18
  144. package/overlays/mkdocs/overlay.yml +2 -1
  145. package/overlays/mkdocs2/README.md +135 -0
  146. package/overlays/mkdocs2/devcontainer.patch.json +19 -0
  147. package/overlays/mkdocs2/overlay.yml +17 -0
  148. package/overlays/mkdocs2/setup.sh +67 -0
  149. package/overlays/mkdocs2/verify.sh +35 -0
  150. package/overlays/modern-cli-tools/devcontainer.patch.json +7 -1
  151. package/overlays/modern-cli-tools/setup.sh +21 -71
  152. package/overlays/mongodb/devcontainer.patch.json +0 -6
  153. package/overlays/mongodb/setup.sh +59 -0
  154. package/overlays/mysql/verify.sh +4 -3
  155. package/overlays/nats/.env.example +1 -1
  156. package/overlays/nats/README.md +1 -1
  157. package/overlays/nats/docker-compose.yml +1 -1
  158. package/overlays/ngrok/setup.sh +9 -6
  159. package/overlays/nodejs/setup.sh +5 -0
  160. package/overlays/ollama/.env.example +14 -0
  161. package/overlays/ollama/README.md +325 -0
  162. package/overlays/ollama/devcontainer.patch.json +14 -0
  163. package/overlays/ollama/docker-compose.yml +24 -0
  164. package/overlays/ollama/overlay.yml +22 -0
  165. package/overlays/ollama/setup.sh +106 -0
  166. package/overlays/ollama/verify.sh +99 -0
  167. package/overlays/open-webui/.env.example +5 -0
  168. package/overlays/open-webui/README.md +162 -0
  169. package/overlays/open-webui/devcontainer.patch.json +14 -0
  170. package/overlays/open-webui/docker-compose.yml +23 -0
  171. package/overlays/open-webui/overlay.yml +38 -0
  172. package/overlays/openapi-tools/devcontainer.patch.json +1 -2
  173. package/overlays/openapi-tools/setup.sh +9 -8
  174. package/overlays/opencode/setup.sh +5 -0
  175. package/overlays/otel-collector/overlay.yml +2 -0
  176. package/overlays/otel-collector/setup.sh +3 -16
  177. package/overlays/otel-demo-nodejs/verify.sh +8 -9
  178. package/overlays/otel-demo-python/verify.sh +16 -10
  179. package/overlays/pandoc/README.md +22 -15
  180. package/overlays/pandoc/devcontainer.patch.json +6 -2
  181. package/overlays/pandoc/setup.sh +217 -18
  182. package/overlays/pandoc/verify.sh +16 -4
  183. package/overlays/pgvector/.env.example +6 -0
  184. package/overlays/pgvector/README.md +215 -0
  185. package/overlays/pgvector/devcontainer.patch.json +23 -0
  186. package/overlays/pgvector/docker-compose.yml +32 -0
  187. package/overlays/pgvector/overlay.yml +44 -0
  188. package/overlays/playwright/devcontainer.patch.json +3 -1
  189. package/overlays/playwright/setup.sh +37 -0
  190. package/overlays/postgres/.env.example +5 -5
  191. package/overlays/postgres/devcontainer.patch.json +4 -4
  192. package/overlays/postgres/docker-compose.yml +15 -5
  193. package/overlays/postgres/overlay.yml +19 -1
  194. package/overlays/powershell/setup.sh +49 -13
  195. package/overlays/pre-commit/setup.sh +12 -3
  196. package/overlays/prometheus/overlay.yml +2 -0
  197. package/overlays/promtail/verify.sh +16 -10
  198. package/overlays/pulumi/devcontainer.patch.json +1 -1
  199. package/overlays/python/setup.sh +28 -9
  200. package/overlays/python/verify.sh +4 -2
  201. package/overlays/qdrant/.env.example +4 -0
  202. package/overlays/qdrant/README.md +216 -0
  203. package/overlays/qdrant/devcontainer.patch.json +20 -0
  204. package/overlays/qdrant/docker-compose.yml +25 -0
  205. package/overlays/qdrant/overlay.yml +40 -0
  206. package/overlays/redpanda/docker-compose.yml +3 -5
  207. package/overlays/rocm/README.md +227 -0
  208. package/overlays/rocm/devcontainer.patch.json +4 -0
  209. package/overlays/rocm/overlay.yml +17 -0
  210. package/overlays/rocm/setup.sh +45 -0
  211. package/overlays/rocm/verify.sh +47 -0
  212. package/overlays/rust/setup.sh +11 -18
  213. package/overlays/skaffold/README.md +256 -0
  214. package/overlays/skaffold/devcontainer.patch.json +9 -0
  215. package/overlays/skaffold/overlay.yml +20 -0
  216. package/overlays/skaffold/setup.sh +33 -0
  217. package/overlays/skaffold/verify.sh +24 -0
  218. package/overlays/spec-kit/setup.sh +7 -3
  219. package/overlays/sqlite/setup.sh +14 -14
  220. package/overlays/sqlserver/docker-compose.yml +3 -3
  221. package/overlays/sqlserver/verify.sh +22 -5
  222. package/overlays/tempo/verify.sh +16 -10
  223. package/overlays/tilt/devcontainer.patch.json +1 -2
  224. package/overlays/tilt/setup.sh +14 -4
  225. package/overlays/windsurf-cli/setup.sh +27 -4
  226. package/overlays/windsurf-cli/verify.sh +13 -3
  227. package/package.json +4 -2
  228. package/templates/scripts/setup-utils.sh +228 -0
  229. package/tool/schema/config.schema.json +141 -9
  230. package/tool/schema/overlay-manifest.schema.json +38 -0
  231. package/overlays/.shared/compose/common-healthchecks.yml +0 -38
  232. /package/overlays/otel-demo-nodejs/{Dockerfile-otel-demo-nodejs → Dockerfile} +0 -0
  233. /package/overlays/otel-demo-nodejs/{package-otel-demo-nodejs.json → package.json} +0 -0
  234. /package/overlays/otel-demo-nodejs/{server-otel-demo-nodejs.js → server.js} +0 -0
  235. /package/overlays/otel-demo-nodejs/{tracing-otel-demo-nodejs.js → tracing.js} +0 -0
  236. /package/overlays/otel-demo-python/{Dockerfile-otel-demo-python → Dockerfile} +0 -0
  237. /package/overlays/otel-demo-python/{app-otel-demo-python.py → app.py} +0 -0
  238. /package/overlays/otel-demo-python/{requirements-otel-demo-python.txt → requirements.txt} +0 -0
@@ -0,0 +1,20 @@
1
+ id: skaffold
2
+ name: Skaffold
3
+ description: Continuous development and deployment pipeline for Kubernetes applications
4
+ category: dev
5
+ supports: []
6
+ requires: []
7
+ suggests:
8
+ - kubectl-helm
9
+ - kind
10
+ - k3d
11
+ conflicts:
12
+ - tilt
13
+ tags:
14
+ - dev
15
+ - kubernetes
16
+ - k8s
17
+ - cicd
18
+ - deployment
19
+ - skaffold
20
+ ports: []
@@ -0,0 +1,33 @@
1
+ #!/bin/bash
2
+ # Setup script for Skaffold
3
+
4
+ set -e
5
+
6
+ echo "🔧 Setting up Skaffold..."
7
+
8
+ # Source shared setup utilities
9
+ # shellcheck source=setup-utils.sh
10
+ source "$(dirname "${BASH_SOURCE[0]}")/setup-utils.sh"
11
+
12
+ detect_arch
13
+
14
+ SKAFFOLD_VERSION="${SKAFFOLD_VERSION:-v2.13.2}"
15
+ echo "📦 Installing Skaffold ${SKAFFOLD_VERSION}..."
16
+
17
+ install_binary \
18
+ "https://storage.googleapis.com/skaffold/releases/${SKAFFOLD_VERSION}/skaffold-linux-${CS_ARCH}" \
19
+ "skaffold"
20
+
21
+ # Verify installation
22
+ if command -v skaffold &>/dev/null; then
23
+ echo "✅ Skaffold installed successfully"
24
+ skaffold version
25
+ else
26
+ echo "❌ Skaffold installation failed"
27
+ exit 1
28
+ fi
29
+
30
+ echo "✅ Skaffold setup complete"
31
+ echo ""
32
+ echo "ℹ️ To start continuous development, run:"
33
+ echo " skaffold dev"
@@ -0,0 +1,24 @@
1
+ #!/bin/bash
2
+ # Verification script for Skaffold overlay
3
+ # Confirms Skaffold is installed
4
+
5
+ set -e
6
+
7
+ echo "🔍 Verifying Skaffold overlay..."
8
+ echo ""
9
+
10
+ # Check Skaffold is installed
11
+ echo "1️⃣ Checking Skaffold installation..."
12
+ if command -v skaffold &>/dev/null; then
13
+ skaffold version
14
+ echo " ✅ Skaffold is installed"
15
+ else
16
+ echo " ❌ Skaffold is not installed"
17
+ exit 1
18
+ fi
19
+
20
+ echo ""
21
+ echo "✅ Skaffold overlay verification complete"
22
+ echo ""
23
+ echo "ℹ️ To start continuous development, run:"
24
+ echo " skaffold dev"
@@ -3,6 +3,10 @@
3
3
 
4
4
  set -e
5
5
 
6
+ # Source shared setup utilities (provides run_spinner)
7
+ # shellcheck source=setup-utils.sh
8
+ source "$(dirname "${BASH_SOURCE[0]}")/setup-utils.sh"
9
+
6
10
  echo "📦 Installing prerequisites for spec-kit..."
7
11
 
8
12
  # Ensure uv tool bin directory is always on PATH (uv puts shims here regardless
@@ -21,11 +25,11 @@ echo "📦 Installing specify-cli..."
21
25
  # Pin to a uv-managed Python (avoids broken system Python 3.13 on Debian trixie
22
26
  # where stdlib modules like shutil/os can be missing due to Debian's split packages)
23
27
  UV_PYTHON_VERSION="3.12"
24
- echo " Ensuring uv-managed Python ${UV_PYTHON_VERSION} is available..."
25
- uv python install "${UV_PYTHON_VERSION}"
28
+ run_spinner "Python ${UV_PYTHON_VERSION} (uv)" uv python install --quiet "${UV_PYTHON_VERSION}"
26
29
 
27
30
  # Install specify-cli using the uv-managed Python, not the system interpreter
28
- uv tool install specify-cli --from git+https://github.com/github/spec-kit.git \
31
+ run_spinner "specify-cli" uv tool install --quiet specify-cli \
32
+ --from git+https://github.com/github/spec-kit.git \
29
33
  --python "${UV_PYTHON_VERSION}"
30
34
 
31
35
  # Verify — use the full path as a fallback in case the shim dir is not yet in PATH
@@ -5,20 +5,20 @@ set -e
5
5
 
6
6
  echo "🔧 Setting up SQLite tools..."
7
7
 
8
- # Install litecli via pip if Python is available
9
- if command -v pip &> /dev/null || command -v pip3 &> /dev/null; then
10
- echo "📦 Installing litecli..."
11
- if command -v pip3 &> /dev/null; then
12
- pip3 install --user litecli || echo "⚠️ litecli installation failed, continuing..."
13
- else
14
- pip install --user litecli || echo "⚠️ litecli installation failed, continuing..."
15
- fi
16
-
17
- # Add to PATH if not already there
18
- if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
19
- echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
20
- export PATH="$HOME/.local/bin:$PATH"
21
- fi
8
+ # Install litecli via pipx (avoids --user conflicts inside virtualenvs)
9
+ if command -v pipx &> /dev/null; then
10
+ echo "📦 Installing litecli via pipx..."
11
+ pipx install litecli || echo "⚠️ litecli installation failed, continuing..."
12
+ elif command -v pip3 &> /dev/null; then
13
+ echo "📦 Installing litecli via pip3..."
14
+ pip3 install litecli 2>/dev/null || \
15
+ pip3 install --break-system-packages litecli || \
16
+ echo "⚠️ litecli installation failed, continuing..."
17
+ elif command -v pip &> /dev/null; then
18
+ echo "📦 Installing litecli via pip..."
19
+ pip install litecli 2>/dev/null || \
20
+ pip install --break-system-packages litecli || \
21
+ echo "⚠️ litecli installation failed, continuing..."
22
22
  else
23
23
  echo "⚠️ Python/pip not found, skipping litecli installation"
24
24
  echo " Install Python overlay for enhanced SQLite CLI (litecli)"
@@ -18,12 +18,12 @@ services:
18
18
  test:
19
19
  [
20
20
  'CMD-SHELL',
21
- "/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P '${MSSQL_SA_PASSWORD:-YourStrong@Passw0rd}' -Q 'SELECT 1' || exit 1",
21
+ "/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P '${MSSQL_SA_PASSWORD:-YourStrong@Passw0rd}' -Q 'SELECT 1' -No || exit 1",
22
22
  ]
23
23
  interval: 10s
24
24
  timeout: 5s
25
- retries: 5
26
- start_period: 30s
25
+ retries: 10
26
+ start_period: 60s
27
27
 
28
28
  volumes:
29
29
  sqlserver-data:
@@ -10,10 +10,27 @@ echo ""
10
10
  # Check if SQL Server service is running
11
11
  echo "1️⃣ Checking SQL Server service..."
12
12
  SQLSERVER_READY=false
13
- for i in {1..30}; do
14
- # Try to connect using docker exec (sqlcmd is in the container, not necessarily in dev container)
15
- if docker exec $(docker ps -qf "name=sqlserver") /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P 'YourStrong@Passw0rd' -Q "SELECT 1" &> /dev/null; then
16
- echo " ✅ SQL Server service is ready"
13
+ MSSQL_SA_PASSWORD="${MSSQL_SA_PASSWORD:-YourStrong@Passw0rd}"
14
+ MSSQL_HOST="${MSSQL_HOST:-sqlserver}"
15
+ MSSQL_PORT="${MSSQL_PORT:-1433}"
16
+
17
+ for i in {1..60}; do
18
+ # Primary: sqlcmd via docker exec when Docker socket is available
19
+ if command -v docker &>/dev/null; then
20
+ CONTAINER=$(docker ps -qf "ancestor=mcr.microsoft.com/mssql/server" 2>/dev/null | head -1)
21
+ if [ -n "$CONTAINER" ] && \
22
+ docker exec "$CONTAINER" /opt/mssql-tools18/bin/sqlcmd \
23
+ -S localhost -U sa -P "$MSSQL_SA_PASSWORD" -Q "SELECT 1" -No &>/dev/null 2>&1; then
24
+ echo " ✅ SQL Server service is ready"
25
+ SQLSERVER_READY=true
26
+ break
27
+ fi
28
+ fi
29
+ # Fallback: TCP connectivity check (no Docker socket available)
30
+ if bash -c "echo > /dev/tcp/${MSSQL_HOST}/${MSSQL_PORT}" 2>/dev/null; then
31
+ # Port is open — allow a brief settle time for full SQL Server initialisation
32
+ sleep 15
33
+ echo " ✅ SQL Server port ${MSSQL_PORT} is accepting connections"
17
34
  SQLSERVER_READY=true
18
35
  break
19
36
  fi
@@ -21,7 +38,7 @@ for i in {1..30}; do
21
38
  done
22
39
 
23
40
  if [ "$SQLSERVER_READY" = false ]; then
24
- echo " ❌ SQL Server service not ready after 60 seconds"
41
+ echo " ❌ SQL Server service not ready after 120 seconds"
25
42
  echo " ⚠️ SQL Server can take 30-60 seconds to start"
26
43
  exit 1
27
44
  fi
@@ -6,19 +6,25 @@ echo "🔍 Verifying Tempo installation..."
6
6
  # Track overall success
7
7
  ALL_CHECKS_PASSED=true
8
8
 
9
- # Check if Tempo service is running
10
- if docker ps --format '{{.Names}}' | grep -q tempo; then
11
- echo "✓ Tempo service is running"
12
- else
13
- echo " Tempo service is not running"
9
+ # Wait for Tempo /ready endpoint (primary health signal).
10
+ # docker ps is informational only not reliably accessible in all devcontainers.
11
+ TEMPO_READY=false
12
+ for i in {1..40}; do
13
+ if curl -s -o /dev/null -w "%{http_code}" http://tempo:3200/ready 2>/dev/null | grep -q "200"; then
14
+ echo "✓ Tempo HTTP API is accessible"
15
+ TEMPO_READY=true
16
+ break
17
+ fi
18
+ sleep 3
19
+ done
20
+ if [ "$TEMPO_READY" = false ]; then
21
+ echo "✗ Tempo /ready endpoint not responding after 120 s (http://tempo:3200/ready)"
14
22
  ALL_CHECKS_PASSED=false
15
23
  fi
16
24
 
17
- # Check if Tempo HTTP API is accessible
18
- if curl -s -o /dev/null -w "%{http_code}" http://tempo:3200/ready 2>/dev/null | grep -q "200"; then
19
- echo "✓ Tempo HTTP API is accessible"
20
- else
21
- echo "⚠️ Tempo HTTP API not responding yet (may still be starting)"
25
+ # Informational: check via docker ps if available.
26
+ if docker ps --format '{{.Names}}' 2>/dev/null | grep -q tempo; then
27
+ echo "✓ Tempo container visible in docker ps"
22
28
  fi
23
29
 
24
30
  # Final result
@@ -12,6 +12,5 @@
12
12
  "label": "Tilt UI",
13
13
  "onAutoForward": "openBrowser"
14
14
  }
15
- },
16
- "postCreateCommand": "bash .devcontainer/scripts/setup-tilt.sh"
15
+ }
17
16
  }
@@ -5,13 +5,23 @@ set -e
5
5
 
6
6
  echo "🔧 Setting up Tilt..."
7
7
 
8
- # Install Tilt
9
- echo "📦 Installing Tilt..."
8
+ # Source shared setup utilities
9
+ # shellcheck source=setup-utils.sh
10
+ source "$(dirname "${BASH_SOURCE[0]}")/setup-utils.sh"
10
11
 
11
- curl -fsSL https://raw.githubusercontent.com/tilt-dev/tilt/master/scripts/install.sh | bash
12
+ TILT_VERSION="${TILT_VERSION:-0.37.0}"
13
+ detect_arch
14
+ TILT_ARCH="$CS_ARCH"
15
+ # tilt uses x86_64 for amd64 in its tarball names
16
+ [ "$TILT_ARCH" = "amd64" ] && TILT_ARCH="x86_64"
17
+
18
+ echo "📦 Installing Tilt v${TILT_VERSION} for linux.${TILT_ARCH}..."
19
+ install_binary_from_tar \
20
+ "https://github.com/tilt-dev/tilt/releases/download/v${TILT_VERSION}/tilt.${TILT_VERSION}.linux.${TILT_ARCH}.tar.gz" \
21
+ "tilt"
12
22
 
13
23
  # Verify installation
14
- if command -v tilt &> /dev/null; then
24
+ if command -v tilt &>/dev/null; then
15
25
  echo "✅ Tilt installed successfully"
16
26
  tilt version
17
27
  else
@@ -5,15 +5,38 @@ set -e
5
5
 
6
6
  echo "📦 Installing Codeium Windsurf CLI..."
7
7
 
8
- # Install windsurf globally via npm
9
- npm install -g @codeium/windsurf-cli
8
+ # Windsurf CLI is distributed as a binary release from GitHub, not via npm
9
+ ARCH=$(uname -m)
10
+ case "$ARCH" in
11
+ x86_64) ARCH_TAG="x86_64" ;;
12
+ aarch64|arm64) ARCH_TAG="aarch64" ;;
13
+ *) echo "⚠️ Unsupported architecture: $ARCH, skipping windsurf-cli installation"; exit 0 ;;
14
+ esac
15
+
16
+ WINDSURF_VERSION=$(curl -fsSL https://api.github.com/repos/codeium-ai/windsurf-cli/releases/latest 2>/dev/null | grep '"tag_name"' | head -1 | sed 's/.*"tag_name": *"\([^"]*\)".*/\1/')
17
+
18
+ if [ -z "$WINDSURF_VERSION" ]; then
19
+ echo "⚠️ Could not determine latest windsurf-cli version, trying known stable"
20
+ WINDSURF_VERSION="v0.1.0"
21
+ fi
22
+
23
+ echo " Downloading windsurf-cli ${WINDSURF_VERSION} for ${ARCH_TAG}..."
24
+ DOWNLOAD_URL="https://github.com/codeium-ai/windsurf-cli/releases/download/${WINDSURF_VERSION}/windsurf-linux-${ARCH_TAG}"
25
+
26
+ if curl -fsSL --head "$DOWNLOAD_URL" >/dev/null 2>&1; then
27
+ curl -fsSL "$DOWNLOAD_URL" -o /tmp/windsurf
28
+ sudo install -m 0755 /tmp/windsurf /usr/local/bin/windsurf
29
+ rm -f /tmp/windsurf
30
+ else
31
+ echo "⚠️ windsurf-cli binary not available for this platform — skipping"
32
+ exit 0
33
+ fi
10
34
 
11
35
  # Verify installation
12
36
  if command -v windsurf &>/dev/null; then
13
37
  echo "✓ Windsurf CLI installed successfully: $(windsurf --version 2>/dev/null || echo 'installed')"
14
38
  else
15
- echo " Windsurf CLI installation failed"
16
- exit 1
39
+ echo "⚠️ windsurf-cli not found after install — may need a shell restart"
17
40
  fi
18
41
 
19
42
  echo "✓ windsurf-cli setup complete"
@@ -5,10 +5,20 @@ set -e
5
5
 
6
6
  echo "🔍 Verifying windsurf-cli overlay setup..."
7
7
 
8
- # Check if windsurf CLI is installed
8
+ # windsurf-cli is a best-effort install — it is skipped on unsupported platforms
9
+ # (arm64 Linux). Exit 0 gracefully when it was intentionally not installed.
9
10
  if ! command -v windsurf &>/dev/null; then
10
- echo "✗ windsurf CLI is not installed or not in PATH"
11
- exit 1
11
+ ARCH=$(uname -m)
12
+ case "$ARCH" in
13
+ aarch64|arm64)
14
+ echo "ℹ️ windsurf-cli skipped (not available for $ARCH)"
15
+ exit 0
16
+ ;;
17
+ *)
18
+ echo "✗ windsurf CLI is not installed or not in PATH"
19
+ exit 1
20
+ ;;
21
+ esac
12
22
  fi
13
23
 
14
24
  echo "✓ windsurf CLI is installed: $(windsurf --version 2>/dev/null || echo 'installed')"
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "container-superposition",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Solution-ready devcontainer templates and features with guided initialization",
5
5
  "type": "module",
6
6
  "main": "dist/scripts/init.js",
7
7
  "bin": {
8
- "container-superposition": "./dist/scripts/init.js"
8
+ "container-superposition": "./dist/scripts/init.js",
9
+ "cs": "./dist/scripts/init.js"
9
10
  },
10
11
  "scripts": {
11
12
  "build": "tsc",
@@ -13,6 +14,7 @@
13
14
  "init:build": "npm run build && node dist/scripts/init.js",
14
15
  "test": "vitest run",
15
16
  "test:watch": "vitest",
17
+ "test:integration": "INTEGRATION=true vitest run tool/__tests__/overlay-features-integration.test.ts",
16
18
  "test:smoke": "bash scripts/test.sh",
17
19
  "docs:generate": "tsx docs/generate-docs.ts && prettier --write docs/overlays.md",
18
20
  "lint": "tsc --noEmit && npm run format:check",
@@ -0,0 +1,228 @@
1
+ #!/bin/bash
2
+ # Shared setup utilities for container-superposition overlay scripts.
3
+ # Sourced automatically: source "$(dirname "${BASH_SOURCE[0]}")/setup-utils.sh"
4
+ #
5
+ # All setup scripts for selected overlays run in PARALLEL via postCreateCommand.
6
+ # Use the locking helpers below for any apt/dpkg operations.
7
+
8
+ # Suppress terminal-capability probes (OSC queries, colour-detection) and npm
9
+ # update notices that show up as garbage or noise in devcontainer build logs.
10
+ export NO_COLOR=1
11
+ export NPM_CONFIG_UPDATE_NOTIFIER=false
12
+ # TERM=dumb prevents most tools from querying cursor position or emitting ANSI
13
+ # escape sequences in non-interactive build logs.
14
+ export TERM=dumb
15
+
16
+ # ---------------------------------------------------------------------------
17
+ # Spinner helper
18
+ # ---------------------------------------------------------------------------
19
+
20
+ # Run a command silently while showing a spinner and a label.
21
+ # Stdout/stderr of the command are suppressed; only pass/fail is reported.
22
+ # Usage: run_spinner "Installing foo..." <command> [args...]
23
+ # Exit code: the exit code of <command>.
24
+ run_spinner() {
25
+ local label="$1"; shift
26
+ local rc
27
+
28
+ if [ -t 1 ]; then
29
+ # Interactive TTY: animated spinner with carriage-return overwriting.
30
+ local spin='⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'
31
+ local i=0
32
+ "$@" &>/dev/null &
33
+ local pid=$!
34
+ while kill -0 "$pid" 2>/dev/null; do
35
+ printf "\r %s %s" "${spin:$((i % ${#spin})):1}" "$label"
36
+ sleep 0.1
37
+ (( i++ )) || true
38
+ done
39
+ wait "$pid"; rc=$?
40
+ if [ "$rc" -eq 0 ]; then
41
+ printf "\r ✓ %s\n" "$label"
42
+ else
43
+ printf "\r ✗ %s (exit %d)\n" "$label" "$rc"
44
+ fi
45
+ else
46
+ # Non-TTY (devcontainer build log, CI): emit a start line immediately
47
+ # so the log shows progress, then a done line when the command finishes.
48
+ # No carriage-return tricks — plain newlines so each line is visible.
49
+ printf " ⋯ %s\n" "$label"
50
+ "$@" &>/dev/null; rc=$?
51
+ if [ "$rc" -eq 0 ]; then
52
+ printf " ✓ %s\n" "$label"
53
+ else
54
+ printf " ✗ %s (exit %d)\n" "$label" "$rc"
55
+ fi
56
+ fi
57
+ return $rc
58
+ }
59
+
60
+ # ---------------------------------------------------------------------------
61
+ # Node.js / npm helpers
62
+ # ---------------------------------------------------------------------------
63
+
64
+ # Ensure npm (and node) are on PATH by loading nvm if needed.
65
+ # The devcontainer node feature installs via nvm; postCreateCommand scripts
66
+ # run in a non-interactive shell that may not have nvm on PATH.
67
+ # Safe to call multiple times (idempotent).
68
+ # Usage: load_nvm
69
+ load_nvm() {
70
+ if command -v npm &>/dev/null; then
71
+ return 0 # already on PATH
72
+ fi
73
+ local nvm_dir="${NVM_DIR:-/usr/local/share/nvm}"
74
+ # shellcheck disable=SC1091
75
+ if [ -s "$nvm_dir/nvm.sh" ]; then
76
+ TERM=dumb \. "$nvm_dir/nvm.sh" --no-use 2>/dev/null || true
77
+ fi
78
+ # Fallback: add the nvm current symlink bin directory to PATH
79
+ if ! command -v npm &>/dev/null && [ -d "$nvm_dir/current/bin" ]; then
80
+ export PATH="$nvm_dir/current/bin:$PATH"
81
+ fi
82
+ }
83
+
84
+ # ---------------------------------------------------------------------------
85
+ # APT / DPKG helpers
86
+ # ---------------------------------------------------------------------------
87
+
88
+ # Advisory lock file shared across all parallel postCreateCommand scripts.
89
+ _CS_APT_LOCK=/tmp/.cs-apt.lock
90
+
91
+ # Acquire an exclusive flock-based lock for apt/dpkg operations.
92
+ # Blocks until the lock is available or 300 s elapses (hard failure).
93
+ # The kernel releases the lock automatically on process exit for any reason.
94
+ acquire_apt_lock() {
95
+ exec 9>"$_CS_APT_LOCK"
96
+ echo "⏳ Acquiring apt lock..."
97
+ flock -w 300 9 || {
98
+ echo "❌ Timed out waiting for apt lock after 300s"
99
+ return 1
100
+ }
101
+ }
102
+
103
+ # Release the lock acquired by acquire_apt_lock.
104
+ release_apt_lock() {
105
+ flock -u 9 2>/dev/null || true
106
+ exec 9>&- 2>/dev/null || true
107
+ }
108
+
109
+ # Run a command inside an apt lock, releasing it even on failure.
110
+ # Usage: with_apt_lock <command> [args...]
111
+ # Example: with_apt_lock sudo apt-get install -y ripgrep
112
+ with_apt_lock() {
113
+ acquire_apt_lock || return 1
114
+ "$@"
115
+ local rc=$?
116
+ release_apt_lock
117
+ return $rc
118
+ }
119
+
120
+ # Run apt-get update + apt-get install under a single held lock.
121
+ # Usage: apt_install <package> [packages...]
122
+ apt_install() {
123
+ acquire_apt_lock || return 1
124
+ # Pass DEBIAN_FRONTEND and TERM explicitly: sudo strips environment by default.
125
+ sudo DEBIAN_FRONTEND=noninteractive TERM=dumb apt-get update -qq
126
+ sudo DEBIAN_FRONTEND=noninteractive TERM=dumb apt-get install -y -qq "$@"
127
+ local rc=$?
128
+ release_apt_lock
129
+ return $rc
130
+ }
131
+
132
+ # @deprecated — kept for backward compat; delegates to acquire_apt_lock.
133
+ wait_for_apt_lock() {
134
+ acquire_apt_lock
135
+ }
136
+
137
+ # Add a third-party apt repository with a GPG key.
138
+ # Does NOT require the apt lock — only writes key/sources files.
139
+ # Caller is responsible for calling apt-get update afterward (inside a lock).
140
+ # Usage: add_apt_repo <key-url> <keyring-path> <repo-line> <sources-file>
141
+ add_apt_repo() {
142
+ local key_url="$1"
143
+ local keyring_path="$2"
144
+ local repo_line="$3"
145
+ local sources_file="$4"
146
+
147
+ sudo mkdir -p "$(dirname "$keyring_path")" "$(dirname "$sources_file")"
148
+ curl -fsSL "$key_url" | sudo gpg --dearmor -o "$keyring_path"
149
+ echo "$repo_line" | sudo tee "$sources_file" >/dev/null
150
+ }
151
+
152
+ # ---------------------------------------------------------------------------
153
+ # Idempotency helpers
154
+ # ---------------------------------------------------------------------------
155
+
156
+ # Returns 0 if the command exists on PATH.
157
+ command_exists() {
158
+ command -v "$1" >/dev/null 2>&1
159
+ }
160
+
161
+ # Returns 0 if an apt package is installed.
162
+ apt_package_installed() {
163
+ dpkg -s "$1" >/dev/null 2>&1
164
+ }
165
+
166
+ # ---------------------------------------------------------------------------
167
+ # Architecture detection
168
+ # ---------------------------------------------------------------------------
169
+
170
+ # Sets CS_ARCH to "amd64" or "arm64" based on uname -m.
171
+ # Usage:
172
+ # detect_arch # returns 1 on unknown arch
173
+ # detect_arch amd64 # falls back to amd64 on unknown arch
174
+ detect_arch() {
175
+ local fallback="${1:-}"
176
+ local raw
177
+ raw=$(uname -m)
178
+ case "$raw" in
179
+ x86_64) CS_ARCH="amd64" ;;
180
+ aarch64|arm64) CS_ARCH="arm64" ;;
181
+ *)
182
+ if [ -n "$fallback" ]; then
183
+ echo "⚠️ Unsupported architecture: $raw, falling back to $fallback"
184
+ CS_ARCH="$fallback"
185
+ else
186
+ echo "❌ Unsupported architecture: $raw"
187
+ return 1
188
+ fi
189
+ ;;
190
+ esac
191
+ export CS_ARCH
192
+ }
193
+
194
+ # ---------------------------------------------------------------------------
195
+ # Binary installation helpers
196
+ # ---------------------------------------------------------------------------
197
+
198
+ # Download a single binary, install it to /usr/local/bin, clean up on failure.
199
+ # Usage: install_binary <url> <name> [mode]
200
+ install_binary() {
201
+ local url="$1"
202
+ local name="$2"
203
+ local mode="${3:-0755}"
204
+ local tmp
205
+ tmp=$(mktemp) || return 1
206
+ curl -fsSL "$url" -o "$tmp" || { rm -f "$tmp"; return 1; }
207
+ sudo install -m "$mode" "$tmp" "/usr/local/bin/$name"
208
+ local rc=$?
209
+ rm -f "$tmp"
210
+ return $rc
211
+ }
212
+
213
+ # Download a .tar.gz, extract a named binary, install to /usr/local/bin.
214
+ # Usage: install_binary_from_tar <url> <bin-in-archive> [dest-name] [mode]
215
+ install_binary_from_tar() {
216
+ local url="$1"
217
+ local bin_in_archive="$2"
218
+ local dest_name="${3:-$bin_in_archive}"
219
+ local mode="${4:-0755}"
220
+ local tmpdir
221
+ tmpdir=$(mktemp -d) || return 1
222
+ curl -fsSL "$url" -o "${tmpdir}/archive.tar.gz" || { rm -rf "$tmpdir"; return 1; }
223
+ tar -xzf "${tmpdir}/archive.tar.gz" -C "$tmpdir" "$bin_in_archive" || { rm -rf "$tmpdir"; return 1; }
224
+ sudo install -m "$mode" "${tmpdir}/${bin_in_archive}" "/usr/local/bin/${dest_name}"
225
+ local rc=$?
226
+ rm -rf "$tmpdir"
227
+ return $rc
228
+ }