Deploy image #36
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: Deploy image | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| image_label: | |
| description: "Image label/tag to deploy (e.g. staging, production, sandbox, 2025.11.05.0001 or branch tag)" | |
| type: string | |
| required: true | |
| environment: | |
| description: "Target environment" | |
| type: choice | |
| required: true | |
| options: | |
| - staging | |
| - sandbox | |
| - production | |
| permissions: | |
| id-token: write | |
| contents: read | |
| env: | |
| AWS_REGION: us-east-1 | |
| EKS_CLUSTER: ce-registry-eks | |
| ECR_URI: 996810415034.dkr.ecr.us-east-1.amazonaws.com/registry | |
| jobs: | |
| deploy: | |
| if: ${{ github.repository_owner == 'CredentialEngine' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Configure AWS credentials | |
| uses: aws-actions/configure-aws-credentials@v4 | |
| with: | |
| role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT }}:role/github-oidc-widget | |
| aws-region: ${{ env.AWS_REGION }} | |
| - name: Install kubectl | |
| uses: azure/setup-kubectl@v4 | |
| with: | |
| version: v1.29.6 | |
| - name: Update kubeconfig | |
| run: | | |
| aws eks update-kubeconfig --name "${{ env.EKS_CLUSTER }}" --region "${{ env.AWS_REGION }}" | |
| - name: Deploy image to selected environment | |
| env: | |
| IMAGE: ${{ env.ECR_URI }}:${{ inputs.image_label }} | |
| run: | | |
| ENV="${{ inputs.environment }}" | |
| case "$ENV" in | |
| staging) NS="credreg-staging" ;; | |
| sandbox) NS="credreg-sandbox" ;; | |
| production) NS="credreg-prod" ;; | |
| *) echo "Unknown environment: $ENV" >&2; exit 1 ;; | |
| esac | |
| echo "Deploying image $IMAGE to namespace $NS" | |
| kubectl -n "$NS" set image deploy/main-app main-app="$IMAGE" | |
| kubectl -n "$NS" set image deploy/worker-app worker="$IMAGE" | |
| kubectl -n "$NS" rollout status deploy/main-app --timeout=10m | |
| kubectl -n "$NS" rollout status deploy/worker-app --timeout=10m | |
| echo "Forcing rollout restart to ensure pods pick up latest image/config" | |
| kubectl -n "$NS" rollout restart deploy/worker-app | |
| kubectl -n "$NS" rollout restart deploy/main-app | |
| kubectl -n "$NS" rollout status deploy/worker-app --timeout=10m | |
| kubectl -n "$NS" rollout status deploy/main-app --timeout=10m | |
| - name: Run DB migrations | |
| env: | |
| IMAGE: ${{ inputs.image }} | |
| run: | | |
| set -euo pipefail | |
| ENV="${{ inputs.environment }}" | |
| case "$ENV" in | |
| staging) | |
| NS="credreg-staging" | |
| MANIFEST="terraform/environments/eks/k8s-manifests-staging/db-migrate-job.yaml" | |
| ;; | |
| sandbox) | |
| NS="credreg-sandbox" | |
| MANIFEST="terraform/environments/eks/k8s-manifests-sandbox/db-migrate-job.yaml" | |
| ;; | |
| production) | |
| NS="credreg-prod" | |
| MANIFEST="terraform/environments/eks/k8s-manifests-prod/db-migrate-job.yaml" | |
| ;; | |
| *) | |
| echo "Unknown environment: $ENV" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| if [ ! -f "$MANIFEST" ]; then | |
| echo "Migration manifest $MANIFEST not found; skipping" | |
| exit 0 | |
| fi | |
| IMAGE_VALUE="${IMAGE:-}" | |
| if [ -z "$IMAGE_VALUE" ]; then | |
| echo "IMAGE env not set; reading current image from deploy/main-app" | |
| IMAGE_VALUE=$(kubectl -n "$NS" get deploy/main-app -o jsonpath='{.spec.template.spec.containers[?(@.name=="main-app")].image}') | |
| fi | |
| if [ -z "$IMAGE_VALUE" ]; then | |
| echo "Unable to determine image for migrations" >&2 | |
| exit 1 | |
| fi | |
| echo "Launching DB migration job in $NS with image $IMAGE_VALUE" | |
| JOB_NAME=$( | |
| sed -e "s#namespace: .*#namespace: $NS#" \ | |
| -e "s#image: .*#image: $IMAGE_VALUE#" "$MANIFEST" | | |
| kubectl -n "$NS" create -f - -o name | sed 's|job.batch/||' | |
| ) | |
| kubectl -n "$NS" wait --for=condition=complete "job/$JOB_NAME" --timeout=10m | |
| kubectl -n "$NS" logs -f "job/$JOB_NAME" --all-containers=true | |
| - name: Notify Slack (deploy) | |
| if: always() | |
| env: | |
| SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} | |
| REPO: ${{ github.repository }} | |
| RUN_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} | |
| ENVIRONMENT: ${{ inputs.environment }} | |
| IMAGE: ${{ env.ECR_URI }}:${{ inputs.image_label }} | |
| run: | | |
| if [ -z "${SLACK_WEBHOOK_URL}" ]; then | |
| echo "SLACK_WEBHOOK_URL not set; skipping notification"; | |
| exit 0; | |
| fi | |
| STATUS="${{ job.status }}"; EMOJI=✅; [ "$STATUS" = "failure" ] && EMOJI=❌ | |
| MSG="$EMOJI Deploy ${STATUS} for ${REPO} (env: ${ENVIRONMENT}). Image: ${IMAGE}. ${RUN_URL}" | |
| payload=$(jq -nc --arg text "$MSG" '{text:$text}') | |
| curl -sS -X POST -H 'Content-type: application/json' --data "$payload" "$SLACK_WEBHOOK_URL" || true |