@getmonoceros/workbench 1.21.2 → 1.22.0

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 (36) hide show
  1. package/bundled-components/features/atlassian/component.yml +52 -0
  2. package/bundled-components/features/atlassian/install.sh +176 -0
  3. package/bundled-components/features/claude-code/component.yml +32 -0
  4. package/bundled-components/features/claude-code/install.sh +56 -0
  5. package/bundled-components/features/github-cli/component.yml +18 -0
  6. package/bundled-components/features/github-cli/install.sh +53 -0
  7. package/bundled-components/languages/dotnet/component.yml +8 -0
  8. package/bundled-components/languages/go/component.yml +8 -0
  9. package/bundled-components/languages/java/component.yml +17 -0
  10. package/bundled-components/languages/node/component.yml +9 -0
  11. package/bundled-components/languages/python/component.yml +8 -0
  12. package/bundled-components/languages/rust/component.yml +8 -0
  13. package/bundled-components/services/mysql/component.yml +40 -0
  14. package/bundled-components/services/postgres/component.yml +34 -0
  15. package/bundled-components/services/redis/component.yml +16 -0
  16. package/dist/bin.js +791 -369
  17. package/dist/bin.js.map +1 -1
  18. package/package.json +5 -4
  19. package/features/atlassian/devcontainer-feature.json +0 -67
  20. package/features/claude-code/devcontainer-feature.json +0 -49
  21. package/features/github-cli/devcontainer-feature.json +0 -32
  22. package/templates/components/README.md +0 -95
  23. package/templates/components/atlassian/rovodev.yml +0 -14
  24. package/templates/components/atlassian/twg.yml +0 -14
  25. package/templates/components/atlassian.yml +0 -15
  26. package/templates/components/claude.yml +0 -16
  27. package/templates/components/dotnet.yml +0 -8
  28. package/templates/components/github.yml +0 -10
  29. package/templates/components/go.yml +0 -8
  30. package/templates/components/java.yml +0 -9
  31. package/templates/components/mysql.yml +0 -8
  32. package/templates/components/node.yml +0 -9
  33. package/templates/components/postgres.yml +0 -10
  34. package/templates/components/python.yml +0 -9
  35. package/templates/components/redis.yml +0 -7
  36. package/templates/components/rust.yml +0 -8
@@ -0,0 +1,52 @@
1
+ id: atlassian
2
+ category: feature
3
+ displayName: Atlassian
4
+ description: 'Rovo Dev (`acli rovodev`) and Teamwork Graph (`twg`) CLIs sharing one Atlassian account. Auth persists across rebuilds.'
5
+ documentationURL: https://developer.atlassian.com/cloud/
6
+ options:
7
+ rovodev:
8
+ type: boolean
9
+ default: true
10
+ description: 'Install acli (with the Rovo Dev agent).'
11
+ surface: yml
12
+ twg:
13
+ type: boolean
14
+ default: true
15
+ description: 'Install twg (Teamwork Graph CLI).'
16
+ surface: yml
17
+ instance:
18
+ type: string
19
+ default: ''
20
+ description: 'Atlassian site host (`yoursite.atlassian.net`); required by twg.'
21
+ surface: env
22
+ email:
23
+ type: string
24
+ default: ''
25
+ description: 'Atlassian account email; used with `apiToken` for non-interactive login.'
26
+ surface: env
27
+ apiToken:
28
+ type: string
29
+ default: ''
30
+ description: 'Atlassian API token (id.atlassian.com → Security → API tokens).'
31
+ surface: env
32
+ bitbucketToken:
33
+ type: string
34
+ default: ''
35
+ description: "Optional Bitbucket app password; only needed for twg's Bitbucket commands."
36
+ surface: env
37
+ feature:
38
+ version: 1.0.0
39
+ persistentHomePaths: [.config/acli, .rovodev, .config/twg, .agents]
40
+ vscodeExtensions: [Atlassian.atlascode]
41
+ briefing:
42
+ - whenOption: rovodev
43
+ text: 'Atlassian Rovo Dev — invoke via `acli rovodev`. Pre-authenticated against the Atlassian account configured in the feature options (shared with twg).'
44
+ - whenOption: twg
45
+ text: 'Atlassian Teamwork Graph CLI (`twg`) — work-data access across Jira, Confluence, Bitbucket, JSM and Assets. Pre-authenticated. Sub-skills cover status rollups, engineering work, ops health and context discovery.'
46
+ presets:
47
+ twg:
48
+ rovodev: false
49
+ twg: true
50
+ rovodev:
51
+ rovodev: true
52
+ twg: false
@@ -0,0 +1,176 @@
1
+ #!/usr/bin/env bash
2
+ # Monoceros devcontainer feature: atlassian.
3
+ #
4
+ # Installs Atlassian CLIs that share a single Atlassian account:
5
+ # - Rovo Dev (acli, default on) — the `acli rovodev` AI agent
6
+ # - Teamwork Graph (twg, default off)
7
+ #
8
+ # Each tool is toggled independently via the `rovodev` / `twg`
9
+ # options. Credentials (instance / email / apiToken) are shared
10
+ # across both tools when set; per-tool post-create hooks under
11
+ # /usr/local/share/monoceros/post-create.d/ perform the
12
+ # non-interactive login on first container start.
13
+
14
+ set -euo pipefail
15
+
16
+ ROVODEV="${ROVODEV:-true}"
17
+ TWG="${TWG:-true}"
18
+ INSTANCE="${INSTANCE:-}"
19
+ EMAIL="${EMAIL:-}"
20
+ APITOKEN="${APITOKEN:-}"
21
+ BITBUCKETTOKEN="${BITBUCKETTOKEN:-}"
22
+
23
+ if [ "${ROVODEV}" != "true" ] && [ "${TWG}" != "true" ]; then
24
+ echo "[atlassian] both rovodev and twg disabled — nothing to install" >&2
25
+ exit 0
26
+ fi
27
+
28
+ ARCH="$(dpkg --print-architecture)"
29
+ case "${ARCH}" in
30
+ amd64 | arm64) ;;
31
+ *)
32
+ echo "[atlassian] unsupported architecture: ${ARCH}" >&2
33
+ exit 1
34
+ ;;
35
+ esac
36
+
37
+ POST_CREATE_DIR=/usr/local/share/monoceros/post-create.d
38
+ mkdir -p "${POST_CREATE_DIR}"
39
+
40
+ # ─── Rovo Dev (acli) ──────────────────────────────────────────────
41
+ if [ "${ROVODEV}" = "true" ]; then
42
+ ACLI_URL="https://acli.atlassian.com/linux/latest/acli_linux_${ARCH}/acli"
43
+ echo "[atlassian/rovodev] downloading acli for ${ARCH} from ${ACLI_URL}"
44
+ TMP="$(mktemp)"
45
+ curl -fsSL -o "${TMP}" "${ACLI_URL}"
46
+ install -o root -g root -m 0755 "${TMP}" /usr/local/bin/acli
47
+ rm -f "${TMP}"
48
+ acli --version >/dev/null 2>&1 || {
49
+ echo "[atlassian/rovodev] ERROR: install completed but \`acli\` is not on PATH" >&2
50
+ exit 1
51
+ }
52
+
53
+ HOOK="${POST_CREATE_DIR}/atlassian-rovodev.sh"
54
+ if [ -n "${EMAIL}" ] && [ -n "${APITOKEN}" ]; then
55
+ cat >"${HOOK}" <<EOF
56
+ #!/usr/bin/env bash
57
+ # Auto-generated by the Monoceros atlassian feature (rovodev).
58
+ # Runs every container start. Always re-runs auth login so that
59
+ # rotating the apiToken in the container yml propagates through on
60
+ # the next \`monoceros apply\` without needing to delete the
61
+ # previous credentials file by hand. acli's login is a single API
62
+ # call; the cost is negligible compared to the container build.
63
+ set -euo pipefail
64
+ echo "[atlassian/rovodev] performing non-interactive Rovo Dev login for ${EMAIL}"
65
+ echo '${APITOKEN}' | acli rovodev auth login --email '${EMAIL}' --token
66
+ echo "[atlassian/rovodev] auth login done — on first \\\`acli rovodev run\\\` you'll be asked for your Atlassian site once; the answer persists."
67
+ EOF
68
+ chmod 0755 "${HOOK}"
69
+ echo "[atlassian/rovodev] post-create login hook installed"
70
+ else
71
+ rm -f "${HOOK}"
72
+ echo "[atlassian/rovodev] no email/apiToken set — login is manual (\`acli rovodev auth login\` once in the container)"
73
+ fi
74
+ fi
75
+
76
+ # ─── Teamwork Graph (twg) ─────────────────────────────────────────
77
+ if [ "${TWG}" = "true" ]; then
78
+ echo "[atlassian/twg] installing via official install script"
79
+ TMP="$(mktemp)"
80
+ curl -fsSL -o "${TMP}" https://teamwork-graph.atlassian.com/cli/install
81
+ # The official install script:
82
+ # - Downloads the binary; we pin install dir to /usr/local/bin so
83
+ # both root (build time) and node (runtime) have it on PATH.
84
+ # - Runs a `twg consent --source direct-public-installer` step
85
+ # that prompts on stdin. We feed it `yes` via a heredoc; the
86
+ # extra blank lines are harmless padding in case a future
87
+ # version adds more prompts. (The recorded consent lands in
88
+ # /root/.config/twg/ which is not visible to the node user at
89
+ # runtime — we re-record it as node in the post-create hook
90
+ # below.)
91
+ # - With --skip-login / --skip-skills we keep the install
92
+ # non-interactive. Login + skills happen later as the node user
93
+ # so they persist into the bind-mounted home.
94
+ #
95
+ # Heredoc (not `yes ... |`) deliberately: a long-lived `yes` left
96
+ # writing into a closed pipe after the install script exits gets
97
+ # SIGPIPE'd, and our own `set -o pipefail` would then propagate
98
+ # that 141 as a feature-install failure even though the install
99
+ # actually succeeded.
100
+ bash "${TMP}" \
101
+ --install-dir /usr/local/bin \
102
+ --skip-login \
103
+ --skip-skills \
104
+ <<'TWG_INSTALL_INPUT'
105
+ yes
106
+ yes
107
+ yes
108
+ TWG_INSTALL_INPUT
109
+ rm -f "${TMP}"
110
+
111
+ # The install script's mktemp + chmod +x leaves twg-bin at 0700
112
+ # (only root can execute it). Re-chmod so the node user can run it.
113
+ if [ -f /usr/local/bin/twg-bin ]; then
114
+ chmod 0755 /usr/local/bin/twg-bin
115
+ fi
116
+ if [ -f /usr/local/bin/twg ]; then
117
+ chmod 0755 /usr/local/bin/twg
118
+ fi
119
+
120
+ twg --version >/dev/null 2>&1 || {
121
+ echo "[atlassian/twg] ERROR: install completed but \`twg\` is not on PATH" >&2
122
+ exit 1
123
+ }
124
+
125
+ HOOK="${POST_CREATE_DIR}/atlassian-twg.sh"
126
+ if [ -n "${INSTANCE}" ] && [ -n "${EMAIL}" ] && [ -n "${APITOKEN}" ]; then
127
+ cat >"${HOOK}" <<EOF
128
+ #!/usr/bin/env bash
129
+ # Auto-generated by the Monoceros atlassian feature (twg).
130
+ # Runs every container start. Always re-runs auth login so that
131
+ # rotating the apiToken / bitbucketToken in the container yml
132
+ # propagates through on the next \`monoceros apply\` without
133
+ # needing to delete the previous credentials file by hand. twg's
134
+ # login is a single API call; the cost is negligible compared to
135
+ # the container build.
136
+ set -euo pipefail
137
+ mkdir -p "\${HOME}/.config/twg"
138
+ echo "[atlassian/twg] configuring twg non-interactively for ${EMAIL} @ ${INSTANCE}"
139
+ # Notes on the non-interactive login dance:
140
+ # - We don't try to re-record consent here as the node user. twg's
141
+ # \`consent\` subcommand demands a TTY; the install-time consent
142
+ # (recorded as root during the feature build) appears to be
143
+ # enough for \`twg login\` itself.
144
+ # - \`twg login --force\` reads Atlassian creds from TWG_USER /
145
+ # TWG_SITE / TWG_TOKEN. If TWG_BBC_TOKEN is set, twg uses that
146
+ # directly and skips the Bitbucket prompt. If empty, twg prompts
147
+ # interactively — we feed two blank lines via heredoc so the
148
+ # "Enter = skip" branch fires and we don't hang. Future twg
149
+ # versions adding another optional prompt are also covered by
150
+ # the second blank line.
151
+ TWG_USER='${EMAIL}' \\
152
+ TWG_SITE='${INSTANCE}' \\
153
+ TWG_TOKEN='${APITOKEN}' \\
154
+ TWG_BBC_TOKEN='${BITBUCKETTOKEN}' \\
155
+ twg login --force <<'TWG_LOGIN_INPUT'
156
+
157
+
158
+ TWG_LOGIN_INPUT
159
+
160
+ # (Re-)install twg's agent skills. Canonical install lands in
161
+ # /home/node/.agents/skills/twg (persisted via the feature's
162
+ # persistentHomePaths); per-agent wrapper scripts go into agent-
163
+ # specific home dirs (.claude/skills/twg, .codex/skills/twg, …)
164
+ # and are regenerated on each apply when those tools are present.
165
+ echo "[atlassian/twg] (re-)installing twg skills"
166
+ twg skills install --global --yes
167
+ EOF
168
+ chmod 0755 "${HOOK}"
169
+ echo "[atlassian/twg] post-create login hook installed"
170
+ else
171
+ rm -f "${HOOK}"
172
+ echo "[atlassian/twg] missing instance/email/apiToken — login is manual (\`twg login\` once in the container)"
173
+ fi
174
+ fi
175
+
176
+ echo "[atlassian] done"
@@ -0,0 +1,32 @@
1
+ id: claude-code
2
+ name: claude
3
+ category: feature
4
+ displayName: Claude Code
5
+ description: "Anthropic's CLI coding assistant. OAuth/subscription login persists across container rebuilds."
6
+ documentationURL: https://docs.anthropic.com/en/docs/claude-code
7
+ options:
8
+ version:
9
+ type: string
10
+ default: latest
11
+ description: 'npm-style version spec (`latest`, `^0.4`, `0.4.2`).'
12
+ surface: silent
13
+ apiKey:
14
+ type: string
15
+ default: ''
16
+ description: '`sk-ant-…` for API auth; empty for OAuth login on first run.'
17
+ surface: env
18
+ permissionMode:
19
+ type: string
20
+ default: auto
21
+ proposals: [auto, ask, edits, bypass]
22
+ description: 'Default Claude permission mode in this container. `auto` = Auto Mode: no per-action prompts and no recurring warning (a background classifier vets actions) — the comfortable default for an isolated container. `ask` prompts as usual; `edits` auto-accepts file edits but prompts for other commands; `bypass` skips all prompts (its one-time warning is pre-accepted). Monoceros writes this to ~/.claude/settings.json on apply; override per-project or with a CLI flag.'
23
+ surface: yml
24
+ feature:
25
+ version: 1.2.0
26
+ persistentHomePaths: [.claude]
27
+ persistentHomeFiles:
28
+ - path: .claude.json
29
+ initialContent: "{}\n"
30
+ vscodeExtensions: [anthropic.claude-code]
31
+ briefing:
32
+ - text: 'Anthropic Claude Code CLI (`claude`) — interactive coding assistant. Authenticated via OAuth/subscription unless `apiKey` was set, in which case it runs in API-key mode.'
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env bash
2
+ # Monoceros devcontainer feature: claude-code.
3
+ #
4
+ # Installs the Anthropic Claude Code CLI globally via the npm registry.
5
+ # Login state lives at /home/node/.claude, which Monoceros bind-mounts
6
+ # from <container-dir>/home/.claude on the host so it survives apply
7
+ # rebuilds.
8
+ #
9
+ # If the optional `apiKey` option was passed in the container yml (or
10
+ # inherited from monoceros-config.yml defaults.features), this script
11
+ # writes a profile.d snippet that exports ANTHROPIC_API_KEY for every
12
+ # shell — Claude Code picks that up and skips the OAuth flow.
13
+
14
+ set -euo pipefail
15
+
16
+ VERSION="${VERSION:-latest}"
17
+ APIKEY="${APIKEY:-}"
18
+
19
+ echo "[claude-code] installing @anthropic-ai/claude-code@${VERSION} (as node)"
20
+
21
+ # Install as the non-root `node` user, NOT root (the feature install
22
+ # script itself runs as root). The base image's npm global prefix
23
+ # (/usr/local/share/npm-global) is owned by `node`, so installing as
24
+ # node leaves the Claude package files node-owned too. That is exactly
25
+ # what lets Claude's runtime self-updater write to them and keep itself
26
+ # current between Monoceros `upgrade`s. Installing as root drops
27
+ # root-owned files into that prefix that the non-root runtime user can
28
+ # never overwrite — the perpetual "Auto-update failed: no write
29
+ # permission to npm prefix" nag, frozen at the build-time version. See
30
+ # ADR 0018.
31
+ runuser -u node -- bash -lc \
32
+ "npm install -g --no-audit --no-fund '@anthropic-ai/claude-code@${VERSION}'"
33
+
34
+ runuser -u node -- bash -lc 'claude --version' >/dev/null 2>&1 || {
35
+ echo "[claude-code] ERROR: install completed but \`claude\` is not on PATH" >&2
36
+ exit 1
37
+ }
38
+
39
+ # When an API key is configured, drop a profile.d snippet so every
40
+ # login shell exports it. We deliberately don't use containerEnv: the
41
+ # value would land in /proc/<pid>/environ of every process; the
42
+ # profile.d route at least keeps it out of non-shell process env when
43
+ # the container starts services directly.
44
+ if [ -n "${APIKEY}" ]; then
45
+ cat >/etc/profile.d/claude-code-apikey.sh <<EOF
46
+ # Auto-generated by the Monoceros claude-code feature. Sets
47
+ # ANTHROPIC_API_KEY so Claude Code uses API auth instead of OAuth.
48
+ export ANTHROPIC_API_KEY='${APIKEY}'
49
+ EOF
50
+ chmod 0644 /etc/profile.d/claude-code-apikey.sh
51
+ echo "[claude-code] API key mode: ANTHROPIC_API_KEY wired via /etc/profile.d/"
52
+ else
53
+ echo "[claude-code] subscription/OAuth mode: run \`claude\` once interactively to log in"
54
+ fi
55
+
56
+ echo "[claude-code] done"
@@ -0,0 +1,18 @@
1
+ id: github-cli
2
+ name: github
3
+ category: feature
4
+ displayName: GitHub CLI
5
+ description: 'The official `gh` CLI. Login persists across container rebuilds.'
6
+ documentationURL: https://cli.github.com/
7
+ options:
8
+ apiToken:
9
+ type: string
10
+ default: ''
11
+ description: 'GitHub PAT (scopes: repo, read:org, gist); empty for `gh auth login` on first run.'
12
+ surface: env
13
+ feature:
14
+ version: 1.0.0
15
+ persistentHomePaths: [.config/gh]
16
+ vscodeExtensions: [github.vscode-pull-request-github]
17
+ briefing:
18
+ - text: 'GitHub CLI (`gh`) — repo, PR, issue, gist operations against github.com. Pre-authenticated; `gh auth status` reflects the active account.'
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env bash
2
+ # Monoceros devcontainer feature: github-cli.
3
+ #
4
+ # Installs the official GitHub CLI (`gh`) from cli.github.com's apt
5
+ # repository. When the `token` option is set, the value is exposed
6
+ # as GH_TOKEN via /etc/profile.d so every login shell sees an
7
+ # authenticated `gh`. Without a token, `gh` is installed but
8
+ # unauthenticated; the builder can run `gh auth login` once
9
+ # interactively and the resulting `~/.config/gh/` state is
10
+ # persisted via Monoceros' bind-mount.
11
+
12
+ set -euo pipefail
13
+
14
+ APITOKEN="${APITOKEN:-}"
15
+
16
+ echo "[github-cli] installing gh from cli.github.com apt repo"
17
+
18
+ # Per https://cli.github.com/manual/installation (Debian/Ubuntu path).
19
+ type -p curl >/dev/null || {
20
+ apt-get update
21
+ apt-get install -y curl
22
+ }
23
+
24
+ curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
25
+ | dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg
26
+ chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg
27
+
28
+ mkdir -p -m 755 /etc/apt/sources.list.d
29
+ ARCH="$(dpkg --print-architecture)"
30
+ echo "deb [arch=${ARCH} signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
31
+ > /etc/apt/sources.list.d/github-cli.list
32
+
33
+ apt-get update
34
+ apt-get install -y --no-install-recommends gh
35
+
36
+ gh --version >/dev/null 2>&1 || {
37
+ echo "[github-cli] ERROR: install completed but \`gh\` is not on PATH" >&2
38
+ exit 1
39
+ }
40
+
41
+ if [ -n "${APITOKEN}" ]; then
42
+ cat >/etc/profile.d/github-cli.sh <<EOF
43
+ # Auto-generated by the Monoceros github-cli feature. Exports
44
+ # GH_TOKEN so the GitHub CLI authenticates non-interactively.
45
+ export GH_TOKEN='${APITOKEN}'
46
+ EOF
47
+ chmod 0644 /etc/profile.d/github-cli.sh
48
+ echo "[github-cli] apiToken wired via /etc/profile.d/ → \`gh\` authenticated in login shells"
49
+ else
50
+ echo "[github-cli] no apiToken set — run \`gh auth login\` once in the container; auth state persists under ~/.config/gh"
51
+ fi
52
+
53
+ echo "[github-cli] done"
@@ -0,0 +1,8 @@
1
+ id: dotnet
2
+ category: language
3
+ displayName: .NET
4
+ description: 'The .NET SDK via the upstream devcontainer feature. Pin a version with `dotnet:<version>`.'
5
+ language:
6
+ feature: ghcr.io/devcontainers/features/dotnet:2
7
+ defaultVersion: latest
8
+ versions: [latest, lts, 10.0, 9.0, 8.0, 7.0, 6.0]
@@ -0,0 +1,8 @@
1
+ id: go
2
+ category: language
3
+ displayName: Go
4
+ description: 'The Go toolchain plus golangci-lint via the upstream devcontainer feature. Pin a version with `go:<version>`.'
5
+ language:
6
+ feature: ghcr.io/devcontainers/features/go:1
7
+ defaultVersion: latest
8
+ versions: [latest, 1.24, 1.23]
@@ -0,0 +1,17 @@
1
+ id: java
2
+ category: language
3
+ displayName: Java
4
+ description: 'A JDK plus Maven and Gradle by default (the upstream feature ships only the JDK), so a plain `languages: [java]` is build-ready. Pin a JDK major with `java:<version>`.'
5
+ language:
6
+ feature: ghcr.io/devcontainers/features/java:1
7
+ defaultVersion: latest
8
+ versions: [latest, 21, 17, 11, 8]
9
+ options:
10
+ installMaven:
11
+ type: boolean
12
+ default: true
13
+ surface: yml
14
+ installGradle:
15
+ type: boolean
16
+ default: true
17
+ surface: yml
@@ -0,0 +1,9 @@
1
+ id: node
2
+ category: language
3
+ displayName: Node.js
4
+ description: 'Node.js, built into the runtime image. A bare `node` installs nothing extra; pin a different major with `node:<version>`.'
5
+ language:
6
+ feature: ghcr.io/devcontainers/features/node:1
7
+ builtin: true
8
+ defaultVersion: 22
9
+ versions: [lts, latest, 22, 20]
@@ -0,0 +1,8 @@
1
+ id: python
2
+ category: language
3
+ displayName: Python
4
+ description: 'CPython plus pip and common dev tooling via the upstream devcontainer feature. Pin a version with `python:<version>`.'
5
+ language:
6
+ feature: ghcr.io/devcontainers/features/python:1
7
+ defaultVersion: latest
8
+ versions: [latest, 3.12, 3.11, 3.10, 3.9, 3.8]
@@ -0,0 +1,8 @@
1
+ id: rust
2
+ category: language
3
+ displayName: Rust
4
+ description: 'rustup plus the stable toolchain (rust-analyzer, rust-src, rustfmt, clippy) via the upstream feature. Pin a version with `rust:<version>`.'
5
+ language:
6
+ feature: ghcr.io/devcontainers/features/rust:1
7
+ defaultVersion: latest
8
+ versions: [latest, 1.87]
@@ -0,0 +1,40 @@
1
+ id: mysql
2
+ category: service
3
+ displayName: MySQL
4
+ description: 'MySQL with seeded dev credentials and a readiness healthcheck. Reachable in-container as host `mysql`.'
5
+ service:
6
+ image: mysql:8
7
+ defaultPort: 3306
8
+ dataMount: /var/lib/mysql
9
+ healthcheck:
10
+ test:
11
+ [
12
+ CMD,
13
+ mysqladmin,
14
+ ping,
15
+ -h,
16
+ 127.0.0.1,
17
+ -u,
18
+ root,
19
+ '-p${MYSQL_ROOT_PASSWORD}',
20
+ ]
21
+ interval: 10s
22
+ timeout: 5s
23
+ retries: 5
24
+ vscodeExtensions: [cweijan.vscode-database-client2]
25
+ connectionEnv:
26
+ MYSQL_HOST: ${host}
27
+ MYSQL_PORT: ${port}
28
+ MYSQL_USER: root
29
+ MYSQL_PASSWORD: ${MYSQL_ROOT_PASSWORD}
30
+ MYSQL_DATABASE: ${MYSQL_DATABASE}
31
+ DATABASE_URL: mysql://root:${MYSQL_ROOT_PASSWORD}@${host}:${port}/${MYSQL_DATABASE}
32
+ options:
33
+ MYSQL_ROOT_PASSWORD:
34
+ type: string
35
+ default: monoceros
36
+ surface: env
37
+ MYSQL_DATABASE:
38
+ type: string
39
+ default: monoceros
40
+ surface: env
@@ -0,0 +1,34 @@
1
+ id: postgres
2
+ category: service
3
+ displayName: PostgreSQL
4
+ description: 'PostgreSQL with seeded dev credentials and a readiness healthcheck. Reachable in-container as host `postgres`.'
5
+ service:
6
+ image: postgres:18
7
+ defaultPort: 5432
8
+ dataMount: /var/lib/postgresql
9
+ healthcheck:
10
+ test: [CMD, pg_isready, -U, '${POSTGRES_USER}', -d, '${POSTGRES_DB}']
11
+ interval: 10s
12
+ timeout: 5s
13
+ retries: 5
14
+ vscodeExtensions: [cweijan.vscode-database-client2]
15
+ connectionEnv:
16
+ PGHOST: ${host}
17
+ PGPORT: ${port}
18
+ PGUSER: ${POSTGRES_USER}
19
+ PGPASSWORD: ${POSTGRES_PASSWORD}
20
+ PGDATABASE: ${POSTGRES_DB}
21
+ DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${host}:${port}/${POSTGRES_DB}
22
+ options:
23
+ POSTGRES_USER:
24
+ type: string
25
+ default: monoceros
26
+ surface: env
27
+ POSTGRES_PASSWORD:
28
+ type: string
29
+ default: monoceros
30
+ surface: env
31
+ POSTGRES_DB:
32
+ type: string
33
+ default: monoceros
34
+ surface: env
@@ -0,0 +1,16 @@
1
+ id: redis
2
+ category: service
3
+ displayName: Redis
4
+ description: 'Redis on the default port with a readiness healthcheck. Reachable in-container as host `redis`.'
5
+ service:
6
+ image: redis:8
7
+ defaultPort: 6379
8
+ dataMount: /data
9
+ healthcheck:
10
+ test: [CMD, redis-cli, ping]
11
+ interval: 10s
12
+ timeout: 5s
13
+ retries: 5
14
+ vscodeExtensions: [cweijan.vscode-database-client2]
15
+ connectionEnv:
16
+ REDIS_URL: redis://${host}:${port}