From 323e03520df734bb11daf563dd16301159e780f1 Mon Sep 17 00:00:00 2001 From: Waleed Date: Fri, 12 Dec 2025 15:57:10 -0800 Subject: [PATCH] feat(releases): tag releases to main with version numbers, speed up docker builds (#2337) * feat(releases): tag releases to main with version numbers, speed up docker builds * resize runners --- .dockerignore | 66 +++++++++++++++++++++++++++++++++++--- .github/workflows/ci.yml | 62 ++++++++++++++++++++++++++++++++--- docker/app.Dockerfile | 17 +++++----- docker/db.Dockerfile | 5 +-- docker/realtime.Dockerfile | 8 ++--- 5 files changed, 133 insertions(+), 25 deletions(-) diff --git a/.dockerignore b/.dockerignore index c1689c398..98af3e0c6 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,11 +1,67 @@ +# Git +.git +.gitignore + +# Documentation LICENSE NOTICE +README.md +*.md +docs/ + +# IDE and editor +.vscode +.idea +*.swp +*.swo + +# Environment and config +.env* +!.env.example .prettierrc .prettierignore -README.md -.gitignore -.husky +.eslintrc* +.eslintignore + +# CI/CD and DevOps .github .devcontainer -.env.example -node_modules \ No newline at end of file +.husky +docker-compose*.yml +Dockerfile* + +# Build artifacts and caches +.next +.turbo +.cache +dist +build +out +coverage +*.log + +# Dependencies (will be installed fresh in container) +node_modules +.bun + +# Test files +**/*.test.ts +**/*.test.tsx +**/*.spec.ts +**/*.spec.tsx +__tests__ +__mocks__ +jest.config.* +vitest.config.* + +# TypeScript build info +*.tsbuildinfo + +# OS files +.DS_Store +Thumbs.db + +# Temporary files +tmp +temp +*.tmp diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3db18c5d4..8b8ba0146 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,10 +16,35 @@ jobs: uses: ./.github/workflows/test-build.yml secrets: inherit + # Detect if this is a version release commit (e.g., "v0.5.24: ...") + detect-version: + name: Detect Version + runs-on: blacksmith-4vcpu-ubuntu-2404 + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging') + outputs: + version: ${{ steps.extract.outputs.version }} + is_release: ${{ steps.extract.outputs.is_release }} + steps: + - name: Extract version from commit message + id: extract + run: | + COMMIT_MSG="${{ github.event.head_commit.message }}" + # Only tag versions on main branch + if [ "${{ github.ref }}" = "refs/heads/main" ] && [[ "$COMMIT_MSG" =~ ^(v[0-9]+\.[0-9]+\.[0-9]+): ]]; then + VERSION="${BASH_REMATCH[1]}" + echo "version=${VERSION}" >> $GITHUB_OUTPUT + echo "is_release=true" >> $GITHUB_OUTPUT + echo "✅ Detected release commit: ${VERSION}" + else + echo "version=" >> $GITHUB_OUTPUT + echo "is_release=false" >> $GITHUB_OUTPUT + echo "ℹ️ Not a release commit" + fi + # Build AMD64 images and push to ECR immediately (+ GHCR for main) build-amd64: name: Build AMD64 - needs: test-build + needs: [test-build, detect-version] if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/staging') runs-on: blacksmith-8vcpu-ubuntu-2404 permissions: @@ -93,6 +118,14 @@ jobs: GHCR_AMD64="${GHCR_IMAGE}:latest-amd64" GHCR_SHA="${GHCR_IMAGE}:${{ github.sha }}-amd64" TAGS="${TAGS},$GHCR_AMD64,$GHCR_SHA" + + # Add version tag if this is a release commit + if [ "${{ needs.detect-version.outputs.is_release }}" = "true" ]; then + VERSION="${{ needs.detect-version.outputs.version }}" + GHCR_VERSION="${GHCR_IMAGE}:${VERSION}-amd64" + TAGS="${TAGS},$GHCR_VERSION" + echo "📦 Adding version tag: ${VERSION}-amd64" + fi fi echo "tags=${TAGS}" >> $GITHUB_OUTPUT @@ -111,7 +144,7 @@ jobs: # Build ARM64 images for GHCR (main branch only, runs in parallel) build-ghcr-arm64: name: Build ARM64 (GHCR Only) - needs: test-build + needs: [test-build, detect-version] runs-on: blacksmith-8vcpu-ubuntu-2404-arm if: github.event_name == 'push' && github.ref == 'refs/heads/main' permissions: @@ -146,7 +179,16 @@ jobs: id: meta run: | IMAGE="${{ matrix.image }}" - echo "tags=${IMAGE}:latest-arm64,${IMAGE}:${{ github.sha }}-arm64" >> $GITHUB_OUTPUT + TAGS="${IMAGE}:latest-arm64,${IMAGE}:${{ github.sha }}-arm64" + + # Add version tag if this is a release commit + if [ "${{ needs.detect-version.outputs.is_release }}" = "true" ]; then + VERSION="${{ needs.detect-version.outputs.version }}" + TAGS="${TAGS},${IMAGE}:${VERSION}-arm64" + echo "📦 Adding version tag: ${VERSION}-arm64" + fi + + echo "tags=${TAGS}" >> $GITHUB_OUTPUT - name: Build and push ARM64 to GHCR uses: useblacksmith/build-push-action@v2 @@ -162,8 +204,8 @@ jobs: # Create GHCR multi-arch manifests (only for main, after both builds) create-ghcr-manifests: name: Create GHCR Manifests - runs-on: blacksmith-8vcpu-ubuntu-2404 - needs: [build-amd64, build-ghcr-arm64] + runs-on: blacksmith-2vcpu-ubuntu-2404 + needs: [build-amd64, build-ghcr-arm64, detect-version] if: github.event_name == 'push' && github.ref == 'refs/heads/main' permissions: packages: write @@ -198,6 +240,16 @@ jobs: "${IMAGE_BASE}:${{ github.sha }}-arm64" docker manifest push "${IMAGE_BASE}:${{ github.sha }}" + # Create version manifest if this is a release commit + if [ "${{ needs.detect-version.outputs.is_release }}" = "true" ]; then + VERSION="${{ needs.detect-version.outputs.version }}" + echo "📦 Creating version manifest: ${VERSION}" + docker manifest create "${IMAGE_BASE}:${VERSION}" \ + "${IMAGE_BASE}:${VERSION}-amd64" \ + "${IMAGE_BASE}:${VERSION}-arm64" + docker manifest push "${IMAGE_BASE}:${VERSION}" + fi + # Check if docs changed check-docs-changes: name: Check Docs Changes diff --git a/docker/app.Dockerfile b/docker/app.Dockerfile index c954e7e49..8f5b07910 100644 --- a/docker/app.Dockerfile +++ b/docker/app.Dockerfile @@ -10,16 +10,15 @@ FROM base AS deps RUN apk add --no-cache libc6-compat WORKDIR /app -# Install turbo globally (cached separately, changes infrequently) -RUN bun install -g turbo - COPY package.json bun.lock turbo.json ./ RUN mkdir -p apps packages/db COPY apps/sim/package.json ./apps/sim/package.json COPY packages/db/package.json ./packages/db/package.json -# Install dependencies (this layer will be cached if package files don't change) -RUN bun install --omit dev --ignore-scripts +# Install turbo globally and dependencies with cache mount for faster builds +RUN --mount=type=cache,id=bun-cache,target=/root/.bun/install/cache \ + bun install -g turbo && \ + bun install --frozen-lockfile --omit dev --ignore-scripts # ======================================== # Builder Stage: Build the Application @@ -27,8 +26,9 @@ RUN bun install --omit dev --ignore-scripts FROM base AS builder WORKDIR /app -# Install turbo globally (cached separately, changes infrequently) -RUN bun install -g turbo +# Install turbo globally (cached for fast reinstall) +RUN --mount=type=cache,id=bun-cache,target=/root/.bun/install/cache \ + bun install -g turbo # Copy node_modules from deps stage (cached if dependencies don't change) COPY --from=deps /app/node_modules ./node_modules @@ -50,7 +50,8 @@ COPY packages ./packages # Required for standalone nextjs build WORKDIR /app/apps/sim -RUN bun install sharp +RUN --mount=type=cache,id=bun-cache,target=/root/.bun/install/cache \ + bun install sharp ENV NEXT_TELEMETRY_DISABLED=1 \ VERCEL_TELEMETRY_DISABLED=1 \ diff --git a/docker/db.Dockerfile b/docker/db.Dockerfile index e1ff537af..d6b824dcc 100644 --- a/docker/db.Dockerfile +++ b/docker/db.Dockerfile @@ -14,8 +14,9 @@ COPY package.json bun.lock turbo.json ./ RUN mkdir -p packages/db COPY packages/db/package.json ./packages/db/package.json -# Install dependencies (this layer will be cached if package files don't change) -RUN bun install --ignore-scripts +# Install dependencies with cache mount for faster builds +RUN --mount=type=cache,id=bun-cache,target=/root/.bun/install/cache \ + bun install --frozen-lockfile --ignore-scripts # ======================================== # Runner Stage: Production Environment diff --git a/docker/realtime.Dockerfile b/docker/realtime.Dockerfile index 03b9ff4ac..f69f042a1 100644 --- a/docker/realtime.Dockerfile +++ b/docker/realtime.Dockerfile @@ -10,16 +10,14 @@ FROM base AS deps RUN apk add --no-cache libc6-compat WORKDIR /app -# Install turbo globally (cached separately, changes infrequently) -RUN bun install -g turbo - COPY package.json bun.lock turbo.json ./ RUN mkdir -p apps packages/db COPY apps/sim/package.json ./apps/sim/package.json COPY packages/db/package.json ./packages/db/package.json -# Install dependencies (this layer will be cached if package files don't change) -RUN bun install --omit dev --ignore-scripts +# Install dependencies with cache mount for faster builds +RUN --mount=type=cache,id=bun-cache,target=/root/.bun/install/cache \ + bun install --frozen-lockfile --omit dev --ignore-scripts # ======================================== # Builder Stage: Prepare source code