Files
devcontainer/.github/workflows/release-unified.yaml
T
DevContainer User 7235d2dc67 fix: disable Docker layer cache in release builds
Release workflow was using GHA cache which served stale layers,
causing tools like gh CLI to be missing from tagged images despite
being in the Dockerfile. Use no-cache for release builds to ensure
every layer is built fresh. Regular CI builds keep the cache for speed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 17:43:11 +00:00

193 lines
6.7 KiB
YAML

name: Unified Release
on:
workflow_dispatch:
inputs:
version:
description: 'Explicit version (e.g., 1.2.3). Leave blank to auto-increment.'
required: false
type: string
release_type:
description: 'Release type (used when version is blank)'
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: |
INPUT_VERSION="${{ github.event.inputs.version }}"
if [ -n "$INPUT_VERSION" ]; then
VERSION="$INPUT_VERSION"
else
# Auto-increment based on release_type
CURRENT=$(grep '^version:' chart/Chart.yaml | awk '{print $2}')
# Strip any pre-release suffix (e.g., 2.0.0-dev -> 2.0.0)
CURRENT=$(echo "$CURRENT" | sed 's/-.*//')
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 diff --quiet --staged || git commit -m "chore(release): ${{ steps.version.outputs.version }} [skip ci]"
- 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
no-cache: 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-to: type=gha,mode=max
platforms: linux/amd64
- name: Publish Helm Chart to GitHub Pages
run: |
helm package chart/
CHART_TGZ="devcontainer-${{ steps.version.outputs.version }}.tgz"
# Set up gh-pages in a temporary directory
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 }}
VERSION: ${{ steps.version.outputs.version }}
TAG: ${{ steps.version.outputs.tag }}
IMAGE: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.tag }}
run: |
PREV_TAG=$(git describe --tags --abbrev=0 HEAD~1 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 > release-notes.md <<NOTESEOF
## Release ${VERSION}
### Changes
${COMMITS}
### Docker Image
\`\`\`bash
docker pull ${IMAGE}
\`\`\`
### Helm Chart
\`\`\`bash
helm repo add devcontainer https://cpfarhood.github.io/devcontainer
helm repo update
helm install mydev devcontainer/devcontainer --version ${VERSION} --set name=mydev
\`\`\`
NOTESEOF
sed -i 's/^ //' release-notes.md
gh release create "${TAG}" \
--title "Release ${TAG}" \
--notes-file release-notes.md