v2.6.8 - ESLint 10 stabilization and TS 6.0 compatibility #291
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build and Push Docker Images | |
| on: | |
| push: | |
| tags: ["v*"] | |
| pull_request: | |
| branches: [main] | |
| env: | |
| REGISTRY: docker.io | |
| IMAGE_NAME: writenotenow/d1-manager | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| permissions: | |
| contents: read | |
| packages: write | |
| security-events: write # For security scanning | |
| pull-requests: write # For PR comments | |
| id-token: write # For supply chain attestations | |
| attestations: write # For generating attestations | |
| jobs: | |
| # Prerequisite: Lint and Build Verification | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: "24.x" | |
| cache: "npm" | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run ESLint | |
| run: npm run lint | |
| - name: Build frontend | |
| run: npm run build | |
| - name: Build worker | |
| run: npx wrangler deploy --dry-run | |
| # Prerequisite: CodeQL Security Analysis | |
| codeql: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| actions: read | |
| contents: read | |
| security-events: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Initialize CodeQL | |
| uses: github/codeql-action/init@v4 | |
| with: | |
| languages: javascript-typescript | |
| - name: Autobuild | |
| uses: github/codeql-action/autobuild@v4 | |
| - name: Perform CodeQL Analysis | |
| uses: github/codeql-action/analyze@v4 | |
| with: | |
| upload: always | |
| # Build each platform on native architecture (avoids QEMU emulation issues) | |
| # Images are built but NOT pushed yet - push happens after security-scan passes | |
| build-platform: | |
| needs: [lint, codeql] | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: linux/amd64 | |
| runner: ubuntu-latest | |
| - platform: linux/arm64 | |
| runner: ubuntu-24.04-arm | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| attestations: write | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Log in to Docker Hub | |
| if: github.event_name != 'pull_request' | |
| uses: docker/login-action@v4 | |
| continue-on-error: true | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Read version from package.json | |
| id: version | |
| run: | | |
| VERSION=$(jq -r '.version // empty' package.json || echo "") | |
| if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then | |
| echo "Error: Failed to extract version from package.json" >&2 | |
| exit 1 | |
| fi | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Detected version: $VERSION" | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v6 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| flavor: | | |
| latest=false | |
| suffix=-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }} | |
| tags: | | |
| type=sha,prefix=sha-,format=short | |
| - name: Build platform image (no push - security scan first) | |
| id: build | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| file: Dockerfile | |
| platforms: ${{ matrix.platform }} | |
| push: false | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha,scope=${{ matrix.platform }} | |
| cache-to: type=gha,scope=${{ matrix.platform }},mode=max | |
| provenance: mode=max | |
| sbom: true | |
| # Security scan with Docker Scout (blocks on critical/high fixable vulns) | |
| security-scan: | |
| runs-on: ubuntu-latest | |
| needs: build-platform | |
| if: github.event_name != 'pull_request' | |
| permissions: | |
| contents: read | |
| security-events: write | |
| pull-requests: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Build image for scanning | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| file: Dockerfile | |
| platforms: linux/amd64 | |
| push: false | |
| load: true | |
| tags: local-scan:latest | |
| cache-from: type=gha,scope=linux/amd64 | |
| - name: Docker Scout CVE Scan | |
| uses: docker/scout-action@v1 | |
| with: | |
| command: cves | |
| image: local://local-scan:latest | |
| exit-code: true | |
| only-severities: critical,high | |
| only-fixed: true | |
| sarif-file: scout-results.sarif | |
| - name: Upload Scout results to GitHub Security | |
| uses: github/codeql-action/upload-sarif@v4 | |
| if: always() | |
| with: | |
| sarif_file: scout-results.sarif | |
| # Push platform images AFTER security scan passes | |
| # This job gates Docker Hub publishing on security verification | |
| push-platform: | |
| needs: [build-platform, security-scan] | |
| if: github.event_name != 'pull_request' | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: linux/amd64 | |
| runner: ubuntu-latest | |
| - platform: linux/arm64 | |
| runner: ubuntu-24.04-arm | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| attestations: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v6 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| flavor: | | |
| latest=false | |
| suffix=-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }} | |
| tags: | | |
| type=sha,prefix=sha-,format=short | |
| - name: Build and push platform image (from cache) | |
| id: build | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| file: Dockerfile | |
| platforms: ${{ matrix.platform }} | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha,scope=${{ matrix.platform }} | |
| provenance: mode=max | |
| sbom: true | |
| - name: Export digest | |
| run: | | |
| mkdir -p /tmp/digests | |
| digest="${{ steps.build.outputs.digest }}" | |
| touch "/tmp/digests/${digest#sha256:}" | |
| - name: Upload digest | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: digests-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }} | |
| path: /tmp/digests/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| # Merge platform images into multi-arch manifest | |
| merge-and-push: | |
| runs-on: ubuntu-latest | |
| needs: [push-platform] | |
| if: github.event_name != 'pull_request' | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| attestations: write | |
| deployments: write | |
| environment: | |
| name: ${{ startsWith(github.ref, 'refs/tags/v') && 'production' || '' }} | |
| url: https://hub.docker.com/r/writenotenow/d1-manager | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Download digests | |
| uses: actions/download-artifact@v7 | |
| with: | |
| path: /tmp/digests | |
| pattern: digests-* | |
| merge-multiple: true | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Read version | |
| id: version | |
| run: | | |
| VERSION=$(jq -r '.version // empty' package.json || echo "") | |
| if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then | |
| echo "Error: Failed to extract version from package.json" >&2 | |
| exit 1 | |
| fi | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| - name: Extract metadata for manifest | |
| id: meta | |
| uses: docker/metadata-action@v6 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| flavor: | | |
| latest=auto | |
| tags: | | |
| type=semver,pattern=v{{version}} | |
| type=raw,value=v${{ steps.version.outputs.version }},enable=${{ github.event_name != 'pull_request' }} | |
| type=raw,value=latest,enable=${{ github.event_name != 'pull_request' }} | |
| type=sha,prefix=sha-,format=short | |
| - name: Create and push manifest | |
| working-directory: /tmp/digests | |
| run: | | |
| docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ | |
| $(printf '${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@sha256:%s ' *) | |
| - name: Inspect manifest | |
| run: | | |
| docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }} | |
| # Update Docker Hub description | |
| - name: Update Docker Hub Description | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| uses: peter-evans/dockerhub-description@v5 | |
| continue-on-error: true | |
| timeout-minutes: 5 | |
| with: | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| repository: ${{ env.IMAGE_NAME }} | |
| readme-filepath: ./DOCKER_README.md | |
| short-description: "Cloudflare D1 Manager with SQL Console, Drizzle, Visual Schema/ER tools, Scheduled Backups." | |
| - name: Deployment Summary | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| run: | | |
| echo "✅ Successfully published Docker images to production" | |
| echo "🐳 Registry: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" | |
| echo "🏷️ Tags: ${{ steps.meta.outputs.tags }}" | |
| echo "📝 Commit: ${{ github.sha }}" | |
| echo "👤 Published by: ${{ github.actor }}" |