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.
Files changed (143) hide show
  1. package/dist/scripts/init.js +7 -4
  2. package/dist/scripts/init.js.map +1 -1
  3. package/dist/tool/commands/adopt.d.ts.map +1 -1
  4. package/dist/tool/commands/adopt.js +1 -27
  5. package/dist/tool/commands/adopt.js.map +1 -1
  6. package/dist/tool/commands/doctor.d.ts +3 -0
  7. package/dist/tool/commands/doctor.d.ts.map +1 -1
  8. package/dist/tool/commands/doctor.js +932 -69
  9. package/dist/tool/commands/doctor.js.map +1 -1
  10. package/dist/tool/commands/explain.d.ts.map +1 -1
  11. package/dist/tool/commands/explain.js +9 -0
  12. package/dist/tool/commands/explain.js.map +1 -1
  13. package/dist/tool/questionnaire/composer.d.ts.map +1 -1
  14. package/dist/tool/questionnaire/composer.js +212 -11
  15. package/dist/tool/questionnaire/composer.js.map +1 -1
  16. package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
  17. package/dist/tool/schema/overlay-loader.js +1 -0
  18. package/dist/tool/schema/overlay-loader.js.map +1 -1
  19. package/dist/tool/schema/project-config.d.ts +1 -1
  20. package/dist/tool/schema/project-config.d.ts.map +1 -1
  21. package/dist/tool/schema/project-config.js +94 -25
  22. package/dist/tool/schema/project-config.js.map +1 -1
  23. package/dist/tool/schema/types.d.ts +85 -11
  24. package/dist/tool/schema/types.d.ts.map +1 -1
  25. package/dist/tool/utils/merge.d.ts.map +1 -1
  26. package/dist/tool/utils/merge.js +9 -0
  27. package/dist/tool/utils/merge.js.map +1 -1
  28. package/docs/creating-overlays.md +151 -2
  29. package/docs/overlay-imports.md +125 -102
  30. package/docs/overlays.md +49 -6
  31. package/docs/quick-reference.md +99 -0
  32. package/docs/specs/003-mkdocs2-overlay/spec.md +114 -0
  33. package/docs/specs/004-doctor-fix/spec.md +70 -0
  34. package/docs/specs/005-cuda-overlay/spec.md +101 -0
  35. package/docs/specs/006-rocm-overlay/spec.md +109 -0
  36. package/overlays/.shared/README.md +80 -21
  37. package/overlays/.shared/compose/common-healthchecks.md +60 -0
  38. package/overlays/.shared/vscode/recommended-extensions.json +15 -11
  39. package/overlays/alertmanager/setup.sh +4 -19
  40. package/overlays/alertmanager/verify.sh +8 -9
  41. package/overlays/all/README.md +43 -0
  42. package/overlays/all/devcontainer.patch.json +6 -0
  43. package/overlays/all/overlay.yml +14 -0
  44. package/overlays/amp/setup.sh +5 -0
  45. package/overlays/bun/setup.sh +10 -1
  46. package/overlays/bun/verify.sh +6 -1
  47. package/overlays/claude-code/setup.sh +5 -0
  48. package/overlays/cloudflared/setup.sh +9 -12
  49. package/overlays/codex/README.md +9 -6
  50. package/overlays/codex/devcontainer.patch.json +7 -1
  51. package/overlays/codex/setup.sh +5 -0
  52. package/overlays/codex/verify.sh +8 -0
  53. package/overlays/commitlint/setup.sh +5 -0
  54. package/overlays/cuda/README.md +179 -0
  55. package/overlays/cuda/devcontainer.patch.json +7 -0
  56. package/overlays/cuda/overlay.yml +17 -0
  57. package/overlays/cuda/setup.sh +32 -0
  58. package/overlays/cuda/verify.sh +38 -0
  59. package/overlays/devcontainer-cli/README.md +50 -0
  60. package/overlays/devcontainer-cli/devcontainer.patch.json +13 -0
  61. package/overlays/devcontainer-cli/overlay.yml +16 -0
  62. package/overlays/devcontainer-cli/setup.sh +14 -0
  63. package/overlays/direnv/devcontainer.patch.json +6 -0
  64. package/overlays/direnv/setup.sh +7 -6
  65. package/overlays/dotnet/setup.sh +14 -7
  66. package/overlays/duckdb/devcontainer.patch.json +1 -2
  67. package/overlays/gcloud/devcontainer.patch.json +0 -6
  68. package/overlays/gcloud/setup.sh +51 -0
  69. package/overlays/gemini-cli/setup.sh +5 -0
  70. package/overlays/git-helpers/devcontainer.patch.json +2 -1
  71. package/overlays/go/setup.sh +15 -14
  72. package/overlays/jaeger/overlay.yml +2 -0
  73. package/overlays/just/setup.sh +5 -17
  74. package/overlays/keycloak/docker-compose.yml +6 -4
  75. package/overlays/keycloak/verify.sh +4 -3
  76. package/overlays/kind/devcontainer.patch.json +1 -2
  77. package/overlays/kind/setup.sh +8 -17
  78. package/overlays/minio/setup.sh +10 -18
  79. package/overlays/mkdocs/overlay.yml +2 -1
  80. package/overlays/mkdocs2/README.md +135 -0
  81. package/overlays/mkdocs2/devcontainer.patch.json +19 -0
  82. package/overlays/mkdocs2/overlay.yml +17 -0
  83. package/overlays/mkdocs2/setup.sh +67 -0
  84. package/overlays/mkdocs2/verify.sh +35 -0
  85. package/overlays/modern-cli-tools/devcontainer.patch.json +7 -1
  86. package/overlays/modern-cli-tools/setup.sh +21 -71
  87. package/overlays/mongodb/devcontainer.patch.json +0 -6
  88. package/overlays/mongodb/setup.sh +59 -0
  89. package/overlays/mysql/verify.sh +4 -3
  90. package/overlays/nats/.env.example +1 -1
  91. package/overlays/nats/README.md +1 -1
  92. package/overlays/nats/docker-compose.yml +1 -1
  93. package/overlays/ngrok/setup.sh +9 -6
  94. package/overlays/nodejs/setup.sh +5 -0
  95. package/overlays/openapi-tools/devcontainer.patch.json +1 -2
  96. package/overlays/openapi-tools/setup.sh +9 -8
  97. package/overlays/opencode/setup.sh +5 -0
  98. package/overlays/otel-collector/overlay.yml +2 -0
  99. package/overlays/otel-collector/setup.sh +3 -16
  100. package/overlays/otel-demo-nodejs/verify.sh +8 -9
  101. package/overlays/otel-demo-python/verify.sh +16 -10
  102. package/overlays/pandoc/README.md +22 -15
  103. package/overlays/pandoc/devcontainer.patch.json +6 -2
  104. package/overlays/pandoc/setup.sh +217 -18
  105. package/overlays/pandoc/verify.sh +16 -4
  106. package/overlays/playwright/devcontainer.patch.json +3 -1
  107. package/overlays/playwright/setup.sh +37 -0
  108. package/overlays/postgres/docker-compose.yml +6 -0
  109. package/overlays/powershell/setup.sh +49 -13
  110. package/overlays/pre-commit/setup.sh +12 -3
  111. package/overlays/prometheus/overlay.yml +2 -0
  112. package/overlays/promtail/verify.sh +16 -10
  113. package/overlays/pulumi/devcontainer.patch.json +1 -1
  114. package/overlays/python/setup.sh +28 -9
  115. package/overlays/python/verify.sh +4 -2
  116. package/overlays/redpanda/docker-compose.yml +3 -5
  117. package/overlays/rocm/README.md +227 -0
  118. package/overlays/rocm/devcontainer.patch.json +4 -0
  119. package/overlays/rocm/overlay.yml +17 -0
  120. package/overlays/rocm/setup.sh +45 -0
  121. package/overlays/rocm/verify.sh +47 -0
  122. package/overlays/rust/setup.sh +11 -18
  123. package/overlays/spec-kit/setup.sh +7 -3
  124. package/overlays/sqlite/setup.sh +14 -14
  125. package/overlays/sqlserver/docker-compose.yml +3 -3
  126. package/overlays/sqlserver/verify.sh +22 -5
  127. package/overlays/tempo/verify.sh +16 -10
  128. package/overlays/tilt/devcontainer.patch.json +1 -2
  129. package/overlays/tilt/setup.sh +14 -4
  130. package/overlays/windsurf-cli/setup.sh +27 -4
  131. package/overlays/windsurf-cli/verify.sh +13 -3
  132. package/package.json +2 -1
  133. package/templates/scripts/setup-utils.sh +228 -0
  134. package/tool/schema/config.schema.json +110 -8
  135. package/tool/schema/overlay-manifest.schema.json +5 -0
  136. package/overlays/.shared/compose/common-healthchecks.yml +0 -38
  137. /package/overlays/otel-demo-nodejs/{Dockerfile-otel-demo-nodejs → Dockerfile} +0 -0
  138. /package/overlays/otel-demo-nodejs/{package-otel-demo-nodejs.json → package.json} +0 -0
  139. /package/overlays/otel-demo-nodejs/{server-otel-demo-nodejs.js → server.js} +0 -0
  140. /package/overlays/otel-demo-nodejs/{tracing-otel-demo-nodejs.js → tracing.js} +0 -0
  141. /package/overlays/otel-demo-python/{Dockerfile-otel-demo-python → Dockerfile} +0 -0
  142. /package/overlays/otel-demo-python/{app-otel-demo-python.py → app.py} +0 -0
  143. /package/overlays/otel-demo-python/{requirements-otel-demo-python.txt → requirements.txt} +0 -0
@@ -1,94 +1,44 @@
1
1
  #!/bin/bash
2
2
  # Modern CLI tools setup script
3
+ # jq, ripgrep, fd, bat are installed via cross-distro-packages devcontainer feature.
4
+ # This script installs yq (not in standard repos), creates Debian symlinks, and configures tools.
3
5
 
4
6
  set -e
5
7
 
6
8
  echo "🚀 Setting up modern CLI tools..."
7
9
 
8
- # Update package list
9
- sudo apt-get update -qq
10
-
11
- # Install jq (JSON processor)
12
- echo "📦 Installing jq..."
13
- sudo apt-get install -y jq
14
- if command -v jq &> /dev/null; then
15
- echo "✓ jq installed: $(jq --version)"
16
- else
17
- echo "✗ jq installation failed"
18
- exit 1
19
- fi
20
-
21
- # Install yq (YAML processor)
10
+ # Install yq (YAML processor — not in standard distro repos)
22
11
  echo "📦 Installing yq..."
23
- YQ_VERSION="4.52.2"
12
+ YQ_VERSION="${YQ_VERSION:-4.52.2}"
24
13
  ARCH=$(uname -m)
14
+ case "$ARCH" in
15
+ x86_64) YQ_ARCH="amd64" ;;
16
+ aarch64|arm64) YQ_ARCH="arm64" ;;
17
+ *) echo "⚠️ Unsupported architecture: $ARCH, defaulting to amd64"; YQ_ARCH="amd64" ;;
18
+ esac
25
19
 
26
- # SHA256 checksums for yq v4.52.2
27
- if [ "$ARCH" = "x86_64" ]; then
28
- YQ_ARCH="amd64"
29
- YQ_CHECKSUM="a74bd266990339e0c48a2103534aef692abf99f19390d12c2b0ce6830385c459"
30
- elif [ "$ARCH" = "aarch64" ] || [ "$ARCH" = "arm64" ]; then
31
- YQ_ARCH="arm64"
32
- YQ_CHECKSUM="c82856ac30da522f50dcdd4f53065487b5a2927e9b87ff637956900986f1f7c2"
33
- else
34
- echo "⚠️ Unsupported architecture: $ARCH, defaulting to amd64"
35
- YQ_ARCH="amd64"
36
- YQ_CHECKSUM="a74bd266990339e0c48a2103534aef692abf99f19390d12c2b0ce6830385c459"
37
- fi
38
-
39
- curl -L "https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/yq_linux_${YQ_ARCH}" \
20
+ curl -fsSL "https://github.com/mikefarah/yq/releases/download/v${YQ_VERSION}/yq_linux_${YQ_ARCH}" \
40
21
  -o /tmp/yq
22
+ sudo install -m 0755 /tmp/yq /usr/local/bin/yq
23
+ rm /tmp/yq
41
24
 
42
- # Verify checksum
43
- echo "🔐 Verifying yq checksum..."
44
- echo "${YQ_CHECKSUM} /tmp/yq" | sha256sum -c - || {
45
- echo "✗ yq checksum verification failed"
46
- rm /tmp/yq
47
- exit 1
48
- }
49
-
50
- sudo mv /tmp/yq /usr/local/bin/yq
51
- sudo chmod +x /usr/local/bin/yq
52
-
53
- if command -v yq &> /dev/null; then
25
+ if command -v yq &>/dev/null; then
54
26
  echo "✓ yq installed: $(yq --version)"
55
27
  else
56
28
  echo "✗ yq installation failed"
57
29
  exit 1
58
30
  fi
59
31
 
60
- # Install ripgrep (fast grep alternative)
61
- echo "📦 Installing ripgrep..."
62
- sudo apt-get install -y ripgrep
63
- if command -v rg &> /dev/null; then
64
- echo "✓ ripgrep installed: $(rg --version | head -n 1)"
65
- else
66
- echo "✗ ripgrep installation failed"
67
- exit 1
32
+ # Create fd symlink Debian installs the binary as 'fdfind'
33
+ if command -v fdfind &>/dev/null && ! command -v fd &>/dev/null; then
34
+ sudo ln -sf "$(which fdfind)" /usr/local/bin/fd
35
+ echo "✓ fd symlink created (fdfind → fd)"
68
36
  fi
69
37
 
70
- # Install fd (fast find alternative)
71
- echo "📦 Installing fd..."
72
- sudo apt-get install -y fd-find
73
- # Create symlink for 'fd' command (package installs as 'fdfind' on Debian)
74
- sudo ln -sf $(which fdfind) /usr/local/bin/fd
75
- if command -v fd &> /dev/null; then
76
- echo "✓ fd installed: $(fd --version)"
77
- else
78
- echo "✗ fd installation failed"
79
- exit 1
80
- fi
81
-
82
- # Install bat (better cat with syntax highlighting)
83
- echo "📦 Installing bat..."
84
- sudo apt-get install -y bat
85
- # Create symlink for 'bat' command (package installs as 'batcat' on Debian)
86
- sudo ln -sf $(which batcat) /usr/local/bin/bat
87
- if command -v bat &> /dev/null; then
88
- echo "✓ bat installed: $(bat --version)"
89
- else
90
- echo "✗ bat installation failed"
91
- exit 1
38
+ # Create bat symlink Debian installs the binary as 'batcat'
39
+ if command -v batcat &>/dev/null && ! command -v bat &>/dev/null; then
40
+ sudo ln -sf "$(which batcat)" /usr/local/bin/bat
41
+ echo "✓ bat symlink created (batcat bat)"
92
42
  fi
93
43
 
94
44
  # Configure bat
@@ -1,11 +1,5 @@
1
1
  {
2
2
  "$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.base.schema.json",
3
- "features": {
4
- "./features/cross-distro-packages": {
5
- "apt": "mongodb-mongosh",
6
- "apk": "mongodb-tools"
7
- }
8
- },
9
3
  "customizations": {
10
4
  "vscode": {
11
5
  "extensions": ["mongodb.mongodb-vscode"]
@@ -0,0 +1,59 @@
1
+ #!/bin/bash
2
+ # MongoDB setup script - Install mongosh client
3
+
4
+ set -e
5
+
6
+ echo "📦 Installing mongosh client..."
7
+
8
+ # Source shared setup utilities
9
+ # shellcheck source=setup-utils.sh
10
+ source "$(dirname "${BASH_SOURCE[0]}")/setup-utils.sh"
11
+
12
+ if command -v apk >/dev/null 2>&1; then
13
+ # Alpine Linux — `mongodb-tools` does not include mongosh on Alpine.
14
+ # Install mongosh from the MongoDB community package (available on Alpine 3.17+).
15
+ apk add --no-cache mongodb-mongosh 2>/dev/null || {
16
+ echo "⚠️ mongosh package not found in Alpine repos; falling back to npm install"
17
+ apk add --no-cache nodejs npm
18
+ npm install -g mongosh
19
+ }
20
+ elif command -v apt-get >/dev/null 2>&1; then
21
+ # Debian/Ubuntu — install prerequisites first, then add the MongoDB repo.
22
+ # MongoDB doesn't publish a trixie/sid repo yet; fall back to bookworm.
23
+ CODENAME=$(. /etc/os-release && echo "${VERSION_CODENAME:-bookworm}")
24
+ case "$CODENAME" in
25
+ trixie | sid | testing) CODENAME="bookworm" ;;
26
+ esac
27
+
28
+ # Single lock acquisition: install prereqs, add repo, update, install mongosh.
29
+ # curl and gnupg must be present before add_apt_repo runs them.
30
+ acquire_apt_lock
31
+ sudo DEBIAN_FRONTEND=noninteractive TERM=dumb apt-get update -qq
32
+ sudo DEBIAN_FRONTEND=noninteractive TERM=dumb apt-get install -y -qq --no-install-recommends curl gnupg ca-certificates
33
+ release_apt_lock
34
+
35
+ add_apt_repo \
36
+ "https://www.mongodb.org/static/pgp/server-8.0.asc" \
37
+ "/usr/share/keyrings/mongodb-server.gpg" \
38
+ "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server.gpg ] https://repo.mongodb.org/apt/debian ${CODENAME}/mongodb-org/8.0 main" \
39
+ "/etc/apt/sources.list.d/mongodb-org.list"
40
+
41
+ acquire_apt_lock
42
+ sudo DEBIAN_FRONTEND=noninteractive TERM=dumb apt-get update -qq
43
+ sudo DEBIAN_FRONTEND=noninteractive TERM=dumb apt-get install -y -qq --no-install-recommends mongodb-mongosh
44
+ sudo apt-get clean
45
+ sudo rm -rf /var/lib/apt/lists/*
46
+ release_apt_lock
47
+ else
48
+ echo "⚠️ Unsupported package manager, skipping mongosh installation"
49
+ exit 0
50
+ fi
51
+
52
+ if command -v mongosh >/dev/null 2>&1; then
53
+ echo "✓ mongosh installed: $(mongosh --version)"
54
+ else
55
+ echo "✗ mongosh installation failed"
56
+ exit 1
57
+ fi
58
+
59
+ echo "✓ mongodb setup complete"
@@ -21,8 +21,9 @@ fi
21
21
  echo ""
22
22
  echo "2️⃣ Checking MySQL service..."
23
23
  MYSQL_READY=false
24
- for i in {1..15}; do
25
- if mysql -h mysql -P 3306 -u root -prootpassword -e "SELECT 1" &> /dev/null; then
24
+ for i in {1..90}; do
25
+ # MYSQL_PWD avoids interactive prompt; </dev/null prevents TTY queries.
26
+ if MYSQL_PWD=rootpassword mysql -h mysql -P 3306 -u root -e "SELECT 1" </dev/null &>/dev/null; then
26
27
  echo " ✅ MySQL service is ready"
27
28
  MYSQL_READY=true
28
29
  break
@@ -31,7 +32,7 @@ for i in {1..15}; do
31
32
  done
32
33
 
33
34
  if [ "$MYSQL_READY" = false ]; then
34
- echo " ❌ MySQL service not ready after 15 seconds"
35
+ echo " ❌ MySQL service not ready after 90 seconds"
35
36
  exit 1
36
37
  fi
37
38
 
@@ -1,5 +1,5 @@
1
1
  # NATS Configuration
2
- NATS_VERSION=latest
2
+ NATS_VERSION=2
3
3
  NATS_CLIENT_PORT=4222
4
4
  NATS_HTTP_PORT=8222
5
5
  NATS_CLUSTER_PORT=6222
@@ -39,7 +39,7 @@ cp .env.example .env
39
39
 
40
40
  ```bash
41
41
  # NATS Configuration
42
- NATS_VERSION=latest
42
+ NATS_VERSION=2
43
43
  NATS_CLIENT_PORT=4222
44
44
  NATS_HTTP_PORT=8222
45
45
  NATS_CLUSTER_PORT=6222
@@ -2,7 +2,7 @@ version: '3.8'
2
2
 
3
3
  services:
4
4
  nats:
5
- image: nats:${NATS_VERSION:-latest}-alpine
5
+ image: nats:${NATS_VERSION:-2}-alpine
6
6
  restart: unless-stopped
7
7
  command:
8
8
  - '--jetstream'
@@ -8,16 +8,19 @@ echo "🌐 Setting up ngrok..."
8
8
  # Install ngrok using official apt repository (provides signed packages)
9
9
  echo "📦 Installing ngrok from official repository..."
10
10
 
11
- # Add ngrok's GPG key and repository
12
- curl -sSL https://ngrok-agent.s3.amazonaws.com/ngrok.asc \
13
- | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null
11
+ # Source shared setup utilities
12
+ # shellcheck source=setup-utils.sh
13
+ source "$(dirname "${BASH_SOURCE[0]}")/setup-utils.sh"
14
14
 
15
+ # Add ngrok GPG key and repository
16
+ # Note: ngrok uses .asc (armored) format, piped directly to trusted.gpg.d (no --dearmor needed)
17
+ curl -fsSL https://ngrok-agent.s3.amazonaws.com/ngrok.asc \
18
+ | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null
15
19
  echo "deb https://ngrok-agent.s3.amazonaws.com buster main" \
16
- | sudo tee /etc/apt/sources.list.d/ngrok.list
20
+ | sudo tee /etc/apt/sources.list.d/ngrok.list >/dev/null
17
21
 
18
22
  # Update and install
19
- sudo apt-get update -qq
20
- sudo apt-get install -y ngrok
23
+ apt_install ngrok
21
24
 
22
25
  # Verify installation
23
26
  if command -v ngrok &> /dev/null; then
@@ -3,6 +3,11 @@
3
3
 
4
4
  set -e
5
5
 
6
+ # Source shared setup utilities (provides load_nvm)
7
+ # shellcheck source=setup-utils.sh
8
+ source "$(dirname "${BASH_SOURCE[0]}")/setup-utils.sh"
9
+ load_nvm
10
+
6
11
  # Extract overlay name from script filename (setup-<overlay>.sh -> <overlay>)
7
12
  OVERLAY_NAME=$(basename "$0" | sed 's/setup-//;s/\.sh$//')
8
13
 
@@ -5,6 +5,5 @@
5
5
  "apt": "curl",
6
6
  "apk": "curl"
7
7
  }
8
- },
9
- "postCreateCommand": "bash .devcontainer/scripts/setup-openapi-tools.sh"
8
+ }
10
9
  }
@@ -3,19 +3,20 @@
3
3
 
4
4
  set -e
5
5
 
6
+ # Source shared setup utilities (provides load_nvm)
7
+ # shellcheck source=setup-utils.sh
8
+ source "$(dirname "${BASH_SOURCE[0]}")/setup-utils.sh"
9
+ load_nvm
10
+
6
11
  echo "🔧 Setting up OpenAPI Tools..."
7
12
 
8
13
  # Install OpenAPI tools globally via npm
9
14
  echo "📦 Installing OpenAPI tools..."
10
15
 
11
- # Install swagger-cli (OpenAPI validation)
12
- npm install -g @apidevtools/swagger-cli || echo "⚠️ swagger-cli already installed or failed"
13
-
14
- # Install spectral (OpenAPI linting)
15
- npm install -g @stoplight/spectral-cli || echo "⚠️ spectral already installed or failed"
16
-
17
- # Install redocly CLI (documentation and bundling)
18
- npm install -g @redocly/cli || echo "⚠️ redocly already installed or failed"
16
+ # Wrap each install in run_spinner to suppress noisy deprecation warnings
17
+ run_spinner "swagger-cli" npm install -g @apidevtools/swagger-cli
18
+ run_spinner "spectral" npm install -g @stoplight/spectral-cli
19
+ run_spinner "redocly" npm install -g @redocly/cli
19
20
 
20
21
  # Verify installations
21
22
  echo ""
@@ -3,6 +3,11 @@
3
3
 
4
4
  set -e
5
5
 
6
+ # Source shared setup utilities (provides load_nvm)
7
+ # shellcheck source=setup-utils.sh
8
+ source "$(dirname "${BASH_SOURCE[0]}")/setup-utils.sh"
9
+ load_nvm
10
+
6
11
  echo "📦 Installing opencode AI coding agent..."
7
12
 
8
13
  # Install opencode-ai globally
@@ -19,3 +19,5 @@ ports:
19
19
  - 8888
20
20
  - 8889
21
21
  order: 2
22
+ imports:
23
+ - .shared/otel/instrumentation.env
@@ -5,23 +5,10 @@ set -e
5
5
 
6
6
  echo "🔧 Configuring OpenTelemetry Collector trace backend..."
7
7
 
8
- # Determine workspace root dynamically
9
- WORKSPACE_ROOT="${LOCAL_WORKSPACE_FOLDER:-$PWD}"
10
-
11
- if [ ! -d "$WORKSPACE_ROOT/.devcontainer" ]; then
12
- if [ -d "/workspaces" ]; then
13
- FIRST_WORKSPACE_DIR="$(find /workspaces -maxdepth 1 -mindepth 1 -type d 2>/dev/null | head -n 1)"
14
- if [ -n "$FIRST_WORKSPACE_DIR" ] && [ -d "$FIRST_WORKSPACE_DIR/.devcontainer" ]; then
15
- WORKSPACE_ROOT="$FIRST_WORKSPACE_DIR"
16
- fi
17
- fi
18
- fi
19
-
20
- if [ ! -d "$WORKSPACE_ROOT/.devcontainer" ] && [ -d "/workspace/.devcontainer" ]; then
21
- WORKSPACE_ROOT="/workspace"
22
- fi
8
+ # Resolve the .devcontainer directory relative to this script.
9
+ DEVCONTAINER_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd .. && pwd)"
23
10
 
24
- OTEL_CONFIG="$WORKSPACE_ROOT/.devcontainer/otel-collector-config-otel-collector.yaml"
11
+ OTEL_CONFIG="$DEVCONTAINER_DIR/otel-collector-config-otel-collector.yaml"
25
12
 
26
13
  if [ ! -f "$OTEL_CONFIG" ]; then
27
14
  echo "⚠️ OTel Collector config not found"
@@ -6,19 +6,18 @@ echo "🔍 Verifying OTel Demo (Node.js) installation..."
6
6
  # Track overall success
7
7
  ALL_CHECKS_PASSED=true
8
8
 
9
- # Check if service is running
10
- if docker ps --format '{{.Names}}' | grep -q otel-demo-nodejs; then
11
- echo " OTel Demo (Node.js) service is running"
9
+ # Check if HTTP health endpoint is accessible (primary health signal).
10
+ # docker ps is informational only not reliably accessible in all devcontainers.
11
+ if curl -s -o /dev/null -w "%{http_code}" http://otel-demo-nodejs:8080/health 2>/dev/null | grep -q "200"; then
12
+ echo "✓ Demo app HTTP endpoint is accessible"
12
13
  else
13
- echo "✗ OTel Demo (Node.js) service is not running"
14
+ echo "✗ Demo app HTTP endpoint not responding (http://otel-demo-nodejs:8080/health)"
14
15
  ALL_CHECKS_PASSED=false
15
16
  fi
16
17
 
17
- # Check if HTTP endpoint is accessible
18
- if curl -s -o /dev/null -w "%{http_code}" http://otel-demo-nodejs:8080/health 2>/dev/null | grep -q "200"; then
19
- echo "✓ Demo app HTTP endpoint is accessible"
20
- else
21
- echo "⚠️ Demo app HTTP endpoint not responding yet (may still be starting)"
18
+ # Informational: check via docker ps if available.
19
+ if docker ps --format '{{.Names}}' 2>/dev/null | grep -q otel-demo-nodejs; then
20
+ echo "✓ OTel Demo (Node.js) container visible in docker ps"
22
21
  fi
23
22
 
24
23
  # Final result
@@ -6,19 +6,25 @@ echo "🔍 Verifying OTel Demo (Python) installation..."
6
6
  # Track overall success
7
7
  ALL_CHECKS_PASSED=true
8
8
 
9
- # Check if service is running
10
- if docker ps --format '{{.Names}}' | grep -q otel-demo-python; then
11
- echo "✓ OTel Demo (Python) service is running"
12
- else
13
- echo " OTel Demo (Python) service is not running"
9
+ # Wait for demo app HTTP health endpoint (primary health signal).
10
+ # docker ps is informational only not reliably accessible in all devcontainers.
11
+ APP_READY=false
12
+ for i in {1..40}; do
13
+ if curl -s -o /dev/null -w "%{http_code}" http://otel-demo-python:8081/health 2>/dev/null | grep -q "200"; then
14
+ echo "✓ Demo app HTTP endpoint is accessible"
15
+ APP_READY=true
16
+ break
17
+ fi
18
+ sleep 3
19
+ done
20
+ if [ "$APP_READY" = false ]; then
21
+ echo "✗ Demo app HTTP endpoint not responding after 120 s (http://otel-demo-python:8081/health)"
14
22
  ALL_CHECKS_PASSED=false
15
23
  fi
16
24
 
17
- # Check if HTTP endpoint is accessible
18
- if curl -s -o /dev/null -w "%{http_code}" http://otel-demo-python:8081/health 2>/dev/null | grep -q "200"; then
19
- echo "✓ Demo app HTTP endpoint is accessible"
20
- else
21
- echo "⚠️ Demo app HTTP endpoint 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 otel-demo-python; then
27
+ echo "✓ OTel Demo (Python) container visible in docker ps"
22
28
  fi
23
29
 
24
30
  # Final result
@@ -6,9 +6,10 @@ Adds a complete Markdown → PDF pipeline to your devcontainer, powered by Pando
6
6
 
7
7
  - **Pandoc 3.x** — Latest release binary from GitHub (not the outdated apt version)
8
8
  - **TeX Live / XeLaTeX** — Full Unicode-capable PDF engine (`texlive-xetex`, `texlive-fonts-extra`, `texlive-latex-extra`)
9
- - **Quality fonts** — Carlito (body), JetBrains Mono (code), Noto Sans Symbols 2 (Unicode fallback) via system packages
9
+ - **Quality fonts** — Carlito (body), JetBrains Mono (code), Noto Sans Symbols 2 (Unicode fallback), and Noto Color Emoji via system packages
10
10
  - Uses the `cross-distro-packages` feature with fallback package names for Carlito (`fonts-carlito|fonts-crosextra-carlito`)
11
11
  - **`diagram.lua`** — Lua filter from [pandoc-ext/diagram](https://github.com/pandoc-ext/diagram) for rendering code-block diagrams
12
+ - **`emoji-fallback.lua`** — Built-in Lua filter that rewrites unsupported emoji and flag glyphs to plain-text placeholders for reliable XeLaTeX PDF builds
12
13
  - **Mermaid CLI (`mmdc`)** — Installed when the `nodejs` overlay is present; skipped gracefully otherwise
13
14
  - **`~/.pandoc/pandoc.yaml`** — Ready-to-use defaults file (XeLaTeX engine, font settings, table tweaks)
14
15
  - **VS Code Extensions:** Markdown All in One (`yzhang.markdown-all-in-one`), markdownlint (`DavidAnson.vscode-markdownlint`)
@@ -30,13 +31,17 @@ Markdown
30
31
 
31
32
  Font discovery is updated with `fc-cache -fv` after installation so XeLaTeX can locate the apt-installed fonts.
32
33
 
34
+ The generated defaults also enable an emoji fallback filter for LaTeX output. The overlay now installs Noto Color Emoji as well, which may improve glyph coverage in some contexts, but the fallback filter remains enabled because XeLaTeX still is not reliable for full emoji and flag rendering. The filter converts unsupported glyphs such as `🇵🇹` to `[PT]` and generic emoji such as `😀` to `[emoji]` before XeLaTeX runs, preventing the `Unicode character ... not set up for use with LaTeX` failure.
35
+
36
+ The setup script also installs a `/usr/local/bin/pandoc` wrapper that automatically applies `~/.pandoc/pandoc.yaml` unless you explicitly pass `-d` or `--defaults`. That makes plain commands like `pandoc doc.md -o doc.pdf` use the overlay defaults.
37
+
33
38
  ## Common Commands
34
39
 
35
40
  ### Basic PDF export
36
41
 
37
42
  ```bash
38
- # Use the default pandoc.yaml
39
- pandoc -d ~/.pandoc/pandoc.yaml document.md -o document.pdf
43
+ # Uses the installed wrapper, which applies ~/.pandoc/pandoc.yaml automatically
44
+ pandoc document.md -o document.pdf
40
45
 
41
46
  # Override the output font on the fly
42
47
  pandoc -d ~/.pandoc/pandoc.yaml -V mainfont="DejaVu Serif" document.md -o document.pdf
@@ -45,8 +50,7 @@ pandoc -d ~/.pandoc/pandoc.yaml -V mainfont="DejaVu Serif" document.md -o docume
45
50
  ### PDF with Mermaid diagrams (requires nodejs overlay)
46
51
 
47
52
  ```bash
48
- pandoc -d ~/.pandoc/pandoc.yaml \
49
- --lua-filter ~/.pandoc/filters/diagram.lua \
53
+ pandoc --lua-filter ~/.pandoc/filters/diagram.lua \
50
54
  document.md -o document.pdf
51
55
  ```
52
56
 
@@ -95,6 +99,8 @@ The setup script writes a defaults file with proven settings:
95
99
 
96
100
  ```yaml
97
101
  pdf-engine: xelatex
102
+ filters:
103
+ - /home/your-user/.pandoc/filters/emoji-fallback.lua
98
104
 
99
105
  variables:
100
106
  mainfont: 'Carlito'
@@ -129,8 +135,9 @@ variables:
129
135
  toc: true
130
136
  toc-depth: 3
131
137
  number-sections: true
132
- lua-filter:
133
- - ~/.pandoc/filters/diagram.lua
138
+ filters:
139
+ - /home/your-user/.pandoc/filters/emoji-fallback.lua
140
+ - /home/your-user/.pandoc/filters/diagram.lua
134
141
  ```
135
142
 
136
143
  Then build with:
@@ -154,21 +161,21 @@ number-sections: true
154
161
  Uncomment in `~/.pandoc/pandoc.yaml`:
155
162
 
156
163
  ```yaml
157
- lua-filter:
158
- - ~/.pandoc/filters/diagram.lua
164
+ filters:
165
+ - /home/your-user/.pandoc/filters/emoji-fallback.lua
166
+ - /home/your-user/.pandoc/filters/diagram.lua
159
167
  ```
160
168
 
161
169
  ## Unicode and Emoji
162
170
 
163
- XeLaTeX handles Unicode well with the Noto and Carlito fonts, but emoji (🎉 🚀) require a colour emoji font (e.g. `fonts-noto-color-emoji`) which is not installed by default due to size. For documents with emoji, either:
171
+ XeLaTeX handles normal Unicode text well with the bundled fonts. The overlay now also installs Noto Color Emoji, which can help with emoji coverage, but the failure mode in PDF builds is still usually emoji or regional-indicator flags, for example `🇵🇹`, which XeLaTeX may reject before font fallback can help.
164
172
 
165
- 1. Replace emoji with text equivalents before generating the PDF:
173
+ The overlay now enables `~/.pandoc/filters/emoji-fallback.lua` by default for LaTeX output. It keeps normal Unicode text intact and rewrites unsupported emoji to plain-text placeholders:
166
174
 
167
- ```bash
168
- sed 's/🎉/[celebration]/g; s/🚀/[rocket]/g' doc.md | pandoc -d ~/.pandoc/pandoc.yaml -o doc.pdf
169
- ```
175
+ - `🇵🇹 Porto` becomes `[PT] Porto`
176
+ - `😀` becomes `[emoji]`
170
177
 
171
- 2. Install `fonts-noto-color-emoji` and add `\setmainfont{Noto Color Emoji}` for the emoji font fallback in your `header-includes`.
178
+ If you want to experiment with more native emoji rendering, keep the installed emoji font and override the default Pandoc/LaTeX settings in a project-local `pandoc.yaml`, but the placeholder filter is still the reliable default for PDF generation.
172
179
 
173
180
  ## Use Cases
174
181
 
@@ -2,13 +2,17 @@
2
2
  "$schema": "https://raw.githubusercontent.com/devcontainers/spec/main/schemas/devContainer.base.schema.json",
3
3
  "features": {
4
4
  "./features/cross-distro-packages": {
5
- "apt": "texlive-xetex texlive-fonts-recommended texlive-fonts-extra texlive-latex-extra texlive-lang-european fonts-carlito|fonts-crosextra-carlito fonts-noto fonts-noto-extra fonts-noto-mono fonts-jetbrains-mono fontconfig perl chromium",
6
- "apk": "fontconfig perl chromium"
5
+ "apt": "texlive-xetex texlive-fonts-recommended texlive-fonts-extra texlive-latex-extra texlive-lang-european lmodern fonts-carlito|fonts-crosextra-carlito fonts-noto fonts-noto-extra fonts-noto-mono fonts-jetbrains-mono fonts-noto-color-emoji fontconfig librsvg2-bin perl chromium",
6
+ "apk": "fontconfig noto-fonts-emoji|noto-emoji perl chromium"
7
7
  }
8
8
  },
9
9
  "customizations": {
10
10
  "vscode": {
11
11
  "extensions": ["yzhang.markdown-all-in-one", "DavidAnson.vscode-markdownlint"]
12
12
  }
13
+ },
14
+ "remoteEnv": {
15
+ "PUPPETEER_EXECUTABLE_PATH": "/usr/local/bin/chromium-no-sandbox",
16
+ "PUPPETEER_SKIP_DOWNLOAD": "true"
13
17
  }
14
18
  }