diff --git a/.github/workflows/README.md b/.github/workflows/README.md new file mode 100644 index 0000000..c031f39 --- /dev/null +++ b/.github/workflows/README.md @@ -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 \ No newline at end of file diff --git a/.github/workflows/helm-publish.yaml b/.github/workflows/helm-publish.yaml new file mode 100644 index 0000000..7be1275 --- /dev/null +++ b/.github/workflows/helm-publish.yaml @@ -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 }}" \ No newline at end of file diff --git a/.github/workflows/helm-release.yaml b/.github/workflows/helm-release.yaml.old similarity index 100% rename from .github/workflows/helm-release.yaml rename to .github/workflows/helm-release.yaml.old diff --git a/.github/workflows/quick-fix.yaml b/.github/workflows/quick-fix.yaml new file mode 100644 index 0000000..83b039a --- /dev/null +++ b/.github/workflows/quick-fix.yaml @@ -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 \ No newline at end of file diff --git a/.github/workflows/release-unified.yaml b/.github/workflows/release-unified.yaml new file mode 100644 index 0000000..23e717a --- /dev/null +++ b/.github/workflows/release-unified.yaml @@ -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<> $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 \ No newline at end of file