name: Build and Deploy on: push: branches: [main] workflow_dispatch: inputs: environment: description: 'Deployment environment' required: true default: 'production' type: choice options: - production - staging env: REGISTRY: ${{ vars.REGISTRY || format('{0}', github.repository_owner) }} IMAGE_NAME: ${{ github.repository }} IMAGE_TAG: ${{ github.sha }} jobs: build: runs-on: docker container: image: catthehacker/ubuntu:act-latest steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: | type=sha,prefix= type=raw,value=latest,enable={{is_default_branch}} - name: Build and push uses: docker/build-push-action@v5 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:cache cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:cache,mode=max - name: Output image digest run: echo "IMAGE_DIGEST=${{ steps.meta.outputs.tags }}" >> $GITHUB_ENV security-scan: runs-on: docker needs: build container: image: aquasec/trivy:0.61.1 steps: - name: Scan image run: | trivy image --exit-code 1 \ --severity HIGH,CRITICAL \ --username "${{ github.actor }}" \ --password "${{ secrets.REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \ "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ env.IMAGE_DIGEST }}" deploy: runs-on: docker needs: [build, security-scan] if: github.ref == 'refs/heads/main' container: image: python:3.12-alpine env: DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} DEPLOY_USER: ${{ secrets.DEPLOY_USER || 'deploy' }} DEPLOY_PORT: ${{ secrets.DEPLOY_PORT || '22' }} DEPLOY_PATH: ${{ secrets.DEPLOY_PATH || '/opt/vault-dash' }} DEPLOY_SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_PRIVATE_KEY }} APP_ENV: production APP_NAME: Vault Dashboard APP_PORT: "8000" APP_BIND_ADDRESS: "127.0.0.1" DEFAULT_SYMBOL: GLD CACHE_TTL: "300" WEBSOCKET_INTERVAL_SECONDS: "5" NICEGUI_MOUNT_PATH: / NICEGUI_STORAGE_SECRET: ${{ secrets.NICEGUI_STORAGE_SECRET }} CORS_ORIGINS: ${{ secrets.CORS_ORIGINS || '*' }} REGISTRY: ${{ env.REGISTRY }} IMAGE_TAG: ${{ env.IMAGE_TAG }} steps: - uses: actions/checkout@v4 - name: Install dependencies run: | apk add --no-cache bash openssh-client curl docker-cli docker-cli-compose mkdir -p ~/.ssh chmod 700 ~/.ssh - name: Setup SSH key run: | printf '%s' "$DEPLOY_SSH_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 - name: Deploy run: | test -n "$DEPLOY_HOST" || (echo "DEPLOY_HOST must be set" && exit 1) bash scripts/deploy.sh - name: Health check if: ${{ secrets.EXTERNAL_HEALTHCHECK_URL != '' }} run: | python scripts/healthcheck.py "${{ secrets.EXTERNAL_HEALTHCHECK_URL }}" \ --timeout 120 \ --expect-status ok \ --expect-environment production