name: Build and Push Server Docker Image on: push: branches: [main, staging] paths: - 'apps/server/**' - 'packages/**' - 'pnpm-lock.yaml' - '.github/workflows/docker-build-server.yml' # Only one build per branch at a time, queue others concurrency: group: docker-build-${{ github.ref }} cancel-in-progress: false # Don't cancel, queue instead for deployments env: REGISTRY: ghcr.io IMAGE_NAME: buster-so/buster-server jobs: build-and-push: runs-on: blacksmith-8vcpu-ubuntu-2404 permissions: contents: read packages: write steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install pnpm uses: pnpm/action-setup@v2 with: version: 9.15.0 - name: Setup Node.js uses: useblacksmith/setup-node@v5 with: node-version: 22 cache: 'pnpm' - name: Install bun run: npm install -g bun@1.2.15 - name: Mount Turbo cache sticky disk uses: useblacksmith/stickydisk@v1 with: key: ${{ github.repository }}-turbo-cache-${{ github.ref_name }} path: ./.turbo - name: Mount Docker buildkit sticky disk uses: useblacksmith/stickydisk@v1 with: key: ${{ github.repository }}-buildkit-cache-${{ github.ref_name }} path: /tmp/.buildkit-cache - name: Install dependencies run: | echo "๐Ÿ“ฆ Installing dependencies with pnpm..." pnpm install --frozen-lockfile - name: Build with Turbo run: | echo "๐Ÿ”จ Building server with Turbo..." # Build with optimized settings for Docker pnpm turbo run build --filter=@buster-app/server... echo "โœ… Build complete!" env: NODE_ENV: production DOCKER_BUILD: true CI: true TURBO_CACHE_DIR: .turbo TURBO_TELEMETRY_DISABLED: 1 - name: Build server bundle run: | echo "๐Ÿ“ฆ Creating server bundle with bun..." cd apps/server bun build src/index.ts --outdir ./dist --target bun --external pino-pretty ls -la dist/ cd ../.. - name: Prepare production dependencies run: | echo "๐Ÿงน Preparing production-only dependencies..." # Create a temporary directory for production deps mkdir -p /tmp/prod-deps/apps/server cp package.json pnpm-lock.yaml pnpm-workspace.yaml /tmp/prod-deps/ cp -r packages /tmp/prod-deps/ cp apps/server/package.json /tmp/prod-deps/apps/server/ # Install production dependencies only cd /tmp/prod-deps pnpm install --frozen-lockfile --prod --no-optional # Copy back to workspace cd - mkdir -p docker-context cp -r /tmp/prod-deps/node_modules docker-context/ cp -r apps/server/dist docker-context/ cp apps/server/package.json docker-context/ - name: Set up Docker Builder uses: useblacksmith/setup-docker-builder@v1 - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata and determine tags id: meta run: | SHA_SHORT=$(git rev-parse --short HEAD) echo "sha_short=${SHA_SHORT}" >> $GITHUB_OUTPUT if [[ "${{ github.ref_name }}" == "main" ]]; then # For main: use commit SHA and latest echo "tags=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${SHA_SHORT},${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> $GITHUB_OUTPUT elif [[ "${{ github.ref_name }}" == "staging" ]]; then # For staging: use staging-SHA and staging echo "tags=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:staging-${SHA_SHORT},${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:staging" >> $GITHUB_OUTPUT fi # Set build timestamp echo "timestamp=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT - name: Build and push Docker image uses: useblacksmith/build-push-action@v2 with: context: ./docker-context file: ./apps/server/Dockerfile.prebuilt push: true tags: ${{ steps.meta.outputs.tags }} labels: | org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.revision=${{ github.sha }} org.opencontainers.image.created=${{ steps.meta.outputs.timestamp }} org.opencontainers.image.ref.name=${{ github.ref_name }} build-args: | COMMIT_SHA=${{ steps.meta.outputs.sha_short }} BUILD_DATE=${{ steps.meta.outputs.timestamp }} platforms: linux/amd64 cache-from: type=local,src=/tmp/.buildkit-cache cache-to: type=local,dest=/tmp/.buildkit-cache,mode=max - name: Output image details run: | echo "โœ… Docker image built and pushed successfully!" echo "๐Ÿ“ฆ Image tags:" echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n' | sed 's/^/ - /' echo "" echo "๐Ÿ”ง To use in Porter:" if [[ "${{ github.ref_name }}" == "main" ]]; then echo " Image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.sha_short }}" else echo " Image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:staging-${{ steps.meta.outputs.sha_short }}" fi