.github/workflows/cd.yml #53
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: CD | |
| on: | |
| workflow_run: | |
| workflows: ["CI"] | |
| types: | |
| - completed | |
| branches: [main] | |
| paths: | |
| - ".github/workflows/cd.yml" | |
| - "api/**" | |
| workflow_dispatch: | |
| env: | |
| REGISTRY_GHCR: ghcr.io | |
| IMAGE_NAME: flashot-api | |
| jobs: | |
| check-ci: | |
| runs-on: ubuntu-latest | |
| if: github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' | |
| outputs: | |
| should_deploy: ${{ steps.check.outputs.should_deploy }} | |
| steps: | |
| - name: 📋 Check CI status | |
| id: check | |
| run: | | |
| if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | |
| echo "should_deploy=true" >> $GITHUB_OUTPUT | |
| echo "✅ Manual deployment triggered" | |
| elif [[ "${{ github.event.workflow_run.conclusion }}" == "success" ]]; then | |
| echo "should_deploy=true" >> $GITHUB_OUTPUT | |
| echo "✅ CI workflow completed successfully" | |
| else | |
| echo "should_deploy=false" >> $GITHUB_OUTPUT | |
| echo "❌ CI workflow failed, skipping deployment" | |
| fi | |
| build-and-push: | |
| needs: check-ci | |
| runs-on: ubuntu-latest | |
| if: needs.check-ci.outputs.should_deploy == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| attestations: write | |
| id-token: write | |
| steps: | |
| - name: 📥 Checkout repository | |
| uses: actions/checkout@v4 | |
| - 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_GHCR }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GHCR_TOKEN }} | |
| - name: 📝 Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: | | |
| ${{ env.REGISTRY_GHCR }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=ref,event=branch | |
| type=sha,prefix={{branch}}- | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| - name: 🏗️ Build and push Docker image | |
| id: push | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: ./api | |
| file: ./api/Dockerfile | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| platforms: linux/amd64,linux/arm64 | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| build-args: | | |
| BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} | |
| VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }} | |
| REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} | |
| - name: 🛡️ Generate artifact attestation for GHCR | |
| uses: actions/attest-build-provenance@v1 | |
| with: | |
| subject-name: ${{ env.REGISTRY_GHCR }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }} | |
| subject-digest: ${{ steps.push.outputs.digest }} | |
| push-to-registry: true | |
| security-scan: | |
| needs: build-and-push | |
| runs-on: ubuntu-latest | |
| permissions: | |
| security-events: write | |
| steps: | |
| - name: 🔍 Run Trivy vulnerability scanner | |
| id: trivy-scan | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| image-ref: ${{ env.REGISTRY_GHCR }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:latest | |
| format: "sarif" | |
| output: "trivy-results.sarif" | |
| continue-on-error: true | |
| - name: 📤 Upload Trivy scan results to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@v3 | |
| if: always() && hashFiles('trivy-results.sarif') != '' | |
| with: | |
| sarif_file: "trivy-results.sarif" | |
| deploy-notification: | |
| needs: [build-and-push, security-scan] | |
| runs-on: ubuntu-latest | |
| if: always() | |
| steps: | |
| - name: 📋 Deployment Status | |
| run: | | |
| if [[ "${{ needs.build-and-push.result }}" == "success" ]]; then | |
| echo "## 🚀 Deployment Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ Docker images successfully built and pushed!" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### 📦 Available Images:" >> $GITHUB_STEP_SUMMARY | |
| echo "- 🐙 **GitHub Container Registry:** \`${{ env.REGISTRY_GHCR }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### 🔧 Usage:" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY | |
| echo "# Pull from GitHub Container Registry" >> $GITHUB_STEP_SUMMARY | |
| echo "docker pull ${{ env.REGISTRY_GHCR }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}:latest" >> $GITHUB_STEP_SUMMARY | |
| echo "\`\`\`" >> $GITHUB_STEP_SUMMARY | |
| echo "✅ Docker images successfully built and pushed!" | |
| echo "🐙 GitHub Container Registry: ${{ env.REGISTRY_GHCR }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}" | |
| else | |
| echo "❌ Deployment failed!" | |
| echo "Build result: ${{ needs.build-and-push.result }}" | |
| echo "Security scan result: ${{ needs.security-scan.result }}" | |
| exit 1 | |
| fi |