mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 12:04:02 +00:00
feat(cd): complete environment support for dev/prod deployments
- Add workflow_dispatch inputs for manual environment selection - Add detect-environment job to centralize environment detection - Support both auto-trigger (branch-based) and manual deployment - Use environment-specific secrets (DATABASE_URL vs DATABASE_URL_TEST) - Dynamic Cloud Run service names based on environment - Update concurrency group to use environment for manual triggers
This commit is contained in:
109
.github/workflows/cd.yml
vendored
109
.github/workflows/cd.yml
vendored
@@ -10,21 +10,93 @@ on:
|
|||||||
- main
|
- main
|
||||||
- dev
|
- dev
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
environment:
|
||||||
|
description: 'Target environment'
|
||||||
|
required: true
|
||||||
|
default: 'dev'
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- dev
|
||||||
|
- prod
|
||||||
|
ref:
|
||||||
|
description: 'Git ref to deploy (branch, tag, or SHA)'
|
||||||
|
required: true
|
||||||
|
default: 'dev'
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
id-token: write
|
id-token: write
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: cd-${{ github.ref_name }}
|
group: cd-${{ github.event_name == 'workflow_dispatch' && inputs.environment || github.ref_name }}
|
||||||
cancel-in-progress: false
|
cancel-in-progress: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
detect-environment:
|
||||||
|
name: Detect environment
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
target_env: ${{ steps.detect.outputs.target_env }}
|
||||||
|
github_environment: ${{ steps.detect.outputs.github_environment }}
|
||||||
|
db_schema: ${{ steps.detect.outputs.db_schema }}
|
||||||
|
service_suffix: ${{ steps.detect.outputs.service_suffix }}
|
||||||
|
bot_secret_id: ${{ steps.detect.outputs.bot_secret_id }}
|
||||||
|
db_secret_name: ${{ steps.detect.outputs.db_secret_name }}
|
||||||
|
ref: ${{ steps.detect.outputs.ref }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Determine target environment
|
||||||
|
id: detect
|
||||||
|
run: |
|
||||||
|
# Determine environment from input (manual) or branch (auto)
|
||||||
|
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||||
|
target_env="${{ inputs.environment }}"
|
||||||
|
ref="${{ inputs.ref }}"
|
||||||
|
else
|
||||||
|
# Auto-detect from branch
|
||||||
|
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
|
||||||
|
target_env="prod"
|
||||||
|
else
|
||||||
|
target_env="dev"
|
||||||
|
fi
|
||||||
|
ref="${{ github.event.workflow_run.head_sha }}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set derived values
|
||||||
|
if [[ "$target_env" == "prod" ]]; then
|
||||||
|
github_environment="Production"
|
||||||
|
db_schema="public"
|
||||||
|
service_suffix="prod"
|
||||||
|
bot_secret_id="telegram-bot-token"
|
||||||
|
db_secret_name="DATABASE_URL"
|
||||||
|
else
|
||||||
|
github_environment="Development"
|
||||||
|
db_schema="test"
|
||||||
|
service_suffix="dev"
|
||||||
|
bot_secret_id="telegram-bot-token-test"
|
||||||
|
db_secret_name="DATABASE_URL_TEST"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "target_env=$target_env" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "github_environment=$github_environment" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "db_schema=$db_schema" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "service_suffix=$service_suffix" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "bot_secret_id=$bot_secret_id" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "db_secret_name=$db_secret_name" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "ref=$ref" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
echo "Target environment: $target_env"
|
||||||
|
echo "GitHub Environment: $github_environment"
|
||||||
|
echo "DB Schema: $db_schema"
|
||||||
|
echo "Service Suffix: $service_suffix"
|
||||||
|
echo "Deploy ref: $ref"
|
||||||
|
|
||||||
check-secrets:
|
check-secrets:
|
||||||
name: Check deploy prerequisites
|
name: Check deploy prerequisites
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
# Select GitHub Environment based on branch
|
needs: detect-environment
|
||||||
environment: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Development' }}
|
environment: ${{ needs.detect-environment.outputs.github_environment }}
|
||||||
outputs:
|
outputs:
|
||||||
eligible_event: ${{ steps.check.outputs.eligible_event }}
|
eligible_event: ${{ steps.check.outputs.eligible_event }}
|
||||||
secrets_ok: ${{ steps.check.outputs.secrets_ok }}
|
secrets_ok: ${{ steps.check.outputs.secrets_ok }}
|
||||||
@@ -37,7 +109,7 @@ jobs:
|
|||||||
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
|
GCP_PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
|
||||||
GCP_WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
|
GCP_WORKLOAD_IDENTITY_PROVIDER: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
|
||||||
GCP_SERVICE_ACCOUNT: ${{ secrets.GCP_SERVICE_ACCOUNT }}
|
GCP_SERVICE_ACCOUNT: ${{ secrets.GCP_SERVICE_ACCOUNT }}
|
||||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
DATABASE_URL: ${{ secrets[needs.detect-environment.outputs.db_secret_name] }}
|
||||||
run: |
|
run: |
|
||||||
eligible_event=false
|
eligible_event=false
|
||||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||||
@@ -63,25 +135,22 @@ jobs:
|
|||||||
deploy:
|
deploy:
|
||||||
name: Deploy Cloud Run
|
name: Deploy Cloud Run
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: check-secrets
|
needs: [detect-environment, check-secrets]
|
||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
if: ${{ needs.check-secrets.outputs.eligible_event == 'true' && needs.check-secrets.outputs.secrets_ok == 'true' && needs.check-secrets.outputs.db_secret_ok == 'true' }}
|
if: ${{ needs.check-secrets.outputs.eligible_event == 'true' && needs.check-secrets.outputs.secrets_ok == 'true' && needs.check-secrets.outputs.db_secret_ok == 'true' }}
|
||||||
environment: ${{ github.ref == 'refs/heads/main' && 'Production' || 'Development' }}
|
environment: ${{ needs.detect-environment.outputs.github_environment }}
|
||||||
env:
|
env:
|
||||||
GCP_REGION: ${{ vars.GCP_REGION || 'europe-west1' }}
|
GCP_REGION: ${{ vars.GCP_REGION || 'europe-west1' }}
|
||||||
ARTIFACT_REPOSITORY: ${{ vars.ARTIFACT_REPOSITORY || 'household-bot' }}
|
ARTIFACT_REPOSITORY: ${{ vars.ARTIFACT_REPOSITORY || 'household-bot' }}
|
||||||
# Dynamic Service Names based on environment
|
SERVICE_SUFFIX: ${{ needs.detect-environment.outputs.service_suffix }}
|
||||||
# Branch 'main' -> Environment 'prod' -> household-prod-*
|
DB_SCHEMA: ${{ needs.detect-environment.outputs.db_schema }}
|
||||||
# Branch 'dev' -> Environment 'dev' -> household-dev-*
|
BOT_SECRET_ID: ${{ needs.detect-environment.outputs.bot_secret_id }}
|
||||||
CLOUD_RUN_SERVICE_BOT: ${{ github.ref == 'refs/heads/main' && 'household-prod-bot-api' || 'household-dev-bot-api' }}
|
|
||||||
CLOUD_RUN_SERVICE_MINI: ${{ github.ref == 'refs/heads/main' && 'household-prod-mini-app' || 'household-dev-mini-app' }}
|
|
||||||
TELEGRAM_BOT_TOKEN_SECRET_ID: ${{ github.ref == 'refs/heads/main' && 'telegram-bot-token' || 'telegram-bot-token-test' }}
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout deployment ref
|
- name: Checkout deployment ref
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event_name == 'workflow_run' && github.event.workflow_run.head_sha || github.sha }}
|
ref: ${{ needs.detect-environment.outputs.ref }}
|
||||||
|
|
||||||
- name: Setup Bun
|
- name: Setup Bun
|
||||||
uses: oven-sh/setup-bun@v2
|
uses: oven-sh/setup-bun@v2
|
||||||
@@ -99,8 +168,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Run database migrations
|
- name: Run database migrations
|
||||||
env:
|
env:
|
||||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
DATABASE_URL: ${{ secrets[needs.detect-environment.outputs.db_secret_name] }}
|
||||||
DB_SCHEMA: ${{ github.ref == 'refs/heads/main' && 'public' || 'test' }}
|
DB_SCHEMA: ${{ needs.detect-environment.outputs.db_schema }}
|
||||||
run: bun run db:migrate
|
run: bun run db:migrate
|
||||||
|
|
||||||
- name: Setup gcloud
|
- name: Setup gcloud
|
||||||
@@ -111,7 +180,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
set +e
|
set +e
|
||||||
token="$(gcloud secrets versions access latest \
|
token="$(gcloud secrets versions access latest \
|
||||||
--secret "${TELEGRAM_BOT_TOKEN_SECRET_ID}" \
|
--secret "${BOT_SECRET_ID}" \
|
||||||
--project "${{ secrets.GCP_PROJECT_ID }}" 2>/dev/null)"
|
--project "${{ secrets.GCP_PROJECT_ID }}" 2>/dev/null)"
|
||||||
status=$?
|
status=$?
|
||||||
set -e
|
set -e
|
||||||
@@ -154,17 +223,17 @@ jobs:
|
|||||||
|
|
||||||
- name: Deploy bot service
|
- name: Deploy bot service
|
||||||
run: |
|
run: |
|
||||||
gcloud run deploy "${CLOUD_RUN_SERVICE_BOT}" \
|
gcloud run deploy "household-${SERVICE_SUFFIX}-bot-api" \
|
||||||
--image "${{ steps.images.outputs.bot_image }}" \
|
--image "${{ steps.images.outputs.bot_image }}" \
|
||||||
--region "${GCP_REGION}" \
|
--region "${GCP_REGION}" \
|
||||||
--project "${{ secrets.GCP_PROJECT_ID }}" \
|
--project "${{ secrets.GCP_PROJECT_ID }}" \
|
||||||
--set-env-vars "DB_SCHEMA=${{ github.ref == 'refs/heads/main' && 'public' || 'test' }}" \
|
--set-env-vars "DB_SCHEMA=${DB_SCHEMA}" \
|
||||||
--allow-unauthenticated \
|
--allow-unauthenticated \
|
||||||
--quiet
|
--quiet
|
||||||
|
|
||||||
- name: Deploy mini app service
|
- name: Deploy mini app service
|
||||||
run: |
|
run: |
|
||||||
gcloud run deploy "${CLOUD_RUN_SERVICE_MINI}" \
|
gcloud run deploy "household-${SERVICE_SUFFIX}-mini-app" \
|
||||||
--image "${{ steps.images.outputs.mini_image }}" \
|
--image "${{ steps.images.outputs.mini_image }}" \
|
||||||
--region "${GCP_REGION}" \
|
--region "${GCP_REGION}" \
|
||||||
--project "${{ secrets.GCP_PROJECT_ID }}" \
|
--project "${{ secrets.GCP_PROJECT_ID }}" \
|
||||||
@@ -182,7 +251,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
TELEGRAM_BOT_TOKEN: ${{ steps.telegram-token.outputs.token }}
|
TELEGRAM_BOT_TOKEN: ${{ steps.telegram-token.outputs.token }}
|
||||||
run: |
|
run: |
|
||||||
SERVICE_URL=$(gcloud run services describe "${CLOUD_RUN_SERVICE_BOT}" \
|
SERVICE_URL=$(gcloud run services describe "household-${SERVICE_SUFFIX}-bot-api" \
|
||||||
--region "${GCP_REGION}" \
|
--region "${GCP_REGION}" \
|
||||||
--project "${{ secrets.GCP_PROJECT_ID }}" \
|
--project "${{ secrets.GCP_PROJECT_ID }}" \
|
||||||
--format 'value(status.url)')
|
--format 'value(status.url)')
|
||||||
|
|||||||
Reference in New Issue
Block a user