HydroServer GCP Cloud Deployment #73
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: HydroServer GCP Cloud Deployment | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| environment: | |
| description: 'Enter a deployment environment to use.' | |
| type: environment | |
| required: true | |
| action: | |
| description: 'Enter the action you want to perform.' | |
| type: choice | |
| required: true | |
| options: | |
| - Initialize HydroServer Deployment | |
| - Update HydroServer Deployment | |
| - Teardown HydroServer Deployment | |
| release: | |
| description: 'Enter the HydroServer release tag to use.' | |
| type: string | |
| required: false | |
| default: 'latest' | |
| permissions: | |
| contents: write | |
| id-token: write | |
| actions: write | |
| jobs: | |
| check-environment-variables: | |
| runs-on: ubuntu-latest | |
| environment: ${{ github.event.inputs.environment }} | |
| env: | |
| GCP_REGION: ${{ vars.GCP_REGION }} | |
| GCP_PROJECT_ID: ${{ vars.GCP_PROJECT_ID }} | |
| GCP_IDENTITY_PROVIDER: ${{ vars.GCP_IDENTITY_PROVIDER }} | |
| GCP_SERVICE_ACCOUNT: ${{ vars.GCP_SERVICE_ACCOUNT }} | |
| GCP_SSL_CERTIFICATE_NAME: ${{ vars.GCP_SSL_CERTIFICATE_NAME }} | |
| PROXY_BASE_URL: ${{ vars.PROXY_BASE_URL }} | |
| TERRAFORM_BUCKET: ${{ vars.TERRAFORM_BUCKET }} | |
| DATABASE_URL: ${{ secrets.DATABASE_URL }} | |
| steps: | |
| - name: Check Required Environment Variables | |
| run: | | |
| echo "Checking required environment variables..." | |
| required_vars=(GCP_REGION GCP_PROJECT_ID GCP_IDENTITY_PROVIDER GCP_SERVICE_ACCOUNT GCP_SSL_CERTIFICATE_NAME PROXY_BASE_URL TERRAFORM_BUCKET) | |
| for var in "${required_vars[@]}"; do | |
| if [ -z "${!var}" ]; then | |
| echo "Error: Environment variable $var is not defined." | |
| exit 1 | |
| fi | |
| done | |
| initialize-hydroserver: | |
| needs: check-environment-variables | |
| if: github.event.inputs.action == 'Initialize HydroServer Deployment' | |
| runs-on: ubuntu-latest | |
| environment: ${{ github.event.inputs.environment }} | |
| defaults: | |
| run: | |
| working-directory: ./terraform/gcp | |
| steps: | |
| - name: Checkout Ops Repo | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.ref }} | |
| - name: Configure GCP Credentials | |
| uses: google-github-actions/auth@v2 | |
| with: | |
| project_id: ${{ vars.GCP_PROJECT_ID }} | |
| workload_identity_provider: ${{ vars.GCP_IDENTITY_PROVIDER }} | |
| service_account: ${{ vars.GCP_SERVICE_ACCOUNT }} | |
| - name: Setup Terraform | |
| uses: hashicorp/setup-terraform@v1 | |
| - name: Terraform Init | |
| run: | | |
| terraform init \ | |
| -backend-config="impersonate_service_account=${{ vars.GCP_SERVICE_ACCOUNT }}" \ | |
| -backend-config="bucket=${{ vars.TERRAFORM_BUCKET }}" \ | |
| -backend-config="prefix=state/hydroserver_${{ github.event.inputs.environment }}" | |
| - name: Terraform Plan | |
| id: plan | |
| run: | | |
| terraform plan \ | |
| -no-color -input=false \ | |
| -var "instance=${{ github.event.inputs.environment }}" \ | |
| -var "region=${{ vars.GCP_REGION }}" \ | |
| -var "project_id=${{ vars.GCP_PROJECT_ID }}" \ | |
| -var "proxy_base_url=${{ vars.PROXY_BASE_URL }}" \ | |
| -var "ssl_certificate_name=${{ vars.GCP_SSL_CERTIFICATE_NAME }}" \ | |
| -var "database_url=${{ secrets.DATABASE_URL || '' }}" \ | |
| -var "label_key=${{ vars.GCP_LABEL_KEY || 'hydroserver-instance' }}" \ | |
| -var "label_value=${{ vars.GCP_LABEL_VALUE || github.event.inputs.environment }}" | |
| continue-on-error: true | |
| - name: Terraform Plan Status | |
| if: steps.plan.outcome == 'failure' | |
| run: exit 1 | |
| - name: Terraform Apply | |
| run: | | |
| terraform apply \ | |
| -auto-approve -input=false \ | |
| -target=google_artifact_registry_repository.api_repository \ | |
| -var "instance=${{ github.event.inputs.environment }}" \ | |
| -var "region=${{ vars.GCP_REGION }}" \ | |
| -var "project_id=${{ vars.GCP_PROJECT_ID }}" \ | |
| -var "proxy_base_url=${{ vars.PROXY_BASE_URL }}" \ | |
| -var "ssl_certificate_name=${{ vars.GCP_SSL_CERTIFICATE_NAME }}" \ | |
| -var "database_url=${{ secrets.DATABASE_URL || '' }}" \ | |
| -var "label_key=${{ vars.GCP_LABEL_KEY || 'hydroserver-instance' }}" \ | |
| -var "label_value=${{ vars.GCP_LABEL_VALUE || github.event.inputs.environment }}" | |
| - name: Authenticate Docker to Google Artifact Registry | |
| run: | | |
| gcloud auth configure-docker ${{ vars.GCP_REGION }}-docker.pkg.dev | |
| - name: Pull image from GHCR | |
| run: | | |
| docker pull ghcr.io/hydroserver2/hydroserver-api-services:latest | |
| - name: Tag image for Artifact Registry | |
| run: | | |
| docker tag ghcr.io/hydroserver2/hydroserver-api-services:latest \ | |
| ${{ vars.GCP_REGION }}-docker.pkg.dev/${{ vars.GCP_PROJECT_ID }}/${{ github.event.inputs.environment }}/hydroserver-api-services:latest | |
| - name: Push image to Google Artifact Registry | |
| run: | | |
| docker push ${{ vars.GCP_REGION }}-docker.pkg.dev/${{ vars.GCP_PROJECT_ID }}/${{ github.event.inputs.environment }}/hydroserver-api-services:latest | |
| - name: Terraform Apply | |
| run: | | |
| terraform apply \ | |
| -auto-approve -input=false \ | |
| -var "instance=${{ github.event.inputs.environment }}" \ | |
| -var "region=${{ vars.GCP_REGION }}" \ | |
| -var "project_id=${{ vars.GCP_PROJECT_ID }}" \ | |
| -var "proxy_base_url=${{ vars.PROXY_BASE_URL }}" \ | |
| -var "ssl_certificate_name=${{ vars.GCP_SSL_CERTIFICATE_NAME }}" \ | |
| -var "database_url=${{ secrets.DATABASE_URL || '' }}" \ | |
| -var "label_key=${{ vars.GCP_LABEL_KEY || 'hydroserver-instance' }}" \ | |
| -var "label_value=${{ vars.GCP_LABEL_VALUE || github.event.inputs.environment }}" | |
| deploy-hydroserver: | |
| needs: | |
| - check-environment-variables | |
| - initialize-hydroserver | |
| if: > | |
| always() && | |
| !contains(needs.*.result, 'failure') && | |
| ( | |
| (github.event.inputs.action == 'Initialize HydroServer Deployment' && needs.initialize-hydroserver.result == 'success') || | |
| (github.event.inputs.action == 'Update HydroServer Deployment' && needs.check-environment-variables.result == 'success') | |
| ) | |
| runs-on: ubuntu-latest | |
| environment: ${{ github.event.inputs.environment }} | |
| defaults: | |
| run: | |
| working-directory: ./terraform/gcp | |
| steps: | |
| - name: Checkout Ops Repo | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.ref }} | |
| - name: Configure GCP Credentials | |
| uses: google-github-actions/auth@v2 | |
| with: | |
| project_id: ${{ vars.GCP_PROJECT_ID }} | |
| workload_identity_provider: ${{ vars.GCP_IDENTITY_PROVIDER }} | |
| service_account: ${{ vars.GCP_SERVICE_ACCOUNT }} | |
| - name: Set up GCP SDK | |
| uses: google-github-actions/setup-gcloud@v1 | |
| with: | |
| project_id: ${{ vars.GCP_PROJECT_ID }} | |
| - name: Authenticate Docker to Google Artifact Registry | |
| run: | | |
| gcloud auth configure-docker ${{ vars.GCP_REGION }}-docker.pkg.dev | |
| - name: Pull image from GHCR | |
| run: | | |
| docker pull ghcr.io/hydroserver2/hydroserver-api-services:${{ github.event.inputs.release }} | |
| - name: Tag image for Artifact Registry | |
| run: | | |
| docker tag ghcr.io/hydroserver2/hydroserver-api-services:${{ github.event.inputs.release }} \ | |
| ${{ vars.GCP_REGION }}-docker.pkg.dev/${{ vars.GCP_PROJECT_ID }}/${{ github.event.inputs.environment }}/hydroserver-api-services:latest | |
| - name: Push image to Google Artifact Registry | |
| run: | | |
| docker push ${{ vars.GCP_REGION }}-docker.pkg.dev/${{ vars.GCP_PROJECT_ID }}/${{ github.event.inputs.environment }}/hydroserver-api-services:latest | |
| - name: Update Cloud Run Secrets | |
| run: | | |
| echo -n "${{ secrets.SMTP_URL }}" | gcloud secrets versions add "hydroserver-${{ github.event.inputs.environment }}-api-smtp-url" --data-file=- | |
| - name: Run HydroServer Setup Commands | |
| run: | | |
| ENV_VARS="" | |
| [ -n "${{ vars.GCP_PROJECT_ID }}" ] && ENV_VARS+="GS_PROJECT_ID=${{ vars.GCP_PROJECT_ID }}," | |
| [ -n "${{ vars.LOAD_DEFAULT_DATA }}" ] && ENV_VARS+="LOAD_DEFAULT_DATA=${{ vars.LOAD_DEFAULT_DATA }}," | |
| ENV_VARS=${ENV_VARS%,} | |
| gcloud run jobs execute hydroserver-init-${{ github.event.inputs.environment }} \ | |
| --region ${{ vars.GCP_REGION }} \ | |
| ${ENV_VARS:+--update-env-vars "$ENV_VARS"} | |
| - name: Update Cloud Run Web Service | |
| run: | | |
| ENV_VARS="" | |
| [ -n "${{ vars.GCP_PROJECT_ID }}" ] && ENV_VARS+="GS_PROJECT_ID=${{ vars.GCP_PROJECT_ID }}," | |
| [ -n "${{ vars.DEBUG }}" ] && ENV_VARS+="DEBUG=${{ vars.DEBUG }}," || ENV_VARS+="DEBUG=True," | |
| [ -n "${{ vars.PROXY_BASE_URL }}" ] && ENV_VARS+="PROXY_BASE_URL=${{ vars.PROXY_BASE_URL }}," | |
| [ -n "${{ vars.ACCOUNT_OWNERSHIP_ENABLED }}" ] && ENV_VARS+="ACCOUNT_OWNERSHIP_ENABLED=${{ vars.ACCOUNT_OWNERSHIP_ENABLED }}," || ENV_VARS+="ACCOUNT_OWNERSHIP_ENABLED=False," | |
| [ -n "${{ vars.ACCOUNT_SIGNUP_ENABLED }}" ] && ENV_VARS+="ACCOUNT_SIGNUP_ENABLED=${{ vars.ACCOUNT_SIGNUP_ENABLED }}," || ENV_VARS+="ACCOUNT_SIGNUP_ENABLED=True," | |
| [ -n "${{ vars.SOCIALACCOUNT_SIGNUP_ONLY }}" ] && ENV_VARS+="SOCIALACCOUNT_SIGNUP_ONLY=${{ vars.SOCIALACCOUNT_SIGNUP_ONLY }}," || ENV_VARS+="SOCIALACCOUNT_SIGNUP_ONLY=False," | |
| ENV_VARS=${ENV_VARS%,} | |
| gcloud run services update hydroserver-api-${{ github.event.inputs.environment }} \ | |
| --image ${{ vars.GCP_REGION }}-docker.pkg.dev/${{ vars.GCP_PROJECT_ID }}/${{ github.event.inputs.environment }}/hydroserver-api-services:latest \ | |
| --region ${{ vars.GCP_REGION }} \ | |
| ${ENV_VARS:+--update-env-vars "$ENV_VARS"} | |
| teardown-hydroserver: | |
| needs: check-environment-variables | |
| runs-on: ubuntu-latest | |
| environment: ${{ github.event.inputs.environment }} | |
| if: success() && github.event.inputs.action == 'Teardown HydroServer Deployment' | |
| defaults: | |
| run: | |
| working-directory: ./terraform/gcp | |
| steps: | |
| - name: Checkout Ops Repo | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.ref }} | |
| - name: Configure GCP Credentials | |
| uses: google-github-actions/auth@v2 | |
| with: | |
| project_id: ${{ vars.GCP_PROJECT_ID }} | |
| workload_identity_provider: ${{ vars.GCP_IDENTITY_PROVIDER }} | |
| service_account: ${{ vars.GCP_SERVICE_ACCOUNT }} | |
| - name: Setup Terraform | |
| uses: hashicorp/setup-terraform@v1 | |
| - name: Terraform Init | |
| run: | | |
| terraform init \ | |
| -backend-config="impersonate_service_account=${{ vars.GCP_SERVICE_ACCOUNT }}" \ | |
| -backend-config="bucket=${{ vars.TERRAFORM_BUCKET }}" \ | |
| -backend-config="prefix=state/hydroserver_${{ github.event.inputs.environment }}" | |
| - name: Terraform Plan Destroy | |
| id: plan_destroy | |
| run: | | |
| terraform state rm google_sql_user.db_user || true | |
| terraform state rm google_sql_database.db || true | |
| terraform state rm google_sql_database_instance.db_instance || true | |
| terraform plan -destroy -no-color -input=false \ | |
| -var instance="${{ github.event.inputs.environment }}" \ | |
| -var region="${{ vars.GCP_REGION }}" \ | |
| -var project_id="${{ vars.GCP_PROJECT_ID }}" \ | |
| -var "proxy_base_url=${{ vars.PROXY_BASE_URL }}" \ | |
| -var "ssl_certificate_name=${{ vars.GCP_SSL_CERTIFICATE_NAME }}" | |
| continue-on-error: true | |
| - name: Terraform Plan Destroy Status | |
| if: steps.plan_destroy.outcome == 'failure' | |
| run: exit 1 | |
| - name: Terraform Destroy | |
| run: | | |
| terraform destroy -auto-approve -input=false \ | |
| -var instance="${{ github.event.inputs.environment }}" \ | |
| -var region="${{ vars.GCP_REGION }}" \ | |
| -var project_id="${{ vars.GCP_PROJECT_ID }}" \ | |
| -var "proxy_base_url=${{ vars.PROXY_BASE_URL }}" \ | |
| -var "ssl_certificate_name=${{ vars.GCP_SSL_CERTIFICATE_NAME }}" |