Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| da40d57e07 | |||
| e99ec65cd9 | |||
| 38e481484e | |||
| 3e46bf5ec1 | |||
| c8a7bbcd6e | |||
| adb2ee4817 | |||
| 3637a0a6fc | |||
| f67066823b | |||
| 50560652cb | |||
| 0fc4ff503b | |||
| 04203e4efb | |||
| b710daac05 | |||
| 52a29da38d | |||
| ea71f71c74 | |||
| f6eceb4d94 | |||
| 84bf7841c3 | |||
| c823a30c2a | |||
| 27af9dc9c4 | |||
| 0944dcec1c | |||
| 60a2689658 | |||
| 53bc4b68a6 | |||
| d526a445fd | |||
| f56b3efb66 | |||
| a778d32b3b | |||
| b48fce97d5 | |||
| 47af7acc5e | |||
| da45415cfe | |||
| 897555b1dc | |||
| df1f4d9b50 | |||
| 2f5a8d65d5 | |||
| 0d8fe1ec64 | |||
| 00638d372c | |||
| 31ec139a8a | |||
| 71c6ca70cc | |||
| b9c30b8e4d | |||
| 794de6d0e5 | |||
| fbcd9c1f72 | |||
| 3be59e56eb | |||
| be9479ef75 | |||
| 065a6534e3 | |||
| d8d83ffa47 | |||
| 9535886945 | |||
| 44f30ec03f | |||
| 76391a8ed0 | |||
| ac1e5074b1 | |||
| 2a63f227f1 |
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"enabledPlugins": {
|
||||||
|
"voltagent-dev-exp@voltagent-subagents": true,
|
||||||
|
"voltagent-lang@voltagent-subagents": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,15 @@
|
|||||||
"enabledMcpjsonServers": [
|
"enabledMcpjsonServers": [
|
||||||
"kubernetes",
|
"kubernetes",
|
||||||
"flux",
|
"flux",
|
||||||
"playwright"
|
"playwright",
|
||||||
]
|
"github",
|
||||||
|
"pgtuner",
|
||||||
|
"fetch",
|
||||||
|
"sequentialthinking"
|
||||||
|
],
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(git add .claude/settings.local.json .claude/settings.json && git commit -m \"$\\(cat <<'EOF'\nchore: update Claude Code settings and enable voltagent plugins\n\nAdd fetch and sequentialthinking MCP servers to allowed list, and enable\nvoltagent dev-exp and lang subagent plugins.\n\nCo-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>\nEOF\n\\)\" && git status)"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,8 @@ Use this for all version releases:
|
|||||||
- ✅ Updates chart version
|
- ✅ Updates chart version
|
||||||
- ✅ Creates git tag
|
- ✅ Creates git tag
|
||||||
- ✅ Builds Docker image with all proper tags
|
- ✅ Builds Docker image with all proper tags
|
||||||
- ✅ Publishes Helm chart to GHCR
|
- ✅ Publishes Helm chart to GitHub Pages (`https://cpfarhood.github.io/devcontainer`)
|
||||||
- ✅ Creates GitHub Release with changelog
|
- ✅ Creates GitHub Release with changelog
|
||||||
- ✅ No more `[skip ci]` blocking builds!
|
|
||||||
|
|
||||||
### 2️⃣ For Quick Fixes → **Quick Fix Build**
|
### 2️⃣ For Quick Fixes → **Quick Fix Build**
|
||||||
Use this for emergency fixes without version changes:
|
Use this for emergency fixes without version changes:
|
||||||
@@ -30,8 +29,8 @@ Use this for emergency fixes without version changes:
|
|||||||
|
|
||||||
### 3️⃣ Automatic CI → **Build and Push**
|
### 3️⃣ Automatic CI → **Build and Push**
|
||||||
Runs automatically on:
|
Runs automatically on:
|
||||||
|
- Pushes to `main` (builds and pushes; skipped for release commits via `[skip ci]`)
|
||||||
- Pull requests (builds but doesn't push)
|
- Pull requests (builds but doesn't push)
|
||||||
- Tags starting with `v*` (builds and pushes)
|
|
||||||
- Manual trigger available
|
- Manual trigger available
|
||||||
|
|
||||||
## Workflow Files
|
## Workflow Files
|
||||||
@@ -90,5 +89,5 @@ gh run watch
|
|||||||
### After (Simple! 🎉)
|
### After (Simple! 🎉)
|
||||||
- **3 total workflows** (down from 6+)
|
- **3 total workflows** (down from 6+)
|
||||||
- **1 button** for complete releases
|
- **1 button** for complete releases
|
||||||
- **No more `[skip ci]`** blocking builds
|
- Release builds its own Docker image — `[skip ci]` on the version commit prevents duplicate CI builds
|
||||||
- **Clear separation** of concerns
|
- **Clear separation** of concerns
|
||||||
@@ -4,8 +4,6 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
@@ -46,9 +44,6 @@ jobs:
|
|||||||
tags: |
|
tags: |
|
||||||
type=ref,event=branch
|
type=ref,event=branch
|
||||||
type=ref,event=pr
|
type=ref,event=pr
|
||||||
type=semver,pattern={{version}}
|
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
|
||||||
type=semver,pattern={{major}}
|
|
||||||
type=sha,prefix=sha-
|
type=sha,prefix=sha-
|
||||||
type=raw,value=latest,enable={{is_default_branch}}
|
type=raw,value=latest,enable={{is_default_branch}}
|
||||||
|
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
version:
|
version:
|
||||||
description: 'Version to release (e.g., 0.1.25)'
|
description: 'Explicit version (e.g., 1.2.3). Leave blank to auto-increment.'
|
||||||
required: true
|
required: false
|
||||||
type: string
|
type: string
|
||||||
release_type:
|
release_type:
|
||||||
description: 'Release type'
|
description: 'Release type (used when version is blank)'
|
||||||
required: true
|
required: true
|
||||||
default: 'patch'
|
default: 'patch'
|
||||||
type: choice
|
type: choice
|
||||||
@@ -49,37 +49,34 @@ jobs:
|
|||||||
- name: Determine Version
|
- name: Determine Version
|
||||||
id: version
|
id: version
|
||||||
run: |
|
run: |
|
||||||
if [ "${{ github.event.inputs.version }}" != "" ]; then
|
INPUT_VERSION="${{ github.event.inputs.version }}"
|
||||||
VERSION="${{ github.event.inputs.version }}"
|
if [ -n "$INPUT_VERSION" ]; then
|
||||||
|
VERSION="$INPUT_VERSION"
|
||||||
else
|
else
|
||||||
# Auto-determine next version based on release type
|
# Auto-increment based on release_type
|
||||||
CURRENT=$(grep '^version:' chart/Chart.yaml | awk '{print $2}')
|
CURRENT=$(grep '^version:' chart/Chart.yaml | awk '{print $2}')
|
||||||
MAJOR=$(echo $CURRENT | cut -d. -f1)
|
# Strip any pre-release suffix (e.g., 2.0.0-dev -> 2.0.0)
|
||||||
MINOR=$(echo $CURRENT | cut -d. -f2)
|
CURRENT=$(echo "$CURRENT" | sed 's/-.*//')
|
||||||
PATCH=$(echo $CURRENT | cut -d. -f3)
|
MAJOR=$(echo "$CURRENT" | cut -d. -f1)
|
||||||
|
MINOR=$(echo "$CURRENT" | cut -d. -f2)
|
||||||
|
PATCH=$(echo "$CURRENT" | cut -d. -f3)
|
||||||
|
|
||||||
case "${{ github.event.inputs.release_type }}" in
|
case "${{ github.event.inputs.release_type }}" in
|
||||||
major)
|
major) VERSION="$((MAJOR + 1)).0.0" ;;
|
||||||
VERSION="$((MAJOR + 1)).0.0"
|
minor) VERSION="${MAJOR}.$((MINOR + 1)).0" ;;
|
||||||
;;
|
patch) VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))" ;;
|
||||||
minor)
|
|
||||||
VERSION="${MAJOR}.$((MINOR + 1)).0"
|
|
||||||
;;
|
|
||||||
patch)
|
|
||||||
VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))"
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||||
echo "tag=v${VERSION}" >> $GITHUB_OUTPUT
|
echo "tag=v${VERSION}" >> $GITHUB_OUTPUT
|
||||||
echo "🚀 Releasing version ${VERSION}"
|
echo "Releasing version ${VERSION}"
|
||||||
|
|
||||||
- name: Update Chart Version
|
- name: Update Chart Version
|
||||||
run: |
|
run: |
|
||||||
sed -i "s/^version: .*/version: ${{ steps.version.outputs.version }}/" chart/Chart.yaml
|
sed -i "s/^version: .*/version: ${{ steps.version.outputs.version }}/" chart/Chart.yaml
|
||||||
git add chart/Chart.yaml
|
git add chart/Chart.yaml
|
||||||
git commit -m "chore: release version ${{ steps.version.outputs.version }}"
|
git diff --quiet --staged || git commit -m "chore(release): ${{ steps.version.outputs.version }} [skip ci]"
|
||||||
|
|
||||||
- name: Create and Push Tag
|
- name: Create and Push Tag
|
||||||
run: |
|
run: |
|
||||||
@@ -107,27 +104,69 @@ jobs:
|
|||||||
cache-to: type=gha,mode=max
|
cache-to: type=gha,mode=max
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64
|
||||||
|
|
||||||
- name: Package Helm Chart
|
- name: Publish Helm Chart to GitHub Pages
|
||||||
run: |
|
run: |
|
||||||
helm registry login ghcr.io \
|
|
||||||
--username ${{ github.actor }} \
|
|
||||||
--password ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
helm package chart/
|
helm package chart/
|
||||||
helm push devcontainer-${{ steps.version.outputs.version }}.tgz oci://ghcr.io/cpfarhood/charts
|
CHART_TGZ="devcontainer-${{ steps.version.outputs.version }}.tgz"
|
||||||
|
|
||||||
- name: Generate Release Notes
|
# Set up gh-pages in a temporary directory
|
||||||
id: notes
|
PAGES_DIR=$(mktemp -d)
|
||||||
|
if git ls-remote --heads origin gh-pages | grep -q gh-pages; then
|
||||||
|
# gh-pages exists — shallow clone just that branch
|
||||||
|
git clone --single-branch --branch gh-pages \
|
||||||
|
"https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git" \
|
||||||
|
"$PAGES_DIR"
|
||||||
|
else
|
||||||
|
# First time — initialize gh-pages
|
||||||
|
git init "$PAGES_DIR"
|
||||||
|
git -C "$PAGES_DIR" checkout --orphan gh-pages
|
||||||
|
git -C "$PAGES_DIR" remote add origin \
|
||||||
|
"https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git"
|
||||||
|
cat > "$PAGES_DIR/index.html" <<'HTMLEOF'
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head><title>Dev Container Helm Chart Repository</title></head>
|
||||||
|
<body>
|
||||||
|
<h1>Dev Container Helm Chart Repository</h1>
|
||||||
|
<p>Add this repository to Helm:</p>
|
||||||
|
<pre>helm repo add devcontainer https://cpfarhood.github.io/devcontainer</pre>
|
||||||
|
<p>Install the chart:</p>
|
||||||
|
<pre>helm install mydev devcontainer/devcontainer --set name=mydev</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
HTMLEOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
git -C "$PAGES_DIR" config user.name "github-actions[bot]"
|
||||||
|
git -C "$PAGES_DIR" config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
|
# Copy chart package and rebuild index
|
||||||
|
cp "$CHART_TGZ" "$PAGES_DIR/"
|
||||||
|
if [ -f "$PAGES_DIR/index.yaml" ]; then
|
||||||
|
helm repo index "$PAGES_DIR" --url https://cpfarhood.github.io/devcontainer --merge "$PAGES_DIR/index.yaml"
|
||||||
|
else
|
||||||
|
helm repo index "$PAGES_DIR" --url https://cpfarhood.github.io/devcontainer
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Commit and push
|
||||||
|
git -C "$PAGES_DIR" add .
|
||||||
|
git -C "$PAGES_DIR" commit -m "Publish chart ${{ steps.version.outputs.version }}"
|
||||||
|
git -C "$PAGES_DIR" push origin gh-pages
|
||||||
|
|
||||||
|
- name: Create GitHub Release
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
# Get commits since last tag
|
# Build release notes
|
||||||
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
|
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
|
||||||
if [ -z "$PREV_TAG" ]; then
|
if [ -z "$PREV_TAG" ]; then
|
||||||
COMMITS=$(git log --pretty=format:"- %s (%h)" HEAD)
|
COMMITS=$(git log --pretty=format:"- %s (%h)" HEAD)
|
||||||
else
|
else
|
||||||
COMMITS=$(git log --pretty=format:"- %s (%h)" ${PREV_TAG}..HEAD)
|
COMMITS=$(git log --pretty=format:"- %s (%h)" "${PREV_TAG}..HEAD")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat << EOF > release-notes.md
|
cat > release-notes.md <<EOF
|
||||||
## 🚀 Release ${{ steps.version.outputs.version }}
|
## Release ${{ steps.version.outputs.version }}
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
${COMMITS}
|
${COMMITS}
|
||||||
@@ -139,21 +178,12 @@ jobs:
|
|||||||
|
|
||||||
### Helm Chart
|
### Helm Chart
|
||||||
\`\`\`bash
|
\`\`\`bash
|
||||||
helm install devcontainer oci://ghcr.io/cpfarhood/charts/devcontainer --version ${{ steps.version.outputs.version }}
|
helm repo add devcontainer https://cpfarhood.github.io/devcontainer
|
||||||
|
helm repo update
|
||||||
|
helm install mydev devcontainer/devcontainer --version ${{ steps.version.outputs.version }} --set name=mydev
|
||||||
\`\`\`
|
\`\`\`
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo "notes<<EOF" >> $GITHUB_OUTPUT
|
gh release create "${{ steps.version.outputs.tag }}" \
|
||||||
cat release-notes.md >> $GITHUB_OUTPUT
|
--title "Release ${{ steps.version.outputs.tag }}" \
|
||||||
echo "EOF" >> $GITHUB_OUTPUT
|
--notes-file release-notes.md
|
||||||
|
|
||||||
- name: Create GitHub Release
|
|
||||||
uses: actions/create-release@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
tag_name: ${{ steps.version.outputs.tag }}
|
|
||||||
release_name: Release ${{ steps.version.outputs.tag }}
|
|
||||||
body: ${{ steps.notes.outputs.notes }}
|
|
||||||
draft: false
|
|
||||||
prerelease: false
|
|
||||||
|
|||||||
@@ -1,86 +0,0 @@
|
|||||||
name: Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- 'v*'
|
|
||||||
|
|
||||||
env:
|
|
||||||
REGISTRY: ghcr.io
|
|
||||||
IMAGE_NAME: ${{ github.repository }}
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
packages: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
- name: Set up Helm
|
|
||||||
uses: azure/setup-helm@v4
|
|
||||||
|
|
||||||
- name: Extract version from tag
|
|
||||||
id: version
|
|
||||||
run: |
|
|
||||||
TAG=${GITHUB_REF#refs/tags/}
|
|
||||||
VERSION=${TAG#v}
|
|
||||||
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
|
||||||
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
|
||||||
echo "🚀 Creating release for ${TAG}"
|
|
||||||
|
|
||||||
- name: Package and Push Helm Chart
|
|
||||||
run: |
|
|
||||||
helm registry login ghcr.io \
|
|
||||||
--username ${{ github.actor }} \
|
|
||||||
--password ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
helm package chart/
|
|
||||||
helm push devcontainer-${{ steps.version.outputs.version }}.tgz oci://ghcr.io/cpfarhood/charts
|
|
||||||
|
|
||||||
- name: Generate Release Notes
|
|
||||||
id: notes
|
|
||||||
run: |
|
|
||||||
# Get commits since last tag
|
|
||||||
PREV_TAG=$(git describe --tags --abbrev=0 ${{ steps.version.outputs.tag }}^ 2>/dev/null || echo "")
|
|
||||||
if [ -z "$PREV_TAG" ]; then
|
|
||||||
COMMITS=$(git log --pretty=format:"- %s (%h)" ${{ steps.version.outputs.tag }})
|
|
||||||
else
|
|
||||||
COMMITS=$(git log --pretty=format:"- %s (%h)" ${PREV_TAG}..${{ steps.version.outputs.tag }})
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat << EOF > release-notes.md
|
|
||||||
## 🚀 Release ${{ steps.version.outputs.version }}
|
|
||||||
|
|
||||||
### Changes
|
|
||||||
${COMMITS}
|
|
||||||
|
|
||||||
### Docker Image
|
|
||||||
\`\`\`bash
|
|
||||||
docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.tag }}
|
|
||||||
\`\`\`
|
|
||||||
|
|
||||||
### Helm Chart
|
|
||||||
\`\`\`bash
|
|
||||||
helm install devcontainer oci://ghcr.io/cpfarhood/charts/devcontainer --version ${{ steps.version.outputs.version }}
|
|
||||||
\`\`\`
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "notes<<EOF" >> $GITHUB_OUTPUT
|
|
||||||
cat release-notes.md >> $GITHUB_OUTPUT
|
|
||||||
echo "EOF" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
- name: Create GitHub Release
|
|
||||||
uses: actions/create-release@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
tag_name: ${{ steps.version.outputs.tag }}
|
|
||||||
release_name: Release ${{ steps.version.outputs.tag }}
|
|
||||||
body: ${{ steps.notes.outputs.notes }}
|
|
||||||
draft: false
|
|
||||||
prerelease: false
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
},
|
},
|
||||||
"playwright": {
|
"playwright": {
|
||||||
"type": "sse",
|
"type": "sse",
|
||||||
"url": "http://playwright-mcp.playwright.svc.cluster.local:3000/sse"
|
"url": "http://localhost:8086/sse"
|
||||||
},
|
},
|
||||||
"pgtuner": {
|
"pgtuner": {
|
||||||
"type": "sse",
|
"type": "sse",
|
||||||
|
|||||||
@@ -4,11 +4,13 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
Antigravity is a Docker-based cloud development environment that provides:
|
The Dev Container is a Docker-based cloud development environment that provides:
|
||||||
- Web-based GUI IDE (VSCode/Antigravity) via VNC on port 5800
|
- Web-based GUI IDE (VSCode/Antigravity) via VNC on port 5800
|
||||||
- Happy Coder AI assistant integration
|
- Claude Code, Happy Coder, OpenCode, and Crush AI coding agents (terminal-based)
|
||||||
|
- Built-in web file manager for uploading/downloading files (optional, via `fileManager.enabled`)
|
||||||
- Automatic GitHub repository cloning on startup
|
- Automatic GitHub repository cloning on startup
|
||||||
- Kubernetes-native deployment with persistent home storage
|
- Kubernetes-native deployment with persistent home storage
|
||||||
|
- MCP (Model Context Protocol) sidecars for AI assistant integrations
|
||||||
|
|
||||||
The stack is primarily **Bash scripts + YAML** — there is no Node.js package, compiled language, or test framework.
|
The stack is primarily **Bash scripts + YAML** — there is no Node.js package, compiled language, or test framework.
|
||||||
|
|
||||||
@@ -19,7 +21,7 @@ The stack is primarily **Bash scripts + YAML** — there is no Node.js package,
|
|||||||
```bash
|
```bash
|
||||||
make build # Build Docker image
|
make build # Build Docker image
|
||||||
make build REGISTRY=ghcr.io/myuser IMAGE_TAG=v1.0 # Custom registry/tag
|
make build REGISTRY=ghcr.io/myuser IMAGE_TAG=v1.0 # Custom registry/tag
|
||||||
docker build -t ghcr.io/cpfarhood/antigravity:latest . # Direct build
|
docker build -t ghcr.io/cpfarhood/devcontainer:latest . # Direct build
|
||||||
```
|
```
|
||||||
|
|
||||||
### Running Locally
|
### Running Locally
|
||||||
@@ -60,7 +62,6 @@ Container start
|
|||||||
→ scripts/init-repo.sh
|
→ scripts/init-repo.sh
|
||||||
→ Configure git user & credentials
|
→ Configure git user & credentials
|
||||||
→ Clone GITHUB_REPO (if set)
|
→ Clone GITHUB_REPO (if set)
|
||||||
→ Start Happy Coder
|
|
||||||
→ Launch VSCode as user `user` in /workspace
|
→ Launch VSCode as user `user` in /workspace
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -68,8 +69,8 @@ Container start
|
|||||||
|
|
||||||
| File | Purpose |
|
| File | Purpose |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| `Dockerfile` | Image definition — installs Chrome, Node.js, VSCode, Happy Coder; creates non-root user (UID 1000) |
|
| `Dockerfile` | Image definition — installs Chrome, Node.js, VSCode, Helm, Claude Code, Happy Coder, OpenCode, Crush; creates non-root user (UID 1000) |
|
||||||
| `scripts/init-repo.sh` | Configures git credentials, clones GitHub repo, starts Happy Coder background service |
|
| `scripts/init-repo.sh` | Configures git credentials, clones GitHub repo |
|
||||||
| `scripts/startapp.sh` | Calls init-repo.sh then opens VSCode in the workspace |
|
| `scripts/startapp.sh` | Calls init-repo.sh then opens VSCode in the workspace |
|
||||||
| `chart/` | Helm chart for Kubernetes deployment |
|
| `chart/` | Helm chart for Kubernetes deployment |
|
||||||
| `chart/templates/deployment.yaml` | Deployment spec — main container + MCP sidecar containers |
|
| `chart/templates/deployment.yaml` | Deployment spec — main container + MCP sidecar containers |
|
||||||
@@ -77,7 +78,7 @@ Container start
|
|||||||
| `chart/templates/pvc.yaml` | PersistentVolumeClaim for user home |
|
| `chart/templates/pvc.yaml` | PersistentVolumeClaim for user home |
|
||||||
| `chart/templates/service.yaml` | ClusterIP Service (VNC + optional SSH) |
|
| `chart/templates/service.yaml` | ClusterIP Service (VNC + optional SSH) |
|
||||||
| `chart/values.yaml` | Default Helm values |
|
| `chart/values.yaml` | Default Helm values |
|
||||||
| `.mcp.json` | MCP server connection config (Kubernetes, Flux, GitHub, Home Assistant, Playwright) |
|
| `.mcp.json` | MCP server connection config (GitHub Copilot, Kubernetes, Flux, Fetch, Sequential Thinking, Playwright, pgtuner) |
|
||||||
| `Makefile` | Build/deploy automation |
|
| `Makefile` | Build/deploy automation |
|
||||||
|
|
||||||
### MCP Sidecars
|
### MCP Sidecars
|
||||||
@@ -88,15 +89,21 @@ MCP (Model Context Protocol) servers run as sidecar containers in the pod, enabl
|
|||||||
|---------|-------|---------|------|----------|---------|
|
|---------|-------|---------|------|----------|---------|
|
||||||
| `kubernetes-mcp` | `quay.io/containers/kubernetes_mcp_server` | v0.0.57 | 8080 | `http://localhost:8080/sse` | Enabled |
|
| `kubernetes-mcp` | `quay.io/containers/kubernetes_mcp_server` | v0.0.57 | 8080 | `http://localhost:8080/sse` | Enabled |
|
||||||
| `flux-mcp` | `ghcr.io/controlplaneio-fluxcd/flux-operator-mcp` | v0.41.1 | 8081 | `http://localhost:8081/sse` | Enabled |
|
| `flux-mcp` | `ghcr.io/controlplaneio-fluxcd/flux-operator-mcp` | v0.41.1 | 8081 | `http://localhost:8081/sse` | Enabled |
|
||||||
| `github-mcp` | `ghcr.io/modelcontextprotocol/servers/github` | latest | 8088 | `http://localhost:8088/sse` | Enabled |
|
| `fetch-mcp` | `mcp/fetch` | latest | 8082 | `http://localhost:8082/sse` | Enabled |
|
||||||
| `homeassistant-mcp` | `ghcr.io/homeassistant-ai/ha-mcp` | 6.7.1 | 8087 | `http://localhost:8087/sse` | Disabled |
|
| `sequentialthinking-mcp` | `mcp/sequentialthinking` | latest | 8083 | `http://localhost:8083/sse` | Enabled |
|
||||||
|
| `homeassistant-mcp` | `ghcr.io/homeassistant-ai/ha-mcp` | stable | 8087 | `http://localhost:8087/sse` | Disabled |
|
||||||
|
| `pgtuner-mcp` | `dog830228/pgtuner_mcp` | latest | 8085 | `http://localhost:8085/sse` | Disabled |
|
||||||
|
| `playwright-mcp` | `mcr.microsoft.com/playwright/mcp` | latest | 8086 | `http://localhost:8086/sse` | Enabled |
|
||||||
|
|
||||||
**Note:**
|
**Note:**
|
||||||
|
- GitHub MCP is accessed via the Copilot API (`https://api.githubcopilot.com/mcp/`), not as a sidecar
|
||||||
- Kubernetes and Flux sidecars require `clusterAccess` != `none` to be deployed (they need RBAC permissions)
|
- Kubernetes and Flux sidecars require `clusterAccess` != `none` to be deployed (they need RBAC permissions)
|
||||||
- Kubernetes and Flux sidecars inherit the pod's ServiceAccount RBAC permissions
|
- Kubernetes and Flux sidecars inherit the pod's ServiceAccount RBAC permissions
|
||||||
- GitHub sidecar uses `GITHUB_TOKEN` from the env secret (same token used for repo cloning)
|
- Fetch sidecar provides web content fetching capabilities and HTML to markdown conversion
|
||||||
|
- Sequential thinking sidecar enables structured thinking and problem-solving processes
|
||||||
- Home Assistant sidecar requires `HOMEASSISTANT_URL` and `HOMEASSISTANT_TOKEN` in the env secret
|
- Home Assistant sidecar requires `HOMEASSISTANT_URL` and `HOMEASSISTANT_TOKEN` in the env secret
|
||||||
- Playwright MCP remains an external service
|
- PostgreSQL tuner sidecar requires `DATABASE_URI` in the env secret (PostgreSQL connection string)
|
||||||
|
- Playwright sidecar provides browser automation and web testing capabilities
|
||||||
|
|
||||||
#### Enabling/Disabling MCP Servers
|
#### Enabling/Disabling MCP Servers
|
||||||
|
|
||||||
@@ -104,34 +111,56 @@ To control MCP sidecars, set the `enabled` flag in your values override:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# Disable all MCP sidecars
|
# Disable all MCP sidecars
|
||||||
mcpSidecars:
|
mcp:
|
||||||
kubernetes:
|
sidecars:
|
||||||
enabled: false
|
kubernetes:
|
||||||
flux:
|
enabled: false
|
||||||
enabled: false
|
flux:
|
||||||
github:
|
enabled: false
|
||||||
enabled: false
|
fetch:
|
||||||
homeassistant:
|
enabled: false
|
||||||
enabled: false
|
sequentialthinking:
|
||||||
|
enabled: false
|
||||||
|
homeassistant:
|
||||||
|
enabled: false
|
||||||
|
pgtuner:
|
||||||
|
enabled: false
|
||||||
|
playwright:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
# Or selectively enable/disable
|
# Or selectively enable/disable
|
||||||
mcpSidecars:
|
mcp:
|
||||||
kubernetes:
|
sidecars:
|
||||||
enabled: true # Keep Kubernetes MCP enabled
|
kubernetes:
|
||||||
flux:
|
enabled: true # Keep Kubernetes MCP enabled
|
||||||
enabled: false # Disable Flux MCP
|
flux:
|
||||||
github:
|
enabled: false # Disable Flux MCP
|
||||||
enabled: true # Keep GitHub MCP enabled (uses GITHUB_TOKEN)
|
fetch:
|
||||||
homeassistant:
|
enabled: true # Enable Fetch MCP for web content fetching
|
||||||
enabled: true # Enable Home Assistant MCP (requires secrets)
|
sequentialthinking:
|
||||||
|
enabled: true # Enable Sequential Thinking MCP for problem-solving
|
||||||
|
homeassistant:
|
||||||
|
enabled: true # Enable Home Assistant MCP (requires secrets)
|
||||||
|
pgtuner:
|
||||||
|
enabled: true # Enable PostgreSQL tuner MCP (requires DATABASE_URI)
|
||||||
|
playwright:
|
||||||
|
enabled: true # Enable Playwright MCP for browser automation
|
||||||
```
|
```
|
||||||
|
|
||||||
When deploying via Helm:
|
When deploying via Helm:
|
||||||
```bash
|
```bash
|
||||||
# Using --set flag
|
# Quick start (recommended)
|
||||||
helm install my-devcontainer ./chart --set mcpSidecars.kubernetes.enabled=false --set mcpSidecars.flux.enabled=false
|
cp chart/values-quickstart.yaml my-values.yaml
|
||||||
|
# Edit name and githubRepo in my-values.yaml
|
||||||
|
helm install my-devcontainer ./chart -f my-values.yaml
|
||||||
|
|
||||||
# Or with a values file
|
# Using --set flags
|
||||||
|
helm install my-devcontainer ./chart \
|
||||||
|
--set name=mydev \
|
||||||
|
--set githubRepo=https://github.com/user/repo \
|
||||||
|
--set mcp.sidecars.kubernetes.enabled=false
|
||||||
|
|
||||||
|
# Full customization
|
||||||
helm install my-devcontainer ./chart -f custom-values.yaml
|
helm install my-devcontainer ./chart -f custom-values.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -155,18 +184,22 @@ helm install my-devcontainer ./chart -f custom-values.yaml
|
|||||||
- `USER_ID` / `GROUP_ID` — Override UID/GID (default 1000)
|
- `USER_ID` / `GROUP_ID` — Override UID/GID (default 1000)
|
||||||
- `HAPPY_SERVER_URL` / `HAPPY_WEBAPP_URL` — Custom Happy Coder endpoints
|
- `HAPPY_SERVER_URL` / `HAPPY_WEBAPP_URL` — Custom Happy Coder endpoints
|
||||||
- `HAPPY_HOME_DIR` / `HAPPY_EXPERIMENTAL`
|
- `HAPPY_HOME_DIR` / `HAPPY_EXPERIMENTAL`
|
||||||
|
- `WEB_FILE_MANAGER` — Set to `1` to enable the built-in web file manager (controlled via `fileManager.enabled` in Helm values)
|
||||||
|
- `WEB_FILE_MANAGER_ALLOWED_PATHS` — Paths accessible by the file manager (default: `/workspace,/config`)
|
||||||
|
- `WEB_FILE_MANAGER_DENIED_PATHS` — Paths to deny access to (takes precedence over allowed)
|
||||||
|
|
||||||
### CI/CD
|
### CI/CD
|
||||||
|
|
||||||
- **`build-and-push.yaml`** — Builds and pushes to GHCR on every push to `main`, version tags (`v*`), and PRs. Tags: `latest` (main), semver, branch name, commit SHA.
|
- **`build-and-push.yaml`** — Builds and pushes to GHCR on every push to `main`, version tags (`v*`), and PRs. Tags: `latest` (main), semver, branch name, commit SHA.
|
||||||
- **`release.yaml`** — Creates a GitHub Release with docker pull instructions when a version tag is pushed.
|
- **`release-unified.yaml`** — Manual release workflow: bumps chart version, builds Docker image, publishes Helm chart to GitHub Pages (`https://cpfarhood.github.io/devcontainer`), and creates GitHub Release.
|
||||||
- **`dependabot.yml`** — Weekly updates for GitHub Actions and Docker base image.
|
- **`dependabot.yml`** — Weekly updates for GitHub Actions and Docker base image.
|
||||||
|
|
||||||
Image registry: `ghcr.io/cpfarhood/devcontainer`
|
Image registry: `ghcr.io/cpfarhood/devcontainer`
|
||||||
|
Helm repo: `https://cpfarhood.github.io/devcontainer`
|
||||||
|
|
||||||
## Kubernetes Notes
|
## Kubernetes Notes
|
||||||
|
|
||||||
- Deployed via Helm chart (`chart/`), published as OCI artifact to GHCR, reconciled by Flux
|
- Deployed via Helm chart (`chart/`), published to GitHub Pages Helm repo, reconciled by Flux
|
||||||
- Storage class is `ceph-filesystem` by default — change via `storage.className` in values
|
- Storage class is `ceph-filesystem` by default — change via `storage.className` in values
|
||||||
- Resource limits: 1–4 CPU, 2–8Gi memory
|
- Resource limits: 1–4 CPU, 2–8Gi memory
|
||||||
- Health checks (liveness/readiness probes) on port 5800
|
- Health checks (liveness/readiness probes) on port 5800
|
||||||
|
|||||||
+39
-3
@@ -1,7 +1,7 @@
|
|||||||
FROM jlesage/baseimage-gui:ubuntu-22.04-v4
|
FROM jlesage/baseimage-gui:ubuntu-22.04-v4
|
||||||
|
|
||||||
# Set environment variables
|
# Set environment variables
|
||||||
ENV APP_NAME="Antigravity Dev Container" \
|
ENV APP_NAME="Dev Container" \
|
||||||
KEEP_APP_RUNNING=1 \
|
KEEP_APP_RUNNING=1 \
|
||||||
DISPLAY_WIDTH=1920 \
|
DISPLAY_WIDTH=1920 \
|
||||||
DISPLAY_HEIGHT=1080 \
|
DISPLAY_HEIGHT=1080 \
|
||||||
@@ -64,6 +64,26 @@ RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && \
|
|||||||
# Install Happy Coder and Claude Code globally
|
# Install Happy Coder and Claude Code globally
|
||||||
RUN npm install -g happy-coder @anthropic-ai/claude-code
|
RUN npm install -g happy-coder @anthropic-ai/claude-code
|
||||||
|
|
||||||
|
# Install OpenCode AI coding agent
|
||||||
|
RUN OPENCODE_VERSION=$(curl -sL https://api.github.com/repos/opencode-ai/opencode/releases/latest | jq -r '.tag_name') && \
|
||||||
|
curl -fsSL "https://github.com/opencode-ai/opencode/releases/download/${OPENCODE_VERSION}/opencode-linux-x86_64.tar.gz" | \
|
||||||
|
tar -xz -C /usr/local/bin opencode && \
|
||||||
|
chmod +x /usr/local/bin/opencode
|
||||||
|
|
||||||
|
# Install Crush AI coding agent (OpenCode successor by Charm)
|
||||||
|
RUN CRUSH_VERSION=$(curl -sL https://api.github.com/repos/charmbracelet/crush/releases/latest | jq -r '.tag_name' | sed 's/^v//') && \
|
||||||
|
curl -fsSL "https://github.com/charmbracelet/crush/releases/download/v${CRUSH_VERSION}/crush_${CRUSH_VERSION}_Linux_x86_64.tar.gz" -o /tmp/crush.tar.gz && \
|
||||||
|
tar -xzf /tmp/crush.tar.gz -C /tmp && \
|
||||||
|
mv /tmp/crush_${CRUSH_VERSION}_Linux_x86_64/crush /usr/local/bin/crush && \
|
||||||
|
chmod +x /usr/local/bin/crush && \
|
||||||
|
rm -rf /tmp/crush*
|
||||||
|
|
||||||
|
# Install Helm CLI for Kubernetes chart management
|
||||||
|
ARG HELM_VERSION=3.17.1
|
||||||
|
RUN curl -fsSL "https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz" | \
|
||||||
|
tar -xz --strip-components=1 -C /usr/local/bin linux-amd64/helm && \
|
||||||
|
chmod +x /usr/local/bin/helm
|
||||||
|
|
||||||
# Install VSCode
|
# Install VSCode
|
||||||
RUN wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/packages.microsoft.gpg && \
|
RUN wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/packages.microsoft.gpg && \
|
||||||
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list && \
|
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list && \
|
||||||
@@ -77,10 +97,26 @@ RUN mkdir -p /etc/apt/keyrings && \
|
|||||||
gpg --dearmor --yes -o /etc/apt/keyrings/antigravity-repo-key.gpg && \
|
gpg --dearmor --yes -o /etc/apt/keyrings/antigravity-repo-key.gpg && \
|
||||||
echo "deb [signed-by=/etc/apt/keyrings/antigravity-repo-key.gpg] https://us-central1-apt.pkg.dev/projects/antigravity-auto-updater-dev/ antigravity-debian main" \
|
echo "deb [signed-by=/etc/apt/keyrings/antigravity-repo-key.gpg] https://us-central1-apt.pkg.dev/projects/antigravity-auto-updater-dev/ antigravity-debian main" \
|
||||||
> /etc/apt/sources.list.d/antigravity.list && \
|
> /etc/apt/sources.list.d/antigravity.list && \
|
||||||
|
# Clear package cache to force fresh repository data
|
||||||
|
rm -rf /var/lib/apt/lists/* && \
|
||||||
apt-get update && \
|
apt-get update && \
|
||||||
apt-get install -y antigravity && \
|
# Show available versions for debugging
|
||||||
|
apt-cache policy antigravity && \
|
||||||
|
# Install latest version
|
||||||
|
apt-get install -y --no-install-recommends antigravity && \
|
||||||
|
# Display installed version
|
||||||
|
dpkg -l | grep antigravity && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Pre-configure Antigravity to skip onboarding/setup on first run
|
||||||
|
RUN mkdir -p /etc/skel/.config/antigravity/User/globalStorage && \
|
||||||
|
echo '{"antigravityUnifiedStateSync.seenNuxOneTimeMigration": true, "antigravityUnifiedStateSync.browserOnboarding.completed": true, "antigravityUnifiedStateSync.hasOnboardingCompleted": true, "browserOnboarding.hasSeenWelcome": true, "antigravityUnifiedStateSync.browserPreferences.hasAddedLocalhostToAllowlist": true, "antigravityUnifiedStateSync.oauthToken.hasLegacyMigrated": true, "antigravityUnifiedStateSync.auth.tokenSyncEnabled": true, "antigravityUnifiedStateSync.auth.cloudSyncEnabled": true, "theme": "vs-dark"}' \
|
||||||
|
> /etc/skel/.config/antigravity/User/globalStorage/storage.json && \
|
||||||
|
echo '{"workbench.startupEditor": "none", "workbench.welcomePage.walkthroughs.openOnInstall": false, "workbench.tips.enabled": false, "extensions.ignoreRecommendations": true, "telemetry.telemetryLevel": "off", "update.mode": "none", "extensions.autoUpdate": false, "extensions.autoCheckUpdates": false, "workbench.enableExperiments": true, "workbench.settings.enableNaturalLanguageSearch": true, "antigravity.onboarding.completed": true, "antigravity.browserOnboarding.completed": true, "antigravity.setup.completed": true, "antigravity.ai.enabled": true, "antigravity.ai.autoComplete.enabled": true, "antigravity.ai.chat.enabled": true, "antigravity.ai.codeActions.enabled": true, "antigravity.ai.explainCode.enabled": true, "antigravity.ai.generateCode.enabled": true, "antigravity.ai.optimizeCode.enabled": true, "antigravity.ai.autoSuggest.enabled": true, "antigravity.telemetry.crashReporter": "on", "antigravity.ai.acceptTerms": true, "antigravity.auth.syncState": true, "antigravity.auth.enableTokenSync": true, "antigravity.ai.enableCloudSync": true, "antigravity.settings.sync": true}' \
|
||||||
|
> /etc/skel/.config/antigravity/User/settings.json && \
|
||||||
|
# Validate Antigravity installation
|
||||||
|
/usr/share/antigravity/antigravity --version || echo "WARNING: Antigravity version check failed"
|
||||||
|
|
||||||
# Install OpenSSH server (for SSH IDE mode)
|
# Install OpenSSH server (for SSH IDE mode)
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y openssh-server && \
|
apt-get install -y openssh-server && \
|
||||||
@@ -119,4 +155,4 @@ ENV HOME=/config/userdata \
|
|||||||
EXPOSE 5800
|
EXPOSE 5800
|
||||||
|
|
||||||
# Set app name for baseimage-gui
|
# Set app name for baseimage-gui
|
||||||
RUN set-cont-env APP_NAME "Antigravity"
|
RUN set-cont-env APP_NAME "Dev Container"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Variables
|
# Variables
|
||||||
REGISTRY ?= ghcr.io/cpfarhood
|
REGISTRY ?= ghcr.io/cpfarhood
|
||||||
IMAGE_NAME ?= antigravity
|
IMAGE_NAME ?= devcontainer
|
||||||
IMAGE_TAG ?= latest
|
IMAGE_TAG ?= latest
|
||||||
FULL_IMAGE = $(REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG)
|
FULL_IMAGE = $(REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG)
|
||||||
|
|
||||||
@@ -29,15 +29,15 @@ run:
|
|||||||
-e HAPPY_EXPERIMENTAL="true" \
|
-e HAPPY_EXPERIMENTAL="true" \
|
||||||
-v $(PWD)/home:/home \
|
-v $(PWD)/home:/home \
|
||||||
-v $(PWD)/workspace:/workspace \
|
-v $(PWD)/workspace:/workspace \
|
||||||
--name antigravity \
|
--name devcontainer \
|
||||||
$(FULL_IMAGE)
|
$(FULL_IMAGE)
|
||||||
@echo "Access at http://localhost:5800"
|
@echo "Access at http://localhost:5800"
|
||||||
|
|
||||||
# Stop the running container
|
# Stop the running container
|
||||||
stop:
|
stop:
|
||||||
@echo "Stopping antigravity container..."
|
@echo "Stopping devcontainer..."
|
||||||
docker stop antigravity || true
|
docker stop devcontainer || true
|
||||||
docker rm antigravity || true
|
docker rm devcontainer || true
|
||||||
|
|
||||||
# Clean up local volumes
|
# Clean up local volumes
|
||||||
clean: stop
|
clean: stop
|
||||||
@@ -81,7 +81,7 @@ helm-port-forward:
|
|||||||
|
|
||||||
# Show help
|
# Show help
|
||||||
help:
|
help:
|
||||||
@echo "Antigravity Dev Container Makefile"
|
@echo "Dev Container Makefile"
|
||||||
@echo ""
|
@echo ""
|
||||||
@echo "Usage: make [target]"
|
@echo "Usage: make [target]"
|
||||||
@echo ""
|
@echo ""
|
||||||
@@ -101,7 +101,7 @@ help:
|
|||||||
@echo ""
|
@echo ""
|
||||||
@echo "Variables:"
|
@echo "Variables:"
|
||||||
@echo " REGISTRY - Docker registry (default: ghcr.io/cpfarhood)"
|
@echo " REGISTRY - Docker registry (default: ghcr.io/cpfarhood)"
|
||||||
@echo " IMAGE_NAME - Image name (default: antigravity)"
|
@echo " IMAGE_NAME - Image name (default: devcontainer)"
|
||||||
@echo " IMAGE_TAG - Image tag (default: latest)"
|
@echo " IMAGE_TAG - Image tag (default: latest)"
|
||||||
@echo " RELEASE_NAME - Helm release name (default: mydev)"
|
@echo " RELEASE_NAME - Helm release name (default: mydev)"
|
||||||
@echo " NAMESPACE - Kubernetes namespace (default: default)"
|
@echo " NAMESPACE - Kubernetes namespace (default: default)"
|
||||||
|
|||||||
@@ -1,17 +1,52 @@
|
|||||||
# Antigravity Dev Container
|
# Dev Container
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
A containerized cloud development environment with web-based GUI access, featuring:
|
A containerized cloud development environment with web-based GUI access, featuring:
|
||||||
- **VSCode or Google Antigravity** via browser-based VNC (port 5800)
|
- **VSCode or Google Antigravity** via browser-based VNC (port 5800)
|
||||||
- **SSH access** option (OpenSSH on port 22, additive with any IDE)
|
- **SSH access** option (OpenSSH on port 22, additive with any IDE)
|
||||||
- **Happy Coder** AI assistant backed by Claude
|
- **Claude Code**, **Happy Coder**, **OpenCode**, and **Crush** AI coding agents (terminal-based)
|
||||||
|
- **Built-in web file manager** for uploading/downloading files via the VNC web interface
|
||||||
|
- **Helm CLI** included for Kubernetes chart development and deployment
|
||||||
- **Automatic GitHub repo cloning** on startup
|
- **Automatic GitHub repo cloning** on startup
|
||||||
- **Persistent home directory** via ReadWriteMany PVC
|
- **Persistent home directory** via ReadWriteMany PVC
|
||||||
- **Kubernetes-native** Helm chart deployment
|
- **Kubernetes-native** Helm chart deployment
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
|
### Option A: Install from Helm Repo (Recommended)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Add the Helm repository
|
||||||
|
helm repo add devcontainer https://cpfarhood.github.io/devcontainer
|
||||||
|
helm repo update
|
||||||
|
|
||||||
|
# Deploy with one command
|
||||||
|
helm install mydev devcontainer/devcontainer \
|
||||||
|
--set name=mydev \
|
||||||
|
--set githubRepo=https://github.com/youruser/yourrepo
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option B: Install from Source
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Clone and customize the quickstart template
|
||||||
|
cp chart/values-quickstart.yaml my-values.yaml
|
||||||
|
# Edit my-values.yaml to set your name and repository
|
||||||
|
|
||||||
|
helm install mydev ./chart -f my-values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option C: One-Command from Source
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install mydev ./chart \
|
||||||
|
--set name=mydev \
|
||||||
|
--set githubRepo=https://github.com/youruser/yourrepo
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option C: Full Configuration
|
||||||
|
|
||||||
### 1. Create a secret
|
### 1. Create a secret
|
||||||
|
|
||||||
The secret is picked up automatically via `envFrom`. Keys recognised:
|
The secret is picked up automatically via `envFrom`. Keys recognised:
|
||||||
@@ -22,8 +57,10 @@ The secret is picked up automatically via `envFrom`. Keys recognised:
|
|||||||
| `VNC_PASSWORD` | Password for the VNC web UI |
|
| `VNC_PASSWORD` | Password for the VNC web UI |
|
||||||
| `ANTHROPIC_API_KEY` | API key — alternative to browser-based Claude login |
|
| `ANTHROPIC_API_KEY` | API key — alternative to browser-based Claude login |
|
||||||
| `SSH_AUTHORIZED_KEYS` | Public key(s) for SSH access (required when `ssh: true`) |
|
| `SSH_AUTHORIZED_KEYS` | Public key(s) for SSH access (required when `ssh: true`) |
|
||||||
| `homeassistant-url` | Home Assistant URL (required when `mcpSidecars.homeassistant.enabled: true`) |
|
| `HOMEASSISTANT_URL` | Home Assistant URL (required when `mcp.sidecars.homeassistant.enabled: true`) |
|
||||||
| `homeassistant-token` | Home Assistant long-lived access token (required when `mcpSidecars.homeassistant.enabled: true`) |
|
| `HOMEASSISTANT_TOKEN` | Home Assistant long-lived access token (required when `mcp.sidecars.homeassistant.enabled: true`) |
|
||||||
|
| `DATABASE_URI` | PostgreSQL connection string (required when `mcp.sidecars.pgtuner.enabled: true`) |
|
||||||
|
| `PGTUNER_EXCLUDE_USERIDS` | Comma-separated PostgreSQL user OIDs to exclude from monitoring (optional) |
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
kubectl create secret generic devcontainer-mydev-secrets-env \
|
kubectl create secret generic devcontainer-mydev-secrets-env \
|
||||||
@@ -73,20 +110,33 @@ A Chrome browser window will open inside VNC for the Claude Max OAuth login. Cre
|
|||||||
|
|
||||||
## Helm Chart Reference
|
## Helm Chart Reference
|
||||||
|
|
||||||
|
The Helm chart uses a logical organization with these main sections:
|
||||||
|
- **Basic Configuration**: name, image, githubRepo
|
||||||
|
- **Access & Interface**: IDE, SSH, display, user settings
|
||||||
|
- **Infrastructure**: storage, resources, cluster access
|
||||||
|
- **Integrations**: Happy Coder, MCP sidecars
|
||||||
|
- **Smart Defaults**: auto-detection and profiles
|
||||||
|
|
||||||
|
📖 **Documentation**:
|
||||||
|
- [USAGE.md](chart/USAGE.md) - Comprehensive examples and scenarios
|
||||||
|
- [values-quickstart.yaml](chart/values-quickstart.yaml) - Minimal configuration
|
||||||
|
- [values.schema.json](chart/values.schema.json) - IDE validation support
|
||||||
|
|
||||||
### Core values
|
### Core values
|
||||||
|
|
||||||
| Value | Default | Description |
|
| Value | Default | Description |
|
||||||
|-------|---------|-------------|
|
|-------|---------|-------------|
|
||||||
| `name` | `""` | Instance name — used in all resource names (`devcontainer-{name}`) |
|
| `name` | `""` | Instance name — used in all resource names (`devcontainer-{name}`) |
|
||||||
| `githubRepo` | `""` | Repository to clone into `/workspace` on startup |
|
| `githubRepo` | `""` | Repository to clone into `/workspace` on startup |
|
||||||
| `ide` | `vscode` | IDE to launch — `vscode`, `antigravity`, or `none` (see below) |
|
| `ide.type` | `vscode` | IDE to launch — `vscode`, `antigravity`, or `none` (see below) |
|
||||||
| `ssh` | `false` | Also start an OpenSSH server on port 22 (additive, any `ide`) |
|
| `ssh.enabled` | `false` | Also start an OpenSSH server on port 22 (additive, any IDE) |
|
||||||
|
| `fileManager.enabled` | `false` | Enable the built-in web file manager for upload/download |
|
||||||
| `image.repository` | `ghcr.io/cpfarhood/devcontainer` | Container image |
|
| `image.repository` | `ghcr.io/cpfarhood/devcontainer` | Container image |
|
||||||
| `image.tag` | `latest` | Image tag |
|
| `image.tag` | `latest` | Image tag |
|
||||||
|
|
||||||
### IDE choice
|
### IDE choice
|
||||||
|
|
||||||
`ide` controls what GUI is launched in the VNC session:
|
`ide.type` controls what GUI is launched in the VNC session:
|
||||||
|
|
||||||
| Value | Port | Description |
|
| Value | Port | Description |
|
||||||
|-------|------|-------------|
|
|-------|------|-------------|
|
||||||
@@ -96,14 +146,14 @@ A Chrome browser window will open inside VNC for the Claude Max OAuth login. Cre
|
|||||||
|
|
||||||
### SSH access
|
### SSH access
|
||||||
|
|
||||||
`ssh: true` starts OpenSSH on port 22 **in addition to** the IDE. It works with any `ide` value:
|
`ssh.enabled: true` starts OpenSSH on port 22 **in addition to** the IDE. It works with any `ide.type` value:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# SSH-only (no VNC)
|
# SSH-only (no VNC)
|
||||||
helm install mydev ./chart --set name=mydev --set ide=none --set ssh=true
|
helm install mydev ./chart --set name=mydev --set ide.type=none --set ssh.enabled=true
|
||||||
|
|
||||||
# VSCode in VNC + SSH access at the same time
|
# VSCode in VNC + SSH access at the same time
|
||||||
helm install mydev ./chart --set name=mydev --set ssh=true
|
helm install mydev ./chart --set name=mydev --set ssh.enabled=true
|
||||||
```
|
```
|
||||||
|
|
||||||
Add your public key to the env secret:
|
Add your public key to the env secret:
|
||||||
@@ -121,14 +171,32 @@ kubectl port-forward deployment/devcontainer-mydev 2222:22
|
|||||||
ssh -p 2222 user@localhost
|
ssh -p 2222 user@localhost
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Web file manager
|
||||||
|
|
||||||
|
The base image includes a built-in web file manager for uploading and downloading files through the VNC web interface (port 5800). No additional sidecar is needed.
|
||||||
|
|
||||||
|
| Value | Default | Description |
|
||||||
|
|-------|---------|-------------|
|
||||||
|
| `fileManager.enabled` | `false` | Enable the web file manager |
|
||||||
|
| `fileManager.allowedPaths` | `/workspace,/config` | Paths accessible by the file manager (`AUTO`, `ALL`, or comma-separated) |
|
||||||
|
| `fileManager.deniedPaths` | `""` | Paths to deny (takes precedence over allowed) |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Enable the file manager
|
||||||
|
helm install mydev ./chart \
|
||||||
|
--set name=mydev \
|
||||||
|
--set githubRepo=https://github.com/youruser/yourrepo \
|
||||||
|
--set fileManager.enabled=true
|
||||||
|
```
|
||||||
|
|
||||||
### Happy Coder
|
### Happy Coder
|
||||||
|
|
||||||
| Value | Default | Description |
|
| Value | Default | Description |
|
||||||
|-------|---------|-------------|
|
|-------|---------|-------------|
|
||||||
| `happyServerUrl` | `https://happy.farh.net` | Happy Coder server endpoint |
|
| `happy.serverUrl` | `https://happy.farh.net` | Happy Coder server endpoint |
|
||||||
| `happyWebappUrl` | `https://happy-coder.farh.net` | Happy Coder webapp URL |
|
| `happy.webappUrl` | `https://happy-coder.farh.net` | Happy Coder webapp URL |
|
||||||
| `happyHomeDir` | `/home/user/.happy` | Happy runtime state directory (persists on the home PVC) |
|
| `happy.homeDir` | `/config/userdata/.happy` | Happy runtime state directory (persists on the home PVC) |
|
||||||
| `happyExperimental` | `true` | Enable experimental Happy features |
|
| `happy.experimental` | `true` | Enable experimental Happy features |
|
||||||
|
|
||||||
### Kubernetes cluster access
|
### Kubernetes cluster access
|
||||||
|
|
||||||
@@ -158,29 +226,35 @@ The devcontainer includes MCP (Model Context Protocol) servers as sidecar contai
|
|||||||
|
|
||||||
| Sidecar | Default | Purpose |
|
| Sidecar | Default | Purpose |
|
||||||
|---------|---------|---------|
|
|---------|---------|---------|
|
||||||
| `mcpSidecars.kubernetes.enabled` | `true` | Kubernetes API access via MCP |
|
| `mcp.sidecars.kubernetes.enabled` | `true` | Kubernetes API access via MCP |
|
||||||
| `mcpSidecars.flux.enabled` | `true` | Flux GitOps operations via MCP |
|
| `mcp.sidecars.flux.enabled` | `true` | Flux GitOps operations via MCP |
|
||||||
| `mcpSidecars.homeassistant.enabled` | `false` | Home Assistant smart home control via MCP |
|
| `mcp.sidecars.homeassistant.enabled` | `false` | Home Assistant smart home control via MCP |
|
||||||
|
| `mcp.sidecars.pgtuner.enabled` | `false` | PostgreSQL performance tuning and analysis via MCP |
|
||||||
|
| `mcp.sidecars.playwright.enabled` | `true` | Browser automation and web testing via MCP |
|
||||||
|
|
||||||
**Notes:**
|
**Notes:**
|
||||||
|
- GitHub MCP is accessed via the Copilot API (`https://api.githubcopilot.com/mcp/`), not as a sidecar
|
||||||
- Kubernetes and Flux sidecars require `clusterAccess` != `none` to be deployed (automatically disabled when no cluster access)
|
- Kubernetes and Flux sidecars require `clusterAccess` != `none` to be deployed (automatically disabled when no cluster access)
|
||||||
- Kubernetes and Flux sidecars inherit the pod's ServiceAccount RBAC permissions (controlled by `clusterAccess`)
|
- Kubernetes and Flux sidecars inherit the pod's ServiceAccount RBAC permissions (controlled by `clusterAccess`)
|
||||||
- Home Assistant sidecar requires additional configuration (see below)
|
- Home Assistant sidecar requires `HOMEASSISTANT_URL` and `HOMEASSISTANT_TOKEN` in the env secret
|
||||||
|
- PostgreSQL tuner sidecar requires `DATABASE_URI` in the env secret (PostgreSQL connection string)
|
||||||
|
- Playwright sidecar provides browser automation and web testing capabilities
|
||||||
|
|
||||||
**Disable MCP sidecars:**
|
**Disable MCP sidecars:**
|
||||||
```bash
|
```bash
|
||||||
# Disable both sidecars
|
# Disable multiple sidecars
|
||||||
helm install mydev ./chart \
|
helm install mydev ./chart \
|
||||||
--set name=mydev \
|
--set name=mydev \
|
||||||
--set githubRepo=https://github.com/youruser/yourrepo \
|
--set githubRepo=https://github.com/youruser/yourrepo \
|
||||||
--set mcpSidecars.kubernetes.enabled=false \
|
--set mcp.sidecars.kubernetes.enabled=false \
|
||||||
--set mcpSidecars.flux.enabled=false
|
--set mcp.sidecars.flux.enabled=false \
|
||||||
|
--set mcp.sidecars.playwright.enabled=false
|
||||||
|
|
||||||
# Or selectively disable
|
# Or selectively disable
|
||||||
helm install mydev ./chart \
|
helm install mydev ./chart \
|
||||||
--set name=mydev \
|
--set name=mydev \
|
||||||
--set githubRepo=https://github.com/youruser/yourrepo \
|
--set githubRepo=https://github.com/youruser/yourrepo \
|
||||||
--set mcpSidecars.flux.enabled=false # Disable only Flux MCP
|
--set mcp.sidecars.flux.enabled=false # Disable only Flux MCP
|
||||||
```
|
```
|
||||||
|
|
||||||
**Enable Home Assistant MCP:**
|
**Enable Home Assistant MCP:**
|
||||||
@@ -188,48 +262,75 @@ helm install mydev ./chart \
|
|||||||
# Create secret with Home Assistant credentials
|
# Create secret with Home Assistant credentials
|
||||||
kubectl create secret generic devcontainer-mydev-secrets-env \
|
kubectl create secret generic devcontainer-mydev-secrets-env \
|
||||||
--from-literal=GITHUB_TOKEN='ghp_...' \
|
--from-literal=GITHUB_TOKEN='ghp_...' \
|
||||||
--from-literal=homeassistant-url='http://homeassistant.local:8123' \
|
--from-literal=HOMEASSISTANT_URL='http://homeassistant.local:8123' \
|
||||||
--from-literal=homeassistant-token='your_long_lived_access_token'
|
--from-literal=HOMEASSISTANT_TOKEN='your_long_lived_access_token'
|
||||||
|
|
||||||
# Deploy with Home Assistant MCP enabled
|
# Deploy with Home Assistant MCP enabled
|
||||||
helm install mydev ./chart \
|
helm install mydev ./chart \
|
||||||
--set name=mydev \
|
--set name=mydev \
|
||||||
--set githubRepo=https://github.com/youruser/yourrepo \
|
--set githubRepo=https://github.com/youruser/yourrepo \
|
||||||
--set mcpSidecars.homeassistant.enabled=true
|
--set mcp.sidecars.homeassistant.enabled=true
|
||||||
|
```
|
||||||
|
|
||||||
|
**Enable PostgreSQL Tuner MCP:**
|
||||||
|
```bash
|
||||||
|
# Create secret with PostgreSQL connection string
|
||||||
|
kubectl create secret generic devcontainer-mydev-secrets-env \
|
||||||
|
--from-literal=GITHUB_TOKEN='ghp_...' \
|
||||||
|
--from-literal=DATABASE_URI='postgresql://user:password@postgres.example.com:5432/dbname'
|
||||||
|
|
||||||
|
# Deploy with PostgreSQL tuner MCP enabled
|
||||||
|
helm install mydev ./chart \
|
||||||
|
--set name=mydev \
|
||||||
|
--set githubRepo=https://github.com/youruser/yourrepo \
|
||||||
|
--set mcp.sidecars.pgtuner.enabled=true
|
||||||
```
|
```
|
||||||
|
|
||||||
**Custom MCP configuration:**
|
**Custom MCP configuration:**
|
||||||
```yaml
|
```yaml
|
||||||
# values.yaml override
|
# values.yaml override
|
||||||
mcpSidecars:
|
mcp:
|
||||||
kubernetes:
|
sidecars:
|
||||||
enabled: true
|
kubernetes:
|
||||||
image:
|
enabled: true
|
||||||
repository: quay.io/containers/kubernetes_mcp_server
|
image:
|
||||||
tag: latest
|
repository: quay.io/containers/kubernetes_mcp_server
|
||||||
port: 8080
|
tag: v0.0.57
|
||||||
resources:
|
port: 8080
|
||||||
requests:
|
resources:
|
||||||
memory: "64Mi"
|
requests:
|
||||||
cpu: "50m"
|
memory: "64Mi"
|
||||||
limits:
|
cpu: "50m"
|
||||||
memory: "256Mi"
|
limits:
|
||||||
cpu: "500m"
|
memory: "256Mi"
|
||||||
flux:
|
cpu: "500m"
|
||||||
enabled: false # Disabled in this example
|
flux:
|
||||||
homeassistant:
|
enabled: false # Disabled in this example
|
||||||
enabled: true
|
homeassistant:
|
||||||
image:
|
enabled: true
|
||||||
repository: ghcr.io/homeassistant-ai/ha-mcp
|
image:
|
||||||
tag: 6.7.1 # Override the pinned version if needed
|
repository: ghcr.io/homeassistant-ai/ha-mcp
|
||||||
port: 8087
|
tag: stable
|
||||||
resources:
|
port: 8087
|
||||||
requests:
|
pgtuner:
|
||||||
memory: "128Mi"
|
enabled: true
|
||||||
cpu: "100m"
|
image:
|
||||||
limits:
|
repository: dog830228/pgtuner_mcp
|
||||||
memory: "512Mi"
|
tag: latest
|
||||||
cpu: "500m"
|
port: 8085
|
||||||
|
playwright:
|
||||||
|
enabled: true
|
||||||
|
image:
|
||||||
|
repository: mcr.microsoft.com/playwright/mcp
|
||||||
|
tag: latest
|
||||||
|
port: 8086
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "128Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
limits:
|
||||||
|
memory: "512Mi"
|
||||||
|
cpu: "1000m"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Display and resources
|
### Display and resources
|
||||||
@@ -238,9 +339,9 @@ mcpSidecars:
|
|||||||
|-------|---------|-------------|
|
|-------|---------|-------------|
|
||||||
| `display.width` | `1920` | VNC width (px) |
|
| `display.width` | `1920` | VNC width (px) |
|
||||||
| `display.height` | `1080` | VNC height (px) |
|
| `display.height` | `1080` | VNC height (px) |
|
||||||
| `secureConnection` | `0` | Set to `1` if TLS is not terminated upstream |
|
| `display.secureConnection` | `0` | Set to `1` if TLS is not terminated upstream |
|
||||||
| `userId` | `1000` | UID for the app user |
|
| `user.id` | `1000` | UID for the app user |
|
||||||
| `groupId` | `1000` | GID for the app user |
|
| `user.groupId` | `1000` | GID for the app user |
|
||||||
| `storage.size` | `32Gi` | Home PVC size |
|
| `storage.size` | `32Gi` | Home PVC size |
|
||||||
| `storage.className` | `ceph-filesystem` | StorageClass (must be ReadWriteMany) |
|
| `storage.className` | `ceph-filesystem` | StorageClass (must be ReadWriteMany) |
|
||||||
| `shm.sizeLimit` | `2Gi` | `/dev/shm` size (memory-backed; used by Electron apps) |
|
| `shm.sizeLimit` | `2Gi` | `/dev/shm` size (memory-backed; used by Electron apps) |
|
||||||
@@ -263,8 +364,6 @@ Container start
|
|||||||
→ /startapp.sh (runs as app user, UID 1000)
|
→ /startapp.sh (runs as app user, UID 1000)
|
||||||
→ init-repo.sh
|
→ init-repo.sh
|
||||||
→ clone / pull GITHUB_REPO into /workspace/{repo}
|
→ clone / pull GITHUB_REPO into /workspace/{repo}
|
||||||
→ rm daemon.state.json.lock — clear stale Happy lock
|
|
||||||
→ happy daemon start — starts Happy Coder background daemon
|
|
||||||
→ IDE=vscode: code --new-window --wait /workspace/{repo}
|
→ IDE=vscode: code --new-window --wait /workspace/{repo}
|
||||||
IDE=antigravity: antigravity --no-sandbox --user-data-dir ~/.config/antigravity ... /workspace/{repo}
|
IDE=antigravity: antigravity --no-sandbox --user-data-dir ~/.config/antigravity ... /workspace/{repo}
|
||||||
IDE=none: sleep infinity
|
IDE=none: sleep infinity
|
||||||
@@ -275,26 +374,31 @@ Container start
|
|||||||
|
|
||||||
| Mount | Source | Persistence |
|
| Mount | Source | Persistence |
|
||||||
|-------|--------|-------------|
|
|-------|--------|-------------|
|
||||||
| `/home` | ReadWriteMany PVC (`userhome-{name}`) | Survives pod restarts — stores Claude credentials, dotfiles, git config |
|
| `/config` | ReadWriteMany PVC (`userhome-{name}`) | Survives pod restarts — stores Claude credentials, dotfiles, git config |
|
||||||
| `/workspace` | `emptyDir` | Ephemeral — repo is re-cloned on each pod start |
|
| `/workspace` | `emptyDir` | Ephemeral — repo is re-cloned on each pod start |
|
||||||
|
|
||||||
Happy Coder's runtime state (`HAPPY_HOME_DIR`) is kept in `/home/user/.happy` on the persistent home PVC, so auth credentials and settings survive pod restarts. A stale lock file (`daemon.state.json.lock`) is removed automatically on each startup.
|
Happy Coder's runtime state (`HAPPY_HOME_DIR`) is kept in `/config/userdata/.happy` on the persistent home PVC, so auth credentials and settings survive pod restarts when manually started.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Happy Coder daemon not starting
|
### Happy Coder (manual startup)
|
||||||
|
|
||||||
|
Happy daemon is not started automatically. Launch it manually when needed:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# Start Happy Coder daemon manually
|
||||||
|
happy daemon start
|
||||||
|
|
||||||
# Check daemon status
|
# Check daemon status
|
||||||
happy daemon status
|
happy daemon status
|
||||||
|
|
||||||
# Start manually (also clears any stale lock)
|
|
||||||
happy daemon start
|
|
||||||
|
|
||||||
# View daemon logs
|
# View daemon logs
|
||||||
ls ~/.happy/logs/
|
ls ~/.happy/logs/
|
||||||
|
|
||||||
|
# Stop daemon if needed
|
||||||
|
happy daemon stop
|
||||||
```
|
```
|
||||||
|
|
||||||
### Claude not authenticated
|
### Claude not authenticated
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
name: devcontainer
|
name: devcontainer
|
||||||
description: Antigravity Dev Container with Happy Coder AI assistant
|
description: Dev Container with AI coding agents and MCP sidecars
|
||||||
type: application
|
type: application
|
||||||
version: 0.2.4
|
version: 1.0.2
|
||||||
appVersion: "latest"
|
appVersion: "latest"
|
||||||
|
|||||||
+381
@@ -0,0 +1,381 @@
|
|||||||
|
# Dev Container Helm Chart Usage Guide
|
||||||
|
|
||||||
|
This guide provides common usage patterns and examples for the Dev Container Helm chart.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### 1. Minimal Installation (Recommended)
|
||||||
|
|
||||||
|
Use the quickstart values for the simplest setup:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy and customize quickstart values
|
||||||
|
cp values-quickstart.yaml my-values.yaml
|
||||||
|
|
||||||
|
# Edit my-values.yaml to set your name and repo:
|
||||||
|
# name: myproject
|
||||||
|
# githubRepo: https://github.com/youruser/yourproject
|
||||||
|
|
||||||
|
# Install
|
||||||
|
helm install myproject ./chart -f my-values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. One-Command Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install mydev ./chart \
|
||||||
|
--set name=mydev \
|
||||||
|
--set githubRepo=https://github.com/youruser/yourrepo
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Use Cases
|
||||||
|
|
||||||
|
### Development Environment
|
||||||
|
|
||||||
|
**Scenario**: Standard development with GitHub integration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: dev-environment
|
||||||
|
githubRepo: https://github.com/company/project
|
||||||
|
|
||||||
|
ide:
|
||||||
|
type: vscode
|
||||||
|
|
||||||
|
mcp:
|
||||||
|
sidecars:
|
||||||
|
kubernetes:
|
||||||
|
enabled: true
|
||||||
|
playwright:
|
||||||
|
enabled: true
|
||||||
|
flux:
|
||||||
|
enabled: false # Disable if not using Flux
|
||||||
|
```
|
||||||
|
|
||||||
|
### Team Workspace
|
||||||
|
|
||||||
|
**Scenario**: Shared development environment with more resources
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: team-workspace
|
||||||
|
githubRepo: https://github.com/company/project
|
||||||
|
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "4Gi"
|
||||||
|
cpu: "2000m"
|
||||||
|
limits:
|
||||||
|
memory: "16Gi"
|
||||||
|
cpu: "8000m"
|
||||||
|
|
||||||
|
storage:
|
||||||
|
size: 64Gi
|
||||||
|
|
||||||
|
ssh:
|
||||||
|
enabled: true # Enable SSH access for team
|
||||||
|
|
||||||
|
clusterAccess: readwrite # Full cluster access
|
||||||
|
```
|
||||||
|
|
||||||
|
### Kubernetes Admin Environment
|
||||||
|
|
||||||
|
**Scenario**: Platform engineering with full cluster access
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: k8s-admin
|
||||||
|
githubRepo: https://github.com/company/k8s-configs
|
||||||
|
|
||||||
|
clusterAccess: readwrite
|
||||||
|
|
||||||
|
mcp:
|
||||||
|
sidecars:
|
||||||
|
kubernetes:
|
||||||
|
enabled: true
|
||||||
|
flux:
|
||||||
|
enabled: true
|
||||||
|
pgtuner:
|
||||||
|
enabled: true # Database administration
|
||||||
|
playwright:
|
||||||
|
enabled: false # Save resources
|
||||||
|
```
|
||||||
|
|
||||||
|
### AI/ML Development
|
||||||
|
|
||||||
|
**Scenario**: AI development with browser automation
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: ai-playground
|
||||||
|
githubRepo: https://github.com/company/ai-project
|
||||||
|
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "8Gi" # More memory for ML workloads
|
||||||
|
cpu: "4000m"
|
||||||
|
limits:
|
||||||
|
memory: "32Gi"
|
||||||
|
cpu: "16000m"
|
||||||
|
|
||||||
|
storage:
|
||||||
|
size: 128Gi # Large datasets
|
||||||
|
|
||||||
|
mcp:
|
||||||
|
sidecars:
|
||||||
|
playwright:
|
||||||
|
enabled: true # Web scraping, testing
|
||||||
|
kubernetes:
|
||||||
|
enabled: false # Save resources
|
||||||
|
flux:
|
||||||
|
enabled: false
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lightweight Environment
|
||||||
|
|
||||||
|
**Scenario**: Resource-constrained setup
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
name: lightweight
|
||||||
|
githubRepo: https://github.com/youruser/small-project
|
||||||
|
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "1Gi"
|
||||||
|
cpu: "500m"
|
||||||
|
limits:
|
||||||
|
memory: "2Gi"
|
||||||
|
cpu: "1000m"
|
||||||
|
|
||||||
|
storage:
|
||||||
|
size: 8Gi
|
||||||
|
|
||||||
|
mcp:
|
||||||
|
sidecars:
|
||||||
|
kubernetes:
|
||||||
|
enabled: false
|
||||||
|
flux:
|
||||||
|
enabled: false
|
||||||
|
playwright:
|
||||||
|
enabled: false
|
||||||
|
# Only keep essential sidecars enabled
|
||||||
|
```
|
||||||
|
|
||||||
|
## Secret Configuration
|
||||||
|
|
||||||
|
### Basic Secrets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# GitHub access only
|
||||||
|
kubectl create secret generic devcontainer-mydev-secrets-env \
|
||||||
|
--from-literal=GITHUB_TOKEN='ghp_...' \
|
||||||
|
--from-literal=VNC_PASSWORD='changeme'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Extended Secrets
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Full feature set
|
||||||
|
kubectl create secret generic devcontainer-mydev-secrets-env \
|
||||||
|
--from-literal=GITHUB_TOKEN='ghp_...' \
|
||||||
|
--from-literal=VNC_PASSWORD='changeme' \
|
||||||
|
--from-literal=SSH_AUTHORIZED_KEYS='ssh-ed25519 AAAA...' \
|
||||||
|
--from-literal=HOMEASSISTANT_URL='http://homeassistant.local:8123' \
|
||||||
|
--from-literal=HOMEASSISTANT_TOKEN='eyJ...' \
|
||||||
|
--from-literal=DATABASE_URI='postgresql://user:pass@postgres:5432/db'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Storage Configuration
|
||||||
|
|
||||||
|
### Different Storage Classes
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# For different Kubernetes distributions
|
||||||
|
storage:
|
||||||
|
className: "" # Auto-detect (recommended)
|
||||||
|
# className: longhorn # Longhorn
|
||||||
|
# className: nfs-client # NFS
|
||||||
|
# className: fast-ssd # Custom fast storage
|
||||||
|
```
|
||||||
|
|
||||||
|
### Storage Sizes by Use Case
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Small projects
|
||||||
|
storage:
|
||||||
|
size: 8Gi
|
||||||
|
|
||||||
|
# Standard development
|
||||||
|
storage:
|
||||||
|
size: 32Gi
|
||||||
|
|
||||||
|
# Large projects / datasets
|
||||||
|
storage:
|
||||||
|
size: 128Gi
|
||||||
|
|
||||||
|
# Team environments
|
||||||
|
storage:
|
||||||
|
size: 256Gi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Access Patterns
|
||||||
|
|
||||||
|
### VNC Only (Default)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ide:
|
||||||
|
type: vscode
|
||||||
|
|
||||||
|
# Access via: kubectl port-forward deployment/devcontainer-mydev 5800:5800
|
||||||
|
```
|
||||||
|
|
||||||
|
### SSH Only
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ide:
|
||||||
|
type: none
|
||||||
|
|
||||||
|
ssh:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# Access via: kubectl port-forward deployment/devcontainer-mydev 2222:22
|
||||||
|
# ssh -p 2222 user@localhost
|
||||||
|
```
|
||||||
|
|
||||||
|
### Both VNC and SSH
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
ide:
|
||||||
|
type: vscode
|
||||||
|
|
||||||
|
ssh:
|
||||||
|
enabled: true
|
||||||
|
|
||||||
|
# VNC: kubectl port-forward deployment/devcontainer-mydev 5800:5800
|
||||||
|
# SSH: kubectl port-forward deployment/devcontainer-mydev 2222:22
|
||||||
|
```
|
||||||
|
|
||||||
|
## Resource Profiles
|
||||||
|
|
||||||
|
### Small (1-2 developers)
|
||||||
|
```yaml
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "1Gi"
|
||||||
|
cpu: "500m"
|
||||||
|
limits:
|
||||||
|
memory: "4Gi"
|
||||||
|
cpu: "2000m"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Medium (standard development)
|
||||||
|
```yaml
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "2Gi"
|
||||||
|
cpu: "1000m"
|
||||||
|
limits:
|
||||||
|
memory: "8Gi"
|
||||||
|
cpu: "4000m"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Large (intensive workloads)
|
||||||
|
```yaml
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "4Gi"
|
||||||
|
cpu: "2000m"
|
||||||
|
limits:
|
||||||
|
memory: "16Gi"
|
||||||
|
cpu: "8000m"
|
||||||
|
```
|
||||||
|
|
||||||
|
### XLarge (AI/ML, data processing)
|
||||||
|
```yaml
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "8Gi"
|
||||||
|
cpu: "4000m"
|
||||||
|
limits:
|
||||||
|
memory: "32Gi"
|
||||||
|
cpu: "16000m"
|
||||||
|
```
|
||||||
|
|
||||||
|
## MCP Sidecar Combinations
|
||||||
|
|
||||||
|
### Minimal (basic development)
|
||||||
|
```yaml
|
||||||
|
mcp:
|
||||||
|
sidecars:
|
||||||
|
kubernetes:
|
||||||
|
enabled: false
|
||||||
|
flux:
|
||||||
|
enabled: false
|
||||||
|
playwright:
|
||||||
|
enabled: true # Keep for web testing
|
||||||
|
```
|
||||||
|
|
||||||
|
### Standard (full-stack development)
|
||||||
|
```yaml
|
||||||
|
mcp:
|
||||||
|
sidecars:
|
||||||
|
kubernetes:
|
||||||
|
enabled: true
|
||||||
|
flux:
|
||||||
|
enabled: false
|
||||||
|
playwright:
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### DevOps/Platform (infrastructure work)
|
||||||
|
```yaml
|
||||||
|
mcp:
|
||||||
|
sidecars:
|
||||||
|
kubernetes:
|
||||||
|
enabled: true
|
||||||
|
flux:
|
||||||
|
enabled: true
|
||||||
|
pgtuner:
|
||||||
|
enabled: true
|
||||||
|
playwright:
|
||||||
|
enabled: false
|
||||||
|
```
|
||||||
|
|
||||||
|
### All Features
|
||||||
|
```yaml
|
||||||
|
mcp:
|
||||||
|
sidecars:
|
||||||
|
kubernetes:
|
||||||
|
enabled: true
|
||||||
|
flux:
|
||||||
|
enabled: true
|
||||||
|
homeassistant:
|
||||||
|
enabled: true
|
||||||
|
pgtuner:
|
||||||
|
enabled: true
|
||||||
|
playwright:
|
||||||
|
enabled: true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Values Validation
|
||||||
|
|
||||||
|
Your IDE should automatically validate values.yaml against the schema. If not:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Manual validation (if you have a JSON schema validator)
|
||||||
|
helm template ./chart -f values.yaml > /dev/null
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
**Resource Limits**: Start with smaller resource requests and increase as needed.
|
||||||
|
|
||||||
|
**Storage Class**: Use `className: ""` for auto-detection.
|
||||||
|
|
||||||
|
**GitHub Access**: Ensure GITHUB_TOKEN has `repo` scope.
|
||||||
|
|
||||||
|
**MCP Sidecars**: Disable unused sidecars to save resources.
|
||||||
|
|
||||||
|
### Getting Help
|
||||||
|
|
||||||
|
1. Check the main [README.md](../README.md) for detailed documentation
|
||||||
|
2. Review [values.yaml](values.yaml) for all available options
|
||||||
|
3. Use [values-quickstart.yaml](values-quickstart.yaml) as a starting point
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
Dev Container "{{ .Values.name }}" has been deployed.
|
||||||
|
|
||||||
|
{{- if ne (.Values.ide.type | default "vscode") "none" }}
|
||||||
|
|
||||||
|
Access the IDE:
|
||||||
|
kubectl port-forward deployment/{{ include "devcontainer.fullname" . }} 5800:5800 -n {{ .Release.Namespace }}
|
||||||
|
Then open: http://localhost:5800
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- if .Values.ssh.enabled }}
|
||||||
|
|
||||||
|
SSH access:
|
||||||
|
kubectl port-forward deployment/{{ include "devcontainer.fullname" . }} 2222:22 -n {{ .Release.Namespace }}
|
||||||
|
Then: ssh -p 2222 user@localhost
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
Useful commands:
|
||||||
|
Logs: kubectl logs -f deployment/{{ include "devcontainer.fullname" . }} -n {{ .Release.Namespace }}
|
||||||
|
Shell: kubectl exec -it deployment/{{ include "devcontainer.fullname" . }} -n {{ .Release.Namespace }} -- bash
|
||||||
|
|
||||||
|
{{- if not (lookup "v1" "Secret" .Release.Namespace (include "devcontainer.envSecretName" .)) }}
|
||||||
|
|
||||||
|
Optional: Create a secret for GITHUB_TOKEN, VNC_PASSWORD, etc:
|
||||||
|
kubectl create secret generic {{ include "devcontainer.envSecretName" . }} \
|
||||||
|
--from-literal=GITHUB_TOKEN=ghp_xxx \
|
||||||
|
--from-literal=VNC_PASSWORD=changeme \
|
||||||
|
-n {{ .Release.Namespace }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
Note: The PVC "{{ include "devcontainer.pvcName" . }}" is protected from deletion on helm uninstall.
|
||||||
|
To remove it manually: kubectl delete pvc {{ include "devcontainer.pvcName" . }} -n {{ .Release.Namespace }}
|
||||||
@@ -1,28 +1,111 @@
|
|||||||
{{/*
|
{{/*
|
||||||
Resource name prefix: devcontainer-{name}
|
Resource name prefix: devcontainer-{name}
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "antigravity.fullname" -}}
|
{{- define "devcontainer.fullname" -}}
|
||||||
|
{{- if not .Values.name }}
|
||||||
|
{{- fail "values.name is required and must not be empty" }}
|
||||||
|
{{- end }}
|
||||||
{{- printf "devcontainer-%s" .Values.name }}
|
{{- printf "devcontainer-%s" .Values.name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
PVC name: userhome-{name}
|
PVC name: userhome-{name}
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "antigravity.pvcName" -}}
|
{{- define "devcontainer.pvcName" -}}
|
||||||
{{- printf "userhome-%s" .Values.name }}
|
{{- printf "userhome-%s" .Values.name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
Secret name for env vars, default to devcontainer-{name}-secrets-env
|
Secret name for env vars, default to devcontainer-{name}-secrets-env
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "antigravity.envSecretName" -}}
|
{{- define "devcontainer.envSecretName" -}}
|
||||||
{{- .Values.envSecretName | default (printf "devcontainer-%s-secrets-env" .Values.name) }}
|
{{- .Values.envSecretName | default (printf "devcontainer-%s-secrets-env" .Values.name) }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
Common labels
|
Common labels
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "antigravity.labels" -}}
|
{{- define "devcontainer.labels" -}}
|
||||||
|
app: devcontainer
|
||||||
|
instance: {{ .Values.name }}
|
||||||
|
app.kubernetes.io/name: devcontainer
|
||||||
|
app.kubernetes.io/instance: {{ .Values.name }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Selector labels — keep narrow since changing these requires recreating the Deployment
|
||||||
|
*/}}
|
||||||
|
{{- define "devcontainer.selectorLabels" -}}
|
||||||
app: devcontainer
|
app: devcontainer
|
||||||
instance: {{ .Values.name }}
|
instance: {{ .Values.name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Smart resource sizing based on enabled features
|
||||||
|
*/}}
|
||||||
|
{{- define "devcontainer.smartResources" -}}
|
||||||
|
{{- $baseMemory := "2Gi" }}
|
||||||
|
{{- $baseCpu := "1000m" }}
|
||||||
|
{{- $limitMemory := "8Gi" }}
|
||||||
|
{{- $limitCpu := "4000m" }}
|
||||||
|
|
||||||
|
{{/* Adjust for enabled MCP sidecars */}}
|
||||||
|
{{- if .Values.mcp.sidecars.playwright.enabled }}
|
||||||
|
{{- $baseMemory = "3Gi" }}
|
||||||
|
{{- $limitMemory = "12Gi" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/* Adjust for IDE type */}}
|
||||||
|
{{- if eq .Values.ide.type "antigravity" }}
|
||||||
|
{{- $baseMemory = "4Gi" }}
|
||||||
|
{{- $limitMemory = "16Gi" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
requests:
|
||||||
|
memory: {{ .Values.resources.requests.memory | default $baseMemory | quote }}
|
||||||
|
cpu: {{ .Values.resources.requests.cpu | default $baseCpu | quote }}
|
||||||
|
limits:
|
||||||
|
memory: {{ .Values.resources.limits.memory | default $limitMemory | quote }}
|
||||||
|
cpu: {{ .Values.resources.limits.cpu | default $limitCpu | quote }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Auto-detect environment type and set smart defaults
|
||||||
|
*/}}
|
||||||
|
{{- define "devcontainer.smartDefaults" -}}
|
||||||
|
{{- $isDev := or (contains "dev" .Values.name) (contains "test" .Values.name) (contains "local" .Values.name) }}
|
||||||
|
{{- $isProd := or (contains "prod" .Values.name) (contains "production" .Values.name) }}
|
||||||
|
{{- $isTeam := or (contains "team" .Values.name) (contains "shared" .Values.name) }}
|
||||||
|
|
||||||
|
{{/* Development environment - enable more sidecars, smaller resources */}}
|
||||||
|
{{- if $isDev }}
|
||||||
|
development: true
|
||||||
|
{{/* Production environment - conservative defaults, fewer sidecars */}}
|
||||||
|
{{- else if $isProd }}
|
||||||
|
production: true
|
||||||
|
{{/* Team environment - enable SSH, more resources */}}
|
||||||
|
{{- else if $isTeam }}
|
||||||
|
team: true
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Smart MCP sidecar selection based on cluster access
|
||||||
|
*/}}
|
||||||
|
{{- define "devcontainer.mcpDefaults" -}}
|
||||||
|
{{- if eq .Values.clusterAccess "none" }}
|
||||||
|
{{/* No cluster access - disable k8s/flux sidecars */}}
|
||||||
|
kubernetes:
|
||||||
|
enabled: false
|
||||||
|
flux:
|
||||||
|
enabled: false
|
||||||
|
{{- else }}
|
||||||
|
{{/* Has cluster access - enable k8s sidecars */}}
|
||||||
|
kubernetes:
|
||||||
|
enabled: true
|
||||||
|
flux:
|
||||||
|
enabled: {{ ne .Values.clusterAccess "readonly" }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
|||||||
+104
-92
@@ -1,29 +1,29 @@
|
|||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "antigravity.fullname" . }}
|
name: {{ include "devcontainer.fullname" . }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "antigravity.labels" . | nindent 4 }}
|
{{- include "devcontainer.labels" . | nindent 4 }}
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
{{- include "antigravity.labels" . | nindent 6 }}
|
{{- include "devcontainer.selectorLabels" . | nindent 6 }}
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
{{- include "antigravity.labels" . | nindent 8 }}
|
{{- include "devcontainer.labels" . | nindent 8 }}
|
||||||
spec:
|
spec:
|
||||||
{{- if ne (.Values.clusterAccess | default "none") "none" }}
|
{{- if ne (.Values.clusterAccess | default "none") "none" }}
|
||||||
serviceAccountName: {{ include "antigravity.fullname" . }}
|
serviceAccountName: {{ include "devcontainer.fullname" . }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
securityContext:
|
securityContext:
|
||||||
fsGroup: 1000
|
fsGroup: 1000
|
||||||
fsGroupChangePolicy: "OnRootMismatch"
|
fsGroupChangePolicy: "OnRootMismatch"
|
||||||
{{- if and .Values.ide (eq .Values.ide "antigravity") }}
|
{{- if and .Values.ide.type (eq .Values.ide.type "antigravity") }}
|
||||||
initContainers:
|
initContainers:
|
||||||
- name: setup-userdata
|
- name: setup-userdata
|
||||||
image: busybox:latest
|
image: busybox:1.37
|
||||||
command: ['sh', '-c']
|
command: ['sh', '-c']
|
||||||
args:
|
args:
|
||||||
- |
|
- |
|
||||||
@@ -44,44 +44,54 @@ spec:
|
|||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
ports:
|
ports:
|
||||||
{{- if ne (.Values.ide | default "vscode") "none" }}
|
{{- if ne (.Values.ide.type | default "vscode") "none" }}
|
||||||
- containerPort: 5800
|
- containerPort: 5800
|
||||||
name: vnc-web
|
name: vnc-web
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.ssh }}
|
{{- if .Values.ssh.enabled }}
|
||||||
- containerPort: 22
|
- containerPort: 22
|
||||||
name: ssh
|
name: ssh
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
{{- end }}
|
{{- end }}
|
||||||
env:
|
env:
|
||||||
- name: IDE
|
- name: IDE
|
||||||
value: {{ .Values.ide | default "vscode" | quote }}
|
value: {{ .Values.ide.type | default "vscode" | quote }}
|
||||||
- name: SSH
|
- name: SSH
|
||||||
value: {{ .Values.ssh | toString | quote }}
|
value: {{ .Values.ssh.enabled | toString | quote }}
|
||||||
- name: USER_ID
|
- name: USER_ID
|
||||||
value: {{ .Values.userId | quote }}
|
value: {{ .Values.user.id | quote }}
|
||||||
- name: GROUP_ID
|
- name: GROUP_ID
|
||||||
value: {{ .Values.groupId | quote }}
|
value: {{ .Values.user.groupId | quote }}
|
||||||
- name: DISPLAY_WIDTH
|
- name: DISPLAY_WIDTH
|
||||||
value: {{ .Values.display.width | quote }}
|
value: {{ .Values.display.width | quote }}
|
||||||
- name: DISPLAY_HEIGHT
|
- name: DISPLAY_HEIGHT
|
||||||
value: {{ .Values.display.height | quote }}
|
value: {{ .Values.display.height | quote }}
|
||||||
- name: SECURE_CONNECTION
|
- name: SECURE_CONNECTION
|
||||||
value: {{ .Values.secureConnection | quote }}
|
value: {{ .Values.display.secureConnection | quote }}
|
||||||
|
{{- if .Values.fileManager.enabled }}
|
||||||
|
- name: WEB_FILE_MANAGER
|
||||||
|
value: "1"
|
||||||
|
- name: WEB_FILE_MANAGER_ALLOWED_PATHS
|
||||||
|
value: {{ .Values.fileManager.allowedPaths | quote }}
|
||||||
|
{{- if .Values.fileManager.deniedPaths }}
|
||||||
|
- name: WEB_FILE_MANAGER_DENIED_PATHS
|
||||||
|
value: {{ .Values.fileManager.deniedPaths | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
- name: HAPPY_HOME_DIR
|
- name: HAPPY_HOME_DIR
|
||||||
value: {{ .Values.happyHomeDir | quote }}
|
value: {{ .Values.happy.homeDir | quote }}
|
||||||
- name: HAPPY_EXPERIMENTAL
|
- name: HAPPY_EXPERIMENTAL
|
||||||
value: {{ .Values.happyExperimental | quote }}
|
value: {{ .Values.happy.experimental | quote }}
|
||||||
- name: HAPPY_SERVER_URL
|
- name: HAPPY_SERVER_URL
|
||||||
value: {{ .Values.happyServerUrl | quote }}
|
value: {{ .Values.happy.serverUrl | quote }}
|
||||||
- name: HAPPY_WEBAPP_URL
|
- name: HAPPY_WEBAPP_URL
|
||||||
value: {{ .Values.happyWebappUrl | quote }}
|
value: {{ .Values.happy.webappUrl | quote }}
|
||||||
- name: GITHUB_REPO
|
- name: GITHUB_REPO
|
||||||
value: {{ .Values.githubRepo | quote }}
|
value: {{ .Values.githubRepo | quote }}
|
||||||
envFrom:
|
envFrom:
|
||||||
- secretRef:
|
- secretRef:
|
||||||
name: {{ include "antigravity.envSecretName" . }}
|
name: {{ include "devcontainer.envSecretName" . }}
|
||||||
optional: true
|
optional: true
|
||||||
resources:
|
resources:
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
@@ -92,7 +102,7 @@ spec:
|
|||||||
mountPath: /workspace
|
mountPath: /workspace
|
||||||
- name: shm
|
- name: shm
|
||||||
mountPath: /dev/shm
|
mountPath: /dev/shm
|
||||||
{{- if ne (.Values.ide | default "vscode") "none" }}
|
{{- if ne (.Values.ide.type | default "vscode") "none" }}
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /
|
path: /
|
||||||
@@ -105,7 +115,7 @@ spec:
|
|||||||
port: 5800
|
port: 5800
|
||||||
initialDelaySeconds: 10
|
initialDelaySeconds: 10
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
{{- else if .Values.ssh }}
|
{{- else if .Values.ssh.enabled }}
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
tcpSocket:
|
tcpSocket:
|
||||||
port: 22
|
port: 22
|
||||||
@@ -117,154 +127,156 @@ spec:
|
|||||||
initialDelaySeconds: 5
|
initialDelaySeconds: 5
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if and .Values.mcpSidecars.kubernetes.enabled (ne .Values.clusterAccess "none") }}
|
{{- if and .Values.mcp.sidecars.kubernetes.enabled (ne .Values.clusterAccess "none") }}
|
||||||
- name: kubernetes-mcp
|
- name: kubernetes-mcp
|
||||||
image: "{{ .Values.mcpSidecars.kubernetes.image.repository }}:{{ .Values.mcpSidecars.kubernetes.image.tag }}"
|
image: "{{ .Values.mcp.sidecars.kubernetes.image.repository }}:{{ .Values.mcp.sidecars.kubernetes.image.tag }}"
|
||||||
args:
|
args:
|
||||||
- --port
|
- --port
|
||||||
- {{ .Values.mcpSidecars.kubernetes.port | quote }}
|
- {{ .Values.mcp.sidecars.kubernetes.port | quote }}
|
||||||
ports:
|
ports:
|
||||||
- containerPort: {{ .Values.mcpSidecars.kubernetes.port }}
|
- containerPort: {{ .Values.mcp.sidecars.kubernetes.port }}
|
||||||
name: k8s-mcp
|
name: k8s-mcp
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /healthz
|
path: /healthz
|
||||||
port: {{ .Values.mcpSidecars.kubernetes.port }}
|
port: {{ .Values.mcp.sidecars.kubernetes.port }}
|
||||||
initialDelaySeconds: 10
|
initialDelaySeconds: 10
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /healthz
|
path: /healthz
|
||||||
port: {{ .Values.mcpSidecars.kubernetes.port }}
|
port: {{ .Values.mcp.sidecars.kubernetes.port }}
|
||||||
initialDelaySeconds: 5
|
initialDelaySeconds: 5
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
resources:
|
resources:
|
||||||
{{- toYaml .Values.mcpSidecars.kubernetes.resources | nindent 12 }}
|
{{- toYaml .Values.mcp.sidecars.kubernetes.resources | nindent 12 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if and .Values.mcpSidecars.flux.enabled (ne .Values.clusterAccess "none") }}
|
{{- if and .Values.mcp.sidecars.flux.enabled (ne .Values.clusterAccess "none") }}
|
||||||
- name: flux-mcp
|
- name: flux-mcp
|
||||||
image: "{{ .Values.mcpSidecars.flux.image.repository }}:{{ .Values.mcpSidecars.flux.image.tag }}"
|
image: "{{ .Values.mcp.sidecars.flux.image.repository }}:{{ .Values.mcp.sidecars.flux.image.tag }}"
|
||||||
args:
|
args:
|
||||||
- serve
|
- serve
|
||||||
- --transport=sse
|
- --transport=sse
|
||||||
- --port={{ .Values.mcpSidecars.flux.port }}
|
- --port={{ .Values.mcp.sidecars.flux.port }}
|
||||||
ports:
|
ports:
|
||||||
- containerPort: {{ .Values.mcpSidecars.flux.port }}
|
- containerPort: {{ .Values.mcp.sidecars.flux.port }}
|
||||||
name: flux-mcp
|
name: flux-mcp
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
tcpSocket:
|
tcpSocket:
|
||||||
port: {{ .Values.mcpSidecars.flux.port }}
|
port: {{ .Values.mcp.sidecars.flux.port }}
|
||||||
initialDelaySeconds: 10
|
initialDelaySeconds: 10
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
tcpSocket:
|
tcpSocket:
|
||||||
port: {{ .Values.mcpSidecars.flux.port }}
|
port: {{ .Values.mcp.sidecars.flux.port }}
|
||||||
initialDelaySeconds: 5
|
initialDelaySeconds: 5
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
resources:
|
resources:
|
||||||
{{- toYaml .Values.mcpSidecars.flux.resources | nindent 12 }}
|
{{- toYaml .Values.mcp.sidecars.flux.resources | nindent 12 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.mcpSidecars.homeassistant.enabled }}
|
{{- if .Values.mcp.sidecars.homeassistant.enabled }}
|
||||||
- name: homeassistant-mcp
|
- name: homeassistant-mcp
|
||||||
image: "{{ .Values.mcpSidecars.homeassistant.image.repository }}:{{ .Values.mcpSidecars.homeassistant.image.tag }}"
|
image: "{{ .Values.mcp.sidecars.homeassistant.image.repository }}:{{ .Values.mcp.sidecars.homeassistant.image.tag }}"
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: IfNotPresent
|
||||||
command: ["fastmcp", "run", "--transport", "sse", "--host", "0.0.0.0", "--port", "{{ .Values.mcpSidecars.homeassistant.port }}"]
|
command: ["fastmcp", "run", "--transport", "sse", "--host", "0.0.0.0", "--port", "{{ .Values.mcp.sidecars.homeassistant.port }}"]
|
||||||
ports:
|
ports:
|
||||||
- name: homeassistant
|
- name: homeassistant
|
||||||
containerPort: {{ .Values.mcpSidecars.homeassistant.port }}
|
containerPort: {{ .Values.mcp.sidecars.homeassistant.port }}
|
||||||
env:
|
env:
|
||||||
- name: HOMEASSISTANT_URL
|
- name: HOMEASSISTANT_URL
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: {{ include "antigravity.envSecretName" . }}
|
name: {{ include "devcontainer.envSecretName" . }}
|
||||||
key: homeassistant-url
|
key: HOMEASSISTANT_URL
|
||||||
optional: true
|
optional: true
|
||||||
- name: HOMEASSISTANT_TOKEN
|
- name: HOMEASSISTANT_TOKEN
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: {{ include "antigravity.envSecretName" . }}
|
name: {{ include "devcontainer.envSecretName" . }}
|
||||||
key: homeassistant-token
|
key: HOMEASSISTANT_TOKEN
|
||||||
optional: true
|
optional: true
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
tcpSocket:
|
tcpSocket:
|
||||||
port: {{ .Values.mcpSidecars.homeassistant.port }}
|
port: {{ .Values.mcp.sidecars.homeassistant.port }}
|
||||||
initialDelaySeconds: 10
|
initialDelaySeconds: 10
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
tcpSocket:
|
tcpSocket:
|
||||||
port: {{ .Values.mcpSidecars.homeassistant.port }}
|
port: {{ .Values.mcp.sidecars.homeassistant.port }}
|
||||||
initialDelaySeconds: 5
|
initialDelaySeconds: 5
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
resources:
|
resources:
|
||||||
{{- toYaml .Values.mcpSidecars.homeassistant.resources | nindent 12 }}
|
{{- toYaml .Values.mcp.sidecars.homeassistant.resources | nindent 12 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.mcpSidecars.github.enabled }}
|
{{- if .Values.mcp.sidecars.pgtuner.enabled }}
|
||||||
- name: github-mcp
|
|
||||||
image: "{{ .Values.mcpSidecars.github.image.repository }}:{{ .Values.mcpSidecars.github.image.tag }}"
|
|
||||||
imagePullPolicy: Always
|
|
||||||
args:
|
|
||||||
- --sse
|
|
||||||
- --port={{ .Values.mcpSidecars.github.port }}
|
|
||||||
ports:
|
|
||||||
- name: github
|
|
||||||
containerPort: {{ .Values.mcpSidecars.github.port }}
|
|
||||||
env:
|
|
||||||
- name: GITHUB_PERSONAL_ACCESS_TOKEN
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: {{ include "antigravity.envSecretName" . }}
|
|
||||||
key: github-token
|
|
||||||
optional: true
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /health
|
|
||||||
port: {{ .Values.mcpSidecars.github.port }}
|
|
||||||
initialDelaySeconds: 10
|
|
||||||
periodSeconds: 10
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /health
|
|
||||||
port: {{ .Values.mcpSidecars.github.port }}
|
|
||||||
initialDelaySeconds: 5
|
|
||||||
periodSeconds: 5
|
|
||||||
resources:
|
|
||||||
{{- toYaml .Values.mcpSidecars.github.resources | nindent 12 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- if .Values.mcpSidecars.pgtuner.enabled }}
|
|
||||||
- name: pgtuner-mcp
|
- name: pgtuner-mcp
|
||||||
image: "{{ .Values.mcpSidecars.pgtuner.image.repository }}:{{ .Values.mcpSidecars.pgtuner.image.tag }}"
|
image: "{{ .Values.mcp.sidecars.pgtuner.image.repository }}:{{ .Values.mcp.sidecars.pgtuner.image.tag }}"
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always # pgtuner uses `latest` tag (no versioned releases available)
|
||||||
command: ["python", "-m", "pgtuner_mcp", "--transport", "sse", "--port", "{{ .Values.mcpSidecars.pgtuner.port }}"]
|
command: ["python", "-m", "pgtuner_mcp", "--mode", "sse", "--host", "0.0.0.0", "--port", "{{ .Values.mcp.sidecars.pgtuner.port }}"]
|
||||||
ports:
|
ports:
|
||||||
- name: pgtuner
|
- name: pgtuner
|
||||||
containerPort: {{ .Values.mcpSidecars.pgtuner.port }}
|
containerPort: {{ .Values.mcp.sidecars.pgtuner.port }}
|
||||||
env:
|
env:
|
||||||
- name: DATABASE_URI
|
- name: DATABASE_URI
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: {{ include "antigravity.envSecretName" . }}
|
name: {{ include "devcontainer.envSecretName" . }}
|
||||||
key: database-uri
|
key: DATABASE_URI
|
||||||
optional: true
|
optional: true
|
||||||
- name: PGTUNER_EXCLUDE_USERIDS
|
- name: PGTUNER_EXCLUDE_USERIDS
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: {{ include "antigravity.envSecretName" . }}
|
name: {{ include "devcontainer.envSecretName" . }}
|
||||||
key: pgtuner-exclude-userids
|
key: PGTUNER_EXCLUDE_USERIDS
|
||||||
optional: true
|
optional: true
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
tcpSocket:
|
tcpSocket:
|
||||||
port: {{ .Values.mcpSidecars.pgtuner.port }}
|
port: {{ .Values.mcp.sidecars.pgtuner.port }}
|
||||||
initialDelaySeconds: 10
|
initialDelaySeconds: 10
|
||||||
periodSeconds: 10
|
periodSeconds: 10
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
tcpSocket:
|
tcpSocket:
|
||||||
port: {{ .Values.mcpSidecars.pgtuner.port }}
|
port: {{ .Values.mcp.sidecars.pgtuner.port }}
|
||||||
initialDelaySeconds: 5
|
initialDelaySeconds: 5
|
||||||
periodSeconds: 5
|
periodSeconds: 5
|
||||||
resources:
|
resources:
|
||||||
{{- toYaml .Values.mcpSidecars.pgtuner.resources | nindent 12 }}
|
{{- toYaml .Values.mcp.sidecars.pgtuner.resources | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.mcp.sidecars.playwright.enabled }}
|
||||||
|
- name: playwright-mcp
|
||||||
|
image: "{{ .Values.mcp.sidecars.playwright.image.repository }}:{{ .Values.mcp.sidecars.playwright.image.tag }}"
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
command: ["node"]
|
||||||
|
args:
|
||||||
|
- cli.js
|
||||||
|
- --headless
|
||||||
|
- --browser
|
||||||
|
- chromium
|
||||||
|
- --no-sandbox
|
||||||
|
- --host
|
||||||
|
- 0.0.0.0
|
||||||
|
- --port
|
||||||
|
- {{ .Values.mcp.sidecars.playwright.port | quote }}
|
||||||
|
ports:
|
||||||
|
- name: playwright
|
||||||
|
containerPort: {{ .Values.mcp.sidecars.playwright.port }}
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: {{ .Values.mcp.sidecars.playwright.port }}
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
periodSeconds: 10
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: {{ .Values.mcp.sidecars.playwright.port }}
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 5
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.mcp.sidecars.playwright.resources | nindent 12 }}
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsGroup: 1000
|
||||||
{{- end }}
|
{{- end }}
|
||||||
volumes:
|
volumes:
|
||||||
- name: workspace
|
- name: workspace
|
||||||
@@ -275,4 +287,4 @@ spec:
|
|||||||
sizeLimit: {{ .Values.shm.sizeLimit }}
|
sizeLimit: {{ .Values.shm.sizeLimit }}
|
||||||
- name: userhome
|
- name: userhome
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: {{ include "antigravity.pvcName" . }}
|
claimName: {{ include "devcontainer.pvcName" . }}
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: PersistentVolumeClaim
|
kind: PersistentVolumeClaim
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "antigravity.pvcName" . }}
|
name: {{ include "devcontainer.pvcName" . }}
|
||||||
|
annotations:
|
||||||
|
helm.sh/resource-policy: keep
|
||||||
labels:
|
labels:
|
||||||
{{- include "antigravity.labels" . | nindent 4 }}
|
{{- include "devcontainer.labels" . | nindent 4 }}
|
||||||
spec:
|
spec:
|
||||||
accessModes:
|
accessModes:
|
||||||
- ReadWriteMany
|
- ReadWriteMany
|
||||||
|
{{- if .Values.storage.className }}
|
||||||
storageClassName: {{ .Values.storage.className }}
|
storageClassName: {{ .Values.storage.className }}
|
||||||
|
{{- end }}
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .Values.storage.size }}
|
storage: {{ .Values.storage.size }}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{{- $access := .Values.clusterAccess | default "none" }}
|
{{- $access := .Values.clusterAccess | default "none" }}
|
||||||
{{- $name := include "antigravity.fullname" . }}
|
{{- $name := include "devcontainer.fullname" . }}
|
||||||
{{- $ns := .Release.Namespace }}
|
{{- $ns := .Release.Namespace }}
|
||||||
{{- $labels := include "antigravity.labels" . }}
|
{{- $labels := include "devcontainer.labels" . }}
|
||||||
|
|
||||||
{{- if ne $access "none" }}
|
{{- if ne $access "none" }}
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "antigravity.fullname" . }}
|
name: {{ include "devcontainer.fullname" . }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "antigravity.labels" . | nindent 4 }}
|
{{- include "devcontainer.labels" . | nindent 4 }}
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
{{- if ne (.Values.ide | default "vscode") "none" }}
|
{{- if ne (.Values.ide.type | default "vscode") "none" }}
|
||||||
- port: 5800
|
- port: 5800
|
||||||
name: vnc-web
|
name: vnc-web
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
targetPort: vnc-web
|
targetPort: vnc-web
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.ssh }}
|
{{- if .Values.ssh.enabled }}
|
||||||
- port: 22
|
- port: 22
|
||||||
name: ssh
|
name: ssh
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
targetPort: ssh
|
targetPort: ssh
|
||||||
{{- end }}
|
{{- end }}
|
||||||
selector:
|
selector:
|
||||||
{{- include "antigravity.labels" . | nindent 4 }}
|
{{- include "devcontainer.labels" . | nindent 4 }}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# QUICKSTART VALUES - Just set these 3 essentials!
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Instance name (required)
|
||||||
|
name: mydev
|
||||||
|
|
||||||
|
# GitHub repository to clone (required)
|
||||||
|
githubRepo: https://github.com/youruser/yourrepo
|
||||||
|
|
||||||
|
# IDE choice (optional - defaults to vscode)
|
||||||
|
# Options: vscode | antigravity | none
|
||||||
|
ide:
|
||||||
|
type: vscode
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# COMMON CUSTOMIZATIONS (optional)
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Enable SSH access
|
||||||
|
# ssh:
|
||||||
|
# enabled: true
|
||||||
|
|
||||||
|
# Adjust resources for smaller/larger workloads
|
||||||
|
# resources:
|
||||||
|
# requests:
|
||||||
|
# memory: "1Gi" # Smaller
|
||||||
|
# cpu: "500m"
|
||||||
|
# limits:
|
||||||
|
# memory: "4Gi" # Smaller
|
||||||
|
# cpu: "2000m"
|
||||||
|
|
||||||
|
# Different storage size
|
||||||
|
# storage:
|
||||||
|
# size: 16Gi # Smaller
|
||||||
|
|
||||||
|
# Disable some MCP sidecars to save resources
|
||||||
|
# mcp:
|
||||||
|
# sidecars:
|
||||||
|
# kubernetes:
|
||||||
|
# enabled: false
|
||||||
|
# flux:
|
||||||
|
# enabled: false
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# USAGE INSTRUCTIONS
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# 1. Copy this file: cp values-quickstart.yaml my-values.yaml
|
||||||
|
# 2. Edit the 'name' and 'githubRepo' fields above
|
||||||
|
# 3. Deploy: helm install mydev ./chart -f my-values.yaml
|
||||||
|
# 4. Access: kubectl port-forward deployment/devcontainer-mydev 5800:5800
|
||||||
|
# 5. Open: http://localhost:5800
|
||||||
|
|
||||||
|
# For secrets (GitHub token, passwords):
|
||||||
|
# kubectl create secret generic devcontainer-mydev-secrets-env \
|
||||||
|
# --from-literal=GITHUB_TOKEN='ghp_...' \
|
||||||
|
# --from-literal=VNC_PASSWORD='changeme'
|
||||||
@@ -0,0 +1,260 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "https://github.com/cpfarhood/devcontainer/chart/values.schema.json",
|
||||||
|
"title": "Dev Container Helm Chart Values Schema",
|
||||||
|
"description": "Schema for validating values.yaml in the Dev Container Helm chart",
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true,
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Instance name used to generate resource names",
|
||||||
|
"pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$",
|
||||||
|
"minLength": 1,
|
||||||
|
"maxLength": 63
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"repository": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Container image repository"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Container image tag"
|
||||||
|
},
|
||||||
|
"pullPolicy": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["Always", "IfNotPresent", "Never"],
|
||||||
|
"description": "Image pull policy"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["repository", "tag"]
|
||||||
|
},
|
||||||
|
"githubRepo": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "GitHub repository URL to clone",
|
||||||
|
"pattern": "^https?://.+/.+/.+$"
|
||||||
|
},
|
||||||
|
"ide": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["vscode", "antigravity", "none"],
|
||||||
|
"description": "IDE to launch in the container"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["type"]
|
||||||
|
},
|
||||||
|
"ssh": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Enable SSH server on port 22"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["enabled"]
|
||||||
|
},
|
||||||
|
"display": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"width": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9]+$",
|
||||||
|
"description": "VNC display width in pixels"
|
||||||
|
},
|
||||||
|
"height": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9]+$",
|
||||||
|
"description": "VNC display height in pixels"
|
||||||
|
},
|
||||||
|
"secureConnection": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["0", "1"],
|
||||||
|
"description": "Enable secure VNC connection"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["width", "height", "secureConnection"]
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9]+$",
|
||||||
|
"description": "User ID (UID)"
|
||||||
|
},
|
||||||
|
"groupId": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9]+$",
|
||||||
|
"description": "Group ID (GID)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["id", "groupId"]
|
||||||
|
},
|
||||||
|
"storage": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"size": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9]+[KMGT]i$",
|
||||||
|
"description": "Storage size (e.g., 32Gi)"
|
||||||
|
},
|
||||||
|
"className": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Storage class name (must support ReadWriteMany)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["size"]
|
||||||
|
},
|
||||||
|
"resources": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"requests": {
|
||||||
|
"$ref": "#/$defs/resourceSpec"
|
||||||
|
},
|
||||||
|
"limits": {
|
||||||
|
"$ref": "#/$defs/resourceSpec"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["requests", "limits"]
|
||||||
|
},
|
||||||
|
"shm": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"sizeLimit": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9]+[KMGT]i$",
|
||||||
|
"description": "Shared memory size limit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["sizeLimit"]
|
||||||
|
},
|
||||||
|
"clusterAccess": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["none", "readonlyns", "readwritens", "readonly", "readwrite"],
|
||||||
|
"description": "Kubernetes cluster access level"
|
||||||
|
},
|
||||||
|
"happy": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"serverUrl": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Happy Coder server URL"
|
||||||
|
},
|
||||||
|
"webappUrl": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Happy Coder webapp URL"
|
||||||
|
},
|
||||||
|
"homeDir": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Happy Coder home directory"
|
||||||
|
},
|
||||||
|
"experimental": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["true", "false"],
|
||||||
|
"description": "Enable experimental Happy features"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["homeDir", "experimental"]
|
||||||
|
},
|
||||||
|
"mcp": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"sidecars": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"kubernetes": {
|
||||||
|
"$ref": "#/$defs/mcpSidecar"
|
||||||
|
},
|
||||||
|
"flux": {
|
||||||
|
"$ref": "#/$defs/mcpSidecar"
|
||||||
|
},
|
||||||
|
"homeassistant": {
|
||||||
|
"$ref": "#/$defs/mcpSidecar"
|
||||||
|
},
|
||||||
|
"pgtuner": {
|
||||||
|
"$ref": "#/$defs/mcpSidecar"
|
||||||
|
},
|
||||||
|
"playwright": {
|
||||||
|
"$ref": "#/$defs/mcpSidecar"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["sidecars"]
|
||||||
|
},
|
||||||
|
"envSecretName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Custom environment secret name"
|
||||||
|
},
|
||||||
|
"resourceProfile": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["auto", "small", "medium", "large", "xlarge"],
|
||||||
|
"description": "Resource profile preset"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["name"],
|
||||||
|
"$defs": {
|
||||||
|
"resourceSpec": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"memory": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9]+[KMGT]i$",
|
||||||
|
"description": "Memory resource specification"
|
||||||
|
},
|
||||||
|
"cpu": {
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[0-9]+m?$",
|
||||||
|
"description": "CPU resource specification"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["memory", "cpu"]
|
||||||
|
},
|
||||||
|
"mcpSidecar": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Enable this MCP sidecar"
|
||||||
|
},
|
||||||
|
"image": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"repository": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["repository", "tag"]
|
||||||
|
},
|
||||||
|
"port": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 65535,
|
||||||
|
"description": "Port for the MCP sidecar"
|
||||||
|
},
|
||||||
|
"resources": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"requests": {
|
||||||
|
"$ref": "#/$defs/resourceSpec"
|
||||||
|
},
|
||||||
|
"limits": {
|
||||||
|
"$ref": "#/$defs/resourceSpec"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["requests", "limits"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["enabled", "image", "port", "resources"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+154
-102
@@ -1,6 +1,11 @@
|
|||||||
|
# =============================================================================
|
||||||
|
# BASIC CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
# Instance name — used to generate resource names (devcontainer-{name}, userhome-{name})
|
# Instance name — used to generate resource names (devcontainer-{name}, userhome-{name})
|
||||||
name: ""
|
name: ""
|
||||||
|
|
||||||
|
# Container image configuration
|
||||||
image:
|
image:
|
||||||
repository: ghcr.io/cpfarhood/devcontainer
|
repository: ghcr.io/cpfarhood/devcontainer
|
||||||
tag: latest
|
tag: latest
|
||||||
@@ -9,43 +14,50 @@ image:
|
|||||||
# GitHub repository to clone into /workspace
|
# GitHub repository to clone into /workspace
|
||||||
githubRepo: ""
|
githubRepo: ""
|
||||||
|
|
||||||
# IDE to launch inside the container.
|
# =============================================================================
|
||||||
# Options:
|
# ACCESS & INTERFACE
|
||||||
# vscode — VSCode via VNC browser UI on port 5800 (default)
|
# =============================================================================
|
||||||
# antigravity — Google Antigravity (VSCode fork) via VNC on port 5800
|
|
||||||
# none — no IDE; useful when ssh: true is the sole access method
|
|
||||||
ide: vscode
|
|
||||||
|
|
||||||
# Start an OpenSSH server on port 22 in addition to the IDE.
|
# IDE configuration
|
||||||
# Set SSH_AUTHORIZED_KEYS in the env secret to allow key-based login.
|
ide:
|
||||||
ssh: false
|
# Options: vscode | antigravity | none
|
||||||
|
type: vscode
|
||||||
|
|
||||||
# Happy Coder endpoints
|
# SSH access configuration
|
||||||
happyServerUrl: "https://happy.farh.net"
|
ssh:
|
||||||
happyWebappUrl: "https://happy-coder.farh.net"
|
enabled: false
|
||||||
happyHomeDir: "/config/userdata/.happy"
|
|
||||||
happyExperimental: "true"
|
|
||||||
|
|
||||||
# VNC display
|
# Web file manager — built-in upload/download via the VNC web interface (port 5800)
|
||||||
|
# Uses the base image's WEB_FILE_MANAGER feature (no extra sidecar needed)
|
||||||
|
fileManager:
|
||||||
|
enabled: false
|
||||||
|
# Paths the file manager can access (default: AUTO = mapped volumes)
|
||||||
|
# Options: AUTO | ALL | comma-separated list of paths
|
||||||
|
allowedPaths: "/workspace,/config"
|
||||||
|
# Paths to deny (takes precedence over allowedPaths)
|
||||||
|
deniedPaths: ""
|
||||||
|
|
||||||
|
# VNC display settings
|
||||||
display:
|
display:
|
||||||
width: "1920"
|
width: "1920"
|
||||||
height: "1080"
|
height: "1080"
|
||||||
|
secureConnection: "0" # Set to "1" when TLS is not terminated upstream
|
||||||
|
|
||||||
# Set to "0" when TLS is terminated at the gateway layer
|
# User configuration
|
||||||
secureConnection: "0"
|
user:
|
||||||
|
id: "1000"
|
||||||
|
groupId: "1000"
|
||||||
|
|
||||||
userId: "1000"
|
# =============================================================================
|
||||||
groupId: "1000"
|
# INFRASTRUCTURE & RESOURCES
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Storage configuration
|
||||||
storage:
|
storage:
|
||||||
size: 32Gi
|
size: 32Gi
|
||||||
className: ceph-filesystem
|
className: "" # Empty string uses the cluster's default StorageClass (must support ReadWriteMany)
|
||||||
|
|
||||||
# Shared memory size — mounted at /dev/shm as a memory-backed emptyDir.
|
|
||||||
# Electron apps (Antigravity, Chrome) use /dev/shm for GPU/IPC buffers.
|
|
||||||
shm:
|
|
||||||
sizeLimit: 2Gi
|
|
||||||
|
|
||||||
|
# Resource allocation
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
memory: "2Gi"
|
memory: "2Gi"
|
||||||
@@ -54,83 +66,123 @@ resources:
|
|||||||
memory: "8Gi"
|
memory: "8Gi"
|
||||||
cpu: "4000m"
|
cpu: "4000m"
|
||||||
|
|
||||||
# Kubernetes cluster access granted to the devcontainer pod via RBAC.
|
# Shared memory for Electron apps (Chrome, Antigravity)
|
||||||
# Options:
|
shm:
|
||||||
# none — no cluster access (default)
|
sizeLimit: 2Gi
|
||||||
# readonlyns — get/list/watch all resources in the release namespace
|
|
||||||
# readwritens — full access to all resources in the release namespace
|
# Kubernetes cluster access via RBAC
|
||||||
# readonly — get/list/watch all resources cluster-wide
|
# Options: none | readonlyns | readwritens | readonly | readwrite
|
||||||
# readwrite — full access to all resources cluster-wide
|
|
||||||
clusterAccess: none
|
clusterAccess: none
|
||||||
|
|
||||||
# Name of existing Secret containing env vars (GITHUB_TOKEN, VNC_PASSWORD, etc.)
|
# =============================================================================
|
||||||
# Defaults to: devcontainer-{name}-secrets-env
|
# INTEGRATIONS
|
||||||
envSecretName: ""
|
# =============================================================================
|
||||||
|
|
||||||
# MCP server sidecars — run alongside the devcontainer to inherit pod RBAC.
|
# Happy Coder AI assistant configuration
|
||||||
mcpSidecars:
|
happy:
|
||||||
kubernetes:
|
serverUrl: ""
|
||||||
enabled: true
|
webappUrl: ""
|
||||||
image:
|
homeDir: "/config/userdata/.happy"
|
||||||
repository: quay.io/containers/kubernetes_mcp_server
|
experimental: "true"
|
||||||
tag: v0.0.57 # Pinned version (Jan 27, 2025) with token exchange and field selector support
|
|
||||||
port: 8080
|
# MCP (Model Context Protocol) server sidecars
|
||||||
resources:
|
mcp:
|
||||||
requests:
|
sidecars:
|
||||||
memory: "64Mi"
|
# Kubernetes API access
|
||||||
cpu: "50m"
|
kubernetes:
|
||||||
limits:
|
enabled: true
|
||||||
memory: "256Mi"
|
image:
|
||||||
cpu: "500m"
|
repository: quay.io/containers/kubernetes_mcp_server
|
||||||
flux:
|
tag: v0.0.57
|
||||||
enabled: true
|
port: 8080
|
||||||
image:
|
resources:
|
||||||
repository: ghcr.io/controlplaneio-fluxcd/flux-operator-mcp
|
requests:
|
||||||
tag: v0.41.1
|
memory: "64Mi"
|
||||||
port: 8081
|
cpu: "50m"
|
||||||
resources:
|
limits:
|
||||||
requests:
|
memory: "256Mi"
|
||||||
memory: "64Mi"
|
cpu: "500m"
|
||||||
cpu: "50m"
|
|
||||||
limits:
|
# Flux GitOps operations
|
||||||
memory: "256Mi"
|
flux:
|
||||||
cpu: "500m"
|
enabled: true
|
||||||
homeassistant:
|
image:
|
||||||
enabled: false # Disabled by default, requires HOMEASSISTANT_URL and HOMEASSISTANT_TOKEN
|
repository: ghcr.io/controlplaneio-fluxcd/flux-operator-mcp
|
||||||
image:
|
tag: v0.41.1
|
||||||
repository: ghcr.io/homeassistant-ai/ha-mcp
|
port: 8081
|
||||||
tag: 6.7.1 # Pinned version (Feb 20, 2026) - latest stable release
|
resources:
|
||||||
port: 8087
|
requests:
|
||||||
resources:
|
memory: "64Mi"
|
||||||
requests:
|
cpu: "50m"
|
||||||
memory: "64Mi"
|
limits:
|
||||||
cpu: "50m"
|
memory: "256Mi"
|
||||||
limits:
|
cpu: "500m"
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "500m"
|
|
||||||
github:
|
|
||||||
enabled: false # DISABLED: GitHub MCP server has been archived, image doesn't exist
|
# Home Assistant smart home control
|
||||||
image:
|
homeassistant:
|
||||||
repository: ghcr.io/modelcontextprotocol/servers/github
|
enabled: false # Requires HOMEASSISTANT_URL and HOMEASSISTANT_TOKEN
|
||||||
tag: latest # Update to specific version once available
|
image:
|
||||||
port: 8088
|
repository: ghcr.io/homeassistant-ai/ha-mcp
|
||||||
resources:
|
tag: v6.7.1
|
||||||
requests:
|
port: 8087
|
||||||
memory: "64Mi"
|
resources:
|
||||||
cpu: "50m"
|
requests:
|
||||||
limits:
|
memory: "64Mi"
|
||||||
memory: "256Mi"
|
cpu: "50m"
|
||||||
cpu: "500m"
|
limits:
|
||||||
pgtuner:
|
memory: "256Mi"
|
||||||
enabled: false # Disabled by default, requires DATABASE_URI in secrets
|
cpu: "500m"
|
||||||
image:
|
|
||||||
repository: dog830228/pgtuner_mcp
|
# PostgreSQL performance tuning
|
||||||
tag: latest # TODO: pin to specific version once stable release available
|
pgtuner:
|
||||||
port: 8085
|
enabled: false # Requires DATABASE_URI in secrets
|
||||||
resources:
|
image:
|
||||||
requests:
|
repository: dog830228/pgtuner_mcp
|
||||||
memory: "64Mi"
|
tag: latest
|
||||||
cpu: "50m"
|
port: 8085
|
||||||
limits:
|
resources:
|
||||||
memory: "256Mi"
|
requests:
|
||||||
cpu: "500m"
|
memory: "64Mi"
|
||||||
|
cpu: "50m"
|
||||||
|
limits:
|
||||||
|
memory: "256Mi"
|
||||||
|
cpu: "500m"
|
||||||
|
|
||||||
|
# Browser automation and web testing
|
||||||
|
playwright:
|
||||||
|
enabled: true
|
||||||
|
image:
|
||||||
|
repository: mcr.microsoft.com/playwright/mcp
|
||||||
|
tag: v0.0.68
|
||||||
|
port: 8086
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "128Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
limits:
|
||||||
|
memory: "512Mi"
|
||||||
|
cpu: "1000m"
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# SMART DEFAULTS & AUTO-DETECTION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Environment auto-detection based on name patterns
|
||||||
|
# Automatically adjusts defaults for dev/test/prod/team environments
|
||||||
|
autoDetect:
|
||||||
|
environment: true # Auto-detect dev/prod/team from name
|
||||||
|
storageClass: true # Auto-detect ReadWriteMany storage class
|
||||||
|
resources: true # Auto-size resources based on enabled features
|
||||||
|
|
||||||
|
# Resource profiles (auto-selected based on environment and features)
|
||||||
|
# Override specific values above to customize
|
||||||
|
resourceProfile: auto # auto | small | medium | large | xlarge
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# ADVANCED CONFIGURATION
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
# Custom env secret name (defaults to: devcontainer-{name}-secrets-env)
|
||||||
|
envSecretName: ""
|
||||||
@@ -2,5 +2,9 @@
|
|||||||
# Fix the app user (UID 1000) created by baseimage-gui at runtime.
|
# Fix the app user (UID 1000) created by baseimage-gui at runtime.
|
||||||
# baseimage-gui sets shell=/sbin/nologin and home=/dev/null, which
|
# baseimage-gui sets shell=/sbin/nologin and home=/dev/null, which
|
||||||
# prevents VSCode from opening terminals.
|
# prevents VSCode from opening terminals.
|
||||||
usermod -s /bin/bash app
|
if id app >/dev/null 2>&1; then
|
||||||
usermod -d /config/userdata app
|
usermod -s /bin/bash app
|
||||||
|
usermod -d /config/userdata app
|
||||||
|
else
|
||||||
|
echo "WARNING: 'app' user not found, skipping usermod" >&2
|
||||||
|
fi
|
||||||
|
|||||||
+3
-13
@@ -1,5 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Initialize repository and start Happy Coder
|
# Initialize repository
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "=== Repository Initialization ==="
|
echo "=== Repository Initialization ==="
|
||||||
@@ -22,6 +22,7 @@ if [ -n "$GITHUB_TOKEN" ]; then
|
|||||||
|
|
||||||
# Create or update the credentials file
|
# Create or update the credentials file
|
||||||
CREDENTIALS_FILE="/config/userdata/.git-credentials"
|
CREDENTIALS_FILE="/config/userdata/.git-credentials"
|
||||||
|
mkdir -p "$(dirname "$CREDENTIALS_FILE")"
|
||||||
|
|
||||||
# Support multiple git hosting providers
|
# Support multiple git hosting providers
|
||||||
# GitHub supports both oauth2 and token as username
|
# GitHub supports both oauth2 and token as username
|
||||||
@@ -51,6 +52,7 @@ else
|
|||||||
|
|
||||||
# Create an empty credentials file with proper permissions
|
# Create an empty credentials file with proper permissions
|
||||||
CREDENTIALS_FILE="/config/userdata/.git-credentials"
|
CREDENTIALS_FILE="/config/userdata/.git-credentials"
|
||||||
|
mkdir -p "$(dirname "$CREDENTIALS_FILE")"
|
||||||
touch "$CREDENTIALS_FILE"
|
touch "$CREDENTIALS_FILE"
|
||||||
chmod 600 "$CREDENTIALS_FILE"
|
chmod 600 "$CREDENTIALS_FILE"
|
||||||
|
|
||||||
@@ -102,18 +104,6 @@ chown -R "$RUN_UID:$RUN_GID" "$WORKSPACE_DIR"
|
|||||||
mkdir -p "$HOME"
|
mkdir -p "$HOME"
|
||||||
chown "$RUN_UID:$RUN_GID" "$HOME"
|
chown "$RUN_UID:$RUN_GID" "$HOME"
|
||||||
|
|
||||||
# Start Happy Coder daemon. startapp.sh already runs as the app user (UID 1000),
|
|
||||||
# so no sudo needed — Happy/Claude Code will find credentials in the correct home dir.
|
|
||||||
echo "Starting Happy Coder..."
|
|
||||||
|
|
||||||
# Remove stale lock file. HAPPY_HOME_DIR lives on the home PVC so it survives
|
|
||||||
# pod restarts — without this cleanup the daemon refuses to start after a crash.
|
|
||||||
rm -f "${HAPPY_HOME_DIR:-$HOME/.happy}/daemon.state.json.lock"
|
|
||||||
|
|
||||||
cd "$WORKSPACE_DIR"
|
|
||||||
happy daemon start || echo "Happy Coder daemon failed to start, continuing anyway..."
|
|
||||||
|
|
||||||
echo "Happy Coder daemon started"
|
|
||||||
|
|
||||||
# Export workspace directory for startapp.sh
|
# Export workspace directory for startapp.sh
|
||||||
echo "$WORKSPACE_DIR" > /tmp/workspace-dir
|
echo "$WORKSPACE_DIR" > /tmp/workspace-dir
|
||||||
|
|||||||
+5
-2
@@ -2,9 +2,9 @@
|
|||||||
# Start application script for baseimage-gui
|
# Start application script for baseimage-gui
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "=== Starting Antigravity Dev Container ==="
|
echo "=== Starting Dev Container ==="
|
||||||
|
|
||||||
# Initialize repository and Happy Coder
|
# Initialize repository
|
||||||
/usr/local/bin/init-repo
|
/usr/local/bin/init-repo
|
||||||
|
|
||||||
# Get workspace directory
|
# Get workspace directory
|
||||||
@@ -34,6 +34,9 @@ case "$IDE" in
|
|||||||
exec sleep infinity
|
exec sleep infinity
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
if [ "$IDE" != "vscode" ]; then
|
||||||
|
echo "WARNING: Unknown IDE value '$IDE', defaulting to VSCode"
|
||||||
|
fi
|
||||||
echo "Opening VSCode in: $WORKSPACE_DIR"
|
echo "Opening VSCode in: $WORKSPACE_DIR"
|
||||||
exec code --new-window --wait "$WORKSPACE_DIR"
|
exec code --new-window --wait "$WORKSPACE_DIR"
|
||||||
;;
|
;;
|
||||||
|
|||||||
Reference in New Issue
Block a user