Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cbdee590bf | |||
| 5570b2c617 | |||
| c3f8421d60 | |||
| 21d8fc73e6 | |||
| 0a63894f6d | |||
| a50a1815e0 | |||
| 131dad8611 | |||
| 581d0737e4 |
@@ -0,0 +1,74 @@
|
|||||||
|
# CI/CD Pipeline Guide
|
||||||
|
|
||||||
|
## 🚀 New Simplified Pipeline
|
||||||
|
|
||||||
|
### For Releases (Recommended)
|
||||||
|
Use the **Unified Release** workflow from GitHub Actions tab:
|
||||||
|
1. Go to Actions → Unified Release → Run workflow
|
||||||
|
2. Enter version number (e.g., 0.1.25) or choose release type
|
||||||
|
3. Click "Run workflow"
|
||||||
|
|
||||||
|
This single workflow:
|
||||||
|
- ✅ Updates chart version
|
||||||
|
- ✅ Creates git tag
|
||||||
|
- ✅ Builds and pushes Docker image with proper tags
|
||||||
|
- ✅ Publishes Helm chart
|
||||||
|
- ✅ Creates GitHub Release with notes
|
||||||
|
- ✅ **NO MORE `[skip ci]` NONSENSE!**
|
||||||
|
|
||||||
|
### For Quick Fixes
|
||||||
|
Use the **Quick Fix Build** workflow when you need to push a fix without ceremony:
|
||||||
|
1. Go to Actions → Quick Fix Build → Run workflow
|
||||||
|
2. Optionally specify a tag (defaults to 'latest')
|
||||||
|
3. Click "Run workflow"
|
||||||
|
|
||||||
|
This builds and pushes the Docker image immediately without version bumps.
|
||||||
|
|
||||||
|
## Workflow Files
|
||||||
|
|
||||||
|
| Workflow | Purpose | Trigger | What it does |
|
||||||
|
|----------|---------|---------|--------------|
|
||||||
|
| `release-unified.yaml` | **Main release workflow** | Manual dispatch | Complete release process |
|
||||||
|
| `quick-fix.yaml` | Emergency fixes | Manual dispatch | Just build & push Docker |
|
||||||
|
| `build-and-push.yaml` | CI builds | Tags & PRs | Auto-build on tags/PRs |
|
||||||
|
| `release.yaml` | GitHub releases | Tag push | Create GitHub release |
|
||||||
|
| `helm-publish.yaml` | Helm chart only | Tags | Publish Helm chart |
|
||||||
|
|
||||||
|
## Common Tasks
|
||||||
|
|
||||||
|
### Release a new version
|
||||||
|
```bash
|
||||||
|
# Option 1: Use GitHub UI
|
||||||
|
# Go to Actions → Unified Release → Run workflow
|
||||||
|
|
||||||
|
# Option 2: Use GitHub CLI
|
||||||
|
gh workflow run release-unified.yaml -f version=0.1.25 -f release_type=patch
|
||||||
|
```
|
||||||
|
|
||||||
|
### Push a quick fix
|
||||||
|
```bash
|
||||||
|
# Use GitHub UI: Actions → Quick Fix Build → Run workflow
|
||||||
|
# Or:
|
||||||
|
gh workflow run quick-fix.yaml -f tag=hotfix-1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check build status
|
||||||
|
```bash
|
||||||
|
gh run list --workflow=release-unified.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Version Strategy
|
||||||
|
|
||||||
|
- **Major** (1.0.0): Breaking changes
|
||||||
|
- **Minor** (0.2.0): New features
|
||||||
|
- **Patch** (0.1.25): Bug fixes
|
||||||
|
|
||||||
|
## Old Pipeline Issues (Now Fixed!)
|
||||||
|
|
||||||
|
❌ **REMOVED**: Auto-version-bump with `[skip ci]` that prevented Docker builds
|
||||||
|
❌ **REMOVED**: Disconnected workflows requiring manual tag juggling
|
||||||
|
❌ **REMOVED**: Complex multi-step process for releases
|
||||||
|
|
||||||
|
✅ **NEW**: Single unified workflow that does everything
|
||||||
|
✅ **NEW**: Manual control over versions
|
||||||
|
✅ **NEW**: Quick fix workflow for emergencies
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
name: Publish Helm Chart
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Set up Helm
|
||||||
|
uses: azure/setup-helm@v4
|
||||||
|
|
||||||
|
- name: Get Chart Version
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
VERSION=$(grep '^version:' chart/Chart.yaml | awk '{print $2}')
|
||||||
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Log in to GHCR
|
||||||
|
run: |
|
||||||
|
helm registry login ghcr.io \
|
||||||
|
--username ${{ github.actor }} \
|
||||||
|
--password ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Package and Push Chart
|
||||||
|
run: |
|
||||||
|
helm package chart/
|
||||||
|
helm push devcontainer-${{ steps.version.outputs.version }}.tgz oci://ghcr.io/cpfarhood/charts
|
||||||
|
echo "✅ Helm chart published: devcontainer-${{ steps.version.outputs.version }}"
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
name: Quick Fix Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
description: 'Tag for the image (defaults to latest)'
|
||||||
|
required: false
|
||||||
|
default: 'latest'
|
||||||
|
type: string
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: ghcr.io
|
||||||
|
IMAGE_NAME: ${{ github.repository }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Log in to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and Push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.event.inputs.tag }}
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
platforms: linux/amd64
|
||||||
|
|
||||||
|
- name: Summary
|
||||||
|
run: |
|
||||||
|
echo "## ✅ Quick Fix Build Complete" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "### Images Published:" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.event.inputs.tag }}\`" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
name: Unified Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: 'Version to release (e.g., 0.1.25)'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
release_type:
|
||||||
|
description: 'Release type'
|
||||||
|
required: true
|
||||||
|
default: 'patch'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- patch
|
||||||
|
- minor
|
||||||
|
- major
|
||||||
|
|
||||||
|
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
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Set up Helm
|
||||||
|
uses: azure/setup-helm@v4
|
||||||
|
|
||||||
|
- name: Configure Git
|
||||||
|
run: |
|
||||||
|
git config user.name "github-actions[bot]"
|
||||||
|
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
|
- name: Determine Version
|
||||||
|
id: version
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event.inputs.version }}" != "" ]; then
|
||||||
|
VERSION="${{ github.event.inputs.version }}"
|
||||||
|
else
|
||||||
|
# Auto-determine next version based on release type
|
||||||
|
CURRENT=$(grep '^version:' chart/Chart.yaml | awk '{print $2}')
|
||||||
|
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
|
||||||
|
major)
|
||||||
|
VERSION="$((MAJOR + 1)).0.0"
|
||||||
|
;;
|
||||||
|
minor)
|
||||||
|
VERSION="${MAJOR}.$((MINOR + 1)).0"
|
||||||
|
;;
|
||||||
|
patch)
|
||||||
|
VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
echo "tag=v${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
echo "🚀 Releasing version ${VERSION}"
|
||||||
|
|
||||||
|
- name: Update Chart Version
|
||||||
|
run: |
|
||||||
|
sed -i "s/^version: .*/version: ${{ steps.version.outputs.version }}/" chart/Chart.yaml
|
||||||
|
git add chart/Chart.yaml
|
||||||
|
git commit -m "chore: release version ${{ steps.version.outputs.version }}"
|
||||||
|
|
||||||
|
- name: Create and Push Tag
|
||||||
|
run: |
|
||||||
|
git tag -a "${{ steps.version.outputs.tag }}" -m "Release ${{ steps.version.outputs.tag }}"
|
||||||
|
git push origin main
|
||||||
|
git push origin "${{ steps.version.outputs.tag }}"
|
||||||
|
|
||||||
|
- name: Log in to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and Push Docker Image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.tag }}
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}
|
||||||
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
platforms: linux/amd64
|
||||||
|
|
||||||
|
- name: Package 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 HEAD^ 2>/dev/null || echo "")
|
||||||
|
if [ -z "$PREV_TAG" ]; then
|
||||||
|
COMMITS=$(git log --pretty=format:"- %s (%h)" HEAD)
|
||||||
|
else
|
||||||
|
COMMITS=$(git log --pretty=format:"- %s (%h)" ${PREV_TAG}..HEAD)
|
||||||
|
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
|
||||||
@@ -88,7 +88,7 @@ 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 |
|
||||||
| `homeassistant-mcp` | `ghcr.io/homeassistant-ai/ha-mcp` | v6.7.1 | 8087 | `http://localhost:8087/sse` | Disabled |
|
| `homeassistant-mcp` | `ghcr.io/homeassistant-ai/ha-mcp` | 6.7.1 | 8087 | `http://localhost:8087/sse` | Disabled |
|
||||||
|
|
||||||
**Note:**
|
**Note:**
|
||||||
- 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)
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ mcpSidecars:
|
|||||||
enabled: true
|
enabled: true
|
||||||
image:
|
image:
|
||||||
repository: ghcr.io/homeassistant-ai/ha-mcp
|
repository: ghcr.io/homeassistant-ai/ha-mcp
|
||||||
tag: v6.7.1 # Override the pinned version if needed
|
tag: 6.7.1 # Override the pinned version if needed
|
||||||
port: 8087
|
port: 8087
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
|
|||||||
+1
-1
@@ -2,5 +2,5 @@ apiVersion: v2
|
|||||||
name: devcontainer
|
name: devcontainer
|
||||||
description: Antigravity Dev Container with Happy Coder AI assistant
|
description: Antigravity Dev Container with Happy Coder AI assistant
|
||||||
type: application
|
type: application
|
||||||
version: 0.1.21
|
version: 0.2.0
|
||||||
appVersion: "latest"
|
appVersion: "latest"
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ spec:
|
|||||||
- name: homeassistant-mcp
|
- name: homeassistant-mcp
|
||||||
image: "{{ .Values.mcpSidecars.homeassistant.image.repository }}:{{ .Values.mcpSidecars.homeassistant.image.tag }}"
|
image: "{{ .Values.mcpSidecars.homeassistant.image.repository }}:{{ .Values.mcpSidecars.homeassistant.image.tag }}"
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
command: ["fastmcp", "run", "fastmcp-sse.json"]
|
command: ["fastmcp", "run", "ha_mcp.main:app", "--transport", "sse", "--sse-server-host", "0.0.0.0", "--sse-server-port", "{{ .Values.mcpSidecars.homeassistant.port }}"]
|
||||||
ports:
|
ports:
|
||||||
- name: homeassistant
|
- name: homeassistant
|
||||||
containerPort: {{ .Values.mcpSidecars.homeassistant.port }}
|
containerPort: {{ .Values.mcpSidecars.homeassistant.port }}
|
||||||
|
|||||||
+1
-1
@@ -99,7 +99,7 @@ mcpSidecars:
|
|||||||
enabled: false # Disabled by default, requires HOMEASSISTANT_URL and HOMEASSISTANT_TOKEN
|
enabled: false # Disabled by default, requires HOMEASSISTANT_URL and HOMEASSISTANT_TOKEN
|
||||||
image:
|
image:
|
||||||
repository: ghcr.io/homeassistant-ai/ha-mcp
|
repository: ghcr.io/homeassistant-ai/ha-mcp
|
||||||
tag: v6.7.1 # Pinned version (Feb 20, 2026) - latest stable release
|
tag: 6.7.1 # Pinned version (Feb 20, 2026) - latest stable release
|
||||||
port: 8087
|
port: 8087
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
## MCP Sidecars
|
## MCP Sidecars
|
||||||
- **Kubernetes MCP** (v0.0.57, port 8080): Only deployed when enabled AND `clusterAccess` != `none`
|
- **Kubernetes MCP** (v0.0.57, port 8080): Only deployed when enabled AND `clusterAccess` != `none`
|
||||||
- **Flux MCP** (v0.41.1, port 8081): Only deployed when enabled AND `clusterAccess` != `none`
|
- **Flux MCP** (v0.41.1, port 8081): Only deployed when enabled AND `clusterAccess` != `none`
|
||||||
- **Home Assistant MCP** (v6.7.1, port 8087): Disabled by default, requires secrets:
|
- **Home Assistant MCP** (6.7.1, port 8087): Disabled by default, requires secrets:
|
||||||
- `homeassistant-url`: Base URL like `http://homeassistant.local:8123`
|
- `homeassistant-url`: Base URL like `http://homeassistant.local:8123`
|
||||||
- `homeassistant-token`: Long-lived access token
|
- `homeassistant-token`: Long-lived access token
|
||||||
- **Playwright MCP**: External service, not a sidecar
|
- **Playwright MCP**: External service, not a sidecar
|
||||||
|
|||||||
Reference in New Issue
Block a user