name: Docker Build, Push & Security Scan on: push: branches: [main] tags: ['v*'] paths: - 'Dockerfile' - '.dockerignore' - 'package.json' - 'bun.lock*' - '.github/workflows/docker-build.yml' pull_request: paths: - 'Dockerfile' - '.dockerignore' - 'package.json' - 'bun.lock*' - '.github/workflows/docker-build.yml' schedule: - cron: '0 0 * * 0' # Weekly security scan on Sunday at midnight env: REGISTRY: ghcr.io IMAGE: ${{ github.repository }} SHA: ${{ github.event.pull_request.head.sha || github.event.after }} jobs: docker: runs-on: ubuntu-latest permissions: contents: write packages: write security-events: write pull-requests: write steps: - name: Checkout repository uses: actions/checkout@v4 with: ref: ${{ env.SHA }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: driver-opts: network=host - name: Log into registry uses: docker/login-action@v3 if: github.event_name != 'pull_request' with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} # Login to Docker Hub for Docker Scout (optional - provides better vulnerability data) # Add DOCKERHUB_USERNAME and DOCKERHUB_TOKEN secrets to enable this - name: Log into Docker Hub uses: docker/login-action@v3 continue-on-error: true with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} # Extract version from tag if present - name: Extract version from tag id: tag_version run: | if [[ $GITHUB_REF == refs/tags/v* ]]; then echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT echo "Using version tag: ${GITHUB_REF#refs/tags/}" else echo "VERSION=latest" >> $GITHUB_OUTPUT echo "No version tag, using 'latest'" fi # Extract metadata for Docker - name: Extract Docker metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE }} labels: | org.opencontainers.image.revision=${{ env.SHA }} tags: | type=edge,branch=$repo.default_branch type=semver,pattern=v{{version}} type=sha,prefix=,suffix=,format=short type=raw,value=latest,enable={{is_default_branch}} type=raw,value=${{ steps.tag_version.outputs.VERSION }} # Build and push Docker image - name: Build and push Docker image id: build-and-push uses: docker/build-push-action@v5 with: context: . platforms: ${{ github.event_name == 'pull_request' && 'linux/amd64' || 'linux/amd64,linux/arm64' }} push: ${{ github.event_name != 'pull_request' }} load: ${{ github.event_name == 'pull_request' }} tags: ${{ github.event_name == 'pull_request' && 'gitea-mirror:scan' || steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max # Wait for image to be available in registry - name: Wait for image availability if: github.event_name != 'pull_request' run: | echo "Waiting for image to be available in registry..." sleep 5 # Docker Scout comprehensive security analysis - name: Docker Scout - Vulnerability Analysis & Recommendations uses: docker/scout-action@v1 if: github.event_name != 'pull_request' with: command: cves,recommendations image: ${{ env.REGISTRY }}/${{ env.IMAGE }}:latest sarif-file: scout-results.sarif summary: true exit-code: false only-severities: critical,high write-comment: true github-token: ${{ secrets.GITHUB_TOKEN }} # Docker Scout for Pull Requests (using local image) - name: Docker Scout - Vulnerability Analysis (PR) uses: docker/scout-action@v1 if: github.event_name == 'pull_request' with: command: cves,recommendations image: local://gitea-mirror:scan sarif-file: scout-results.sarif summary: true exit-code: false only-severities: critical,high write-comment: true github-token: ${{ secrets.GITHUB_TOKEN }} # Compare to latest for PRs and pushes - name: Docker Scout - Compare to Latest uses: docker/scout-action@v1 if: github.event_name == 'pull_request' with: command: compare image: local://gitea-mirror:scan to: ${{ env.REGISTRY }}/${{ env.IMAGE }}:latest ignore-unchanged: true only-severities: critical,high write-comment: true github-token: ${{ secrets.GITHUB_TOKEN }} # Upload security scan results to GitHub Security tab - name: Upload Docker Scout scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@v3 if: always() continue-on-error: true with: sarif_file: scout-results.sarif