deploy.yml•5.36 kB
name: CD Pipeline
on:
push:
branches: [ main, develop ]
release:
types: [published]
workflow_dispatch:
inputs:
environment:
description: "Target environment (dev|staging|prod)"
required: true
type: choice
options:
- dev
- staging
- prod
permissions:
contents: read
packages: write
deployments: write
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
quality_gates:
name: Quality Gates
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Cache cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Format Check
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --workspace --all-targets --all-features -- -D warnings
- name: Unit Tests
run: cargo test --workspace --all-features --verbose
- name: Install cargo-audit
uses: taiki-e/install-action@v2
with:
tool: cargo-audit
- name: Security Audit
run: cargo audit --deny warnings
build_and_push:
name: Build and Push Image
runs-on: ubuntu-latest
needs: quality_gates
outputs:
image_ref: ${{ steps.meta.outputs.image_ref }}
image_tag: ${{ steps.meta.outputs.image_tag }}
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Compute Image Tag
id: meta
run: |
if [[ "${{ github.event_name }}" == "release" ]]; then
TAG="${{ github.event.release.tag_name }}"
elif [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
# allow manual override via run ID to avoid collisions
TAG="manual-${GITHUB_RUN_ID}"
else
TAG="${GITHUB_SHA::12}"
fi
echo "image_tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "image_ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${TAG}" >> "$GITHUB_OUTPUT"
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
file: ./Dockerfile
push: true
platforms: linux/amd64,linux/arm64
tags: |
${{ steps.meta.outputs.image_ref }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Trivy Image Scan
uses: aquasecurity/trivy-action@0.33.1
with:
image-ref: ${{ steps.meta.outputs.image_ref }}
format: table
exit-code: '1'
vuln-type: 'os,library'
severity: 'CRITICAL,HIGH'
deploy_dev:
name: Deploy Dev
if: github.event_name == 'push' && github.ref == 'refs/heads/develop' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'dev')
runs-on: ubuntu-latest
needs: build_and_push
environment:
name: dev
concurrency:
group: deploy-dev
cancel-in-progress: false
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup kubectl
uses: azure/setup-kubectl@v4
- name: Deploy to Dev
env:
KUBECONFIG_CONTENT: ${{ secrets.DEV_KUBECONFIG }}
run: |
bash scripts/deploy_k8s.sh dev ${{ needs.build_and_push.outputs.image_ref }} codegraph-dev
deploy_staging:
name: Deploy Staging
if: github.event_name == 'push' && github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'staging')
runs-on: ubuntu-latest
needs: build_and_push
environment:
name: staging
concurrency:
group: deploy-staging
cancel-in-progress: false
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup kubectl
uses: azure/setup-kubectl@v4
- name: Deploy to Staging
env:
KUBECONFIG_CONTENT: ${{ secrets.STAGING_KUBECONFIG }}
run: |
bash scripts/deploy_k8s.sh staging ${{ needs.build_and_push.outputs.image_ref }} codegraph-staging
deploy_prod:
name: Deploy Production
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.environment == 'prod')
runs-on: ubuntu-latest
needs: build_and_push
environment:
name: production
concurrency:
group: deploy-production
cancel-in-progress: false
steps:
- name: Checkout
uses: actions/checkout@v5
- name: Setup kubectl
uses: azure/setup-kubectl@v4
- name: Deploy to Production
env:
KUBECONFIG_CONTENT: ${{ secrets.PROD_KUBECONFIG }}
run: |
bash scripts/deploy_k8s.sh prod ${{ needs.build_and_push.outputs.image_ref }} codegraph-prod