-
Notifications
You must be signed in to change notification settings - Fork 0
160 lines (136 loc) · 5.67 KB
/
cd-base.yml
File metadata and controls
160 lines (136 loc) · 5.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# ===============================================
# CI/CD Pipeline: Pull GHCR image -> Re-tag -> Push to DockerHub -> Deploy with Terraform
# ===============================================
# Description:
# This workflow takes a Docker image from GHCR (GitHub Container Registry) generated by a PR or push,
# retags it with the DockerHub username, pushes it to DockerHub, and then deploys the latest image
# to Cloud Run using Terraform. It also handles initial database table creation if necessary.
#
# Inputs:
# - deployment_env: Deployment environment (e.g., staging, production)
# - image_uri: URI of the image in GHCR (e.g., ghcr.io/org/repo:tag)
#
# Outputs:
# - dockerhub_image: URI of the retagged image pushed to DockerHub
# ===============================================
on:
workflow_call:
inputs:
deployment_env:
required: true
type: string
image_uri: # GHCR Docker image URI
required: true
type: string
jobs:
# -----------------------------------------------
# Job: Pull image from GHCR, retag, and push to DockerHub
# -----------------------------------------------
pull-tag-push:
runs-on: ubuntu-latest
outputs:
dockerhub_image: ${{ steps.push.outputs.image_uri }}
steps:
- name: Log in Github container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Extract tag name from GHCR
id: extract
run: |
TAG=$(echo "${{ inputs.image_uri }}" | awk -F':' '{print $NF}')
echo "tag=${TAG}" >> $GITHUB_OUTPUT
APP_NAME=$(echo "${{ inputs.image_uri }}" | awk -F'/' '{print $NF}' | cut -d':' -f1)
echo "app_name=${APP_NAME}" >> $GITHUB_OUTPUT
- name: Pull -> re-tag -> push
id: push
run: |
PUBLIC_IMAGE="${{ steps.extract.outputs.app_name }}:${{ steps.extract.outputs.tag }}"
DOCKERHUB_IMAGE="${{ secrets.DOCKERHUB_USERNAME }}/${PUBLIC_IMAGE}"
docker pull ${{ inputs.image_uri }}
docker tag ${{ inputs.image_uri }} ${DOCKERHUB_IMAGE}
docker push ${DOCKERHUB_IMAGE}
echo "image_uri=${PUBLIC_IMAGE}" >> $GITHUB_OUTPUT # <-- output this way given that github actions will censor secrets
# -----------------------------------------------
# Job: Deploy application to GCP using Terraform
# -----------------------------------------------
deploy:
needs: pull-tag-push
runs-on: ubuntu-latest
environment: ${{ inputs.deployment_env }}
steps:
- uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
- name: Auth GCP
uses: google-github-actions/auth@v2
with:
credentials_json: ${{ secrets.GCP_SA_KEY }}
- name: Init Terraform
working-directory: terraform
run: terraform init
- name: Use deployment env workspace
working-directory: terraform
run: |
terraform workspace select ${{ inputs.deployment_env }} || \
terraform workspace new ${{ inputs.deployment_env }}
- name: Debug dockerhub_image
run: |
echo "DockerHub image from previous job: '${{ needs.pull-tag-push.outputs.dockerhub_image }}'"
- name: Terraform plan
working-directory: terraform
run: |
terraform plan \
-var-file=environments/${{ inputs.deployment_env }}.tfvars \
-var="project_id=${{ secrets.GCP_PROJECT_ID }}" \
-var="db_name=${{ secrets.DB_NAME }}" \
-var="db_user=${{ secrets.DB_USER }}" \
-var="db_password=${{ secrets.DB_PASSWORD }}" \
-var="image_uri=${{ secrets.DOCKERHUB_USERNAME }}/${{ needs.pull-tag-push.outputs.dockerhub_image }}" \
-out=tfplan
- name: Terraform Apply
working-directory: terraform
run: terraform apply tfplan
- name: Get db public IP
id: db
working-directory: terraform
run: echo "public_ip=$(terraform output -raw db_host)" >> $GITHUB_OUTPUT
- name: Check if tickets table exists
id: check_table
env:
PGPASSWORD: ${{ secrets.DB_PASSWORD }}
run: |
# install postgres client
sudo apt-get update && sudo apt-get install -y postgresql-client
TABLE_EXISTS=$(psql -h ${{ steps.db.outputs.public_ip }} \
-U ${{ secrets.DB_USER }} \
-d ${{ secrets.DB_NAME }} \
-tAc "SELECT EXISTS (SELECT FROM pg_tables WHERE tablename = 'tickets');" \
)
echo "table_exist=$TABLE_EXISTS" >> $GITHUB_OUTPUT
- name: Create tables and populate (tickets table not existent)
if: steps.check_table.outputs.table_exist == 'f'
env:
PGPASSWORD: ${{ secrets.DB_PASSWORD }}
run: |
# if something fails stop
set -e
for file in $(ls src/db/scripts/*.sql | sort -V); do
echo "> Executing: $file"
psql -h ${{ steps.db.outputs.public_ip }} \
-U ${{ secrets.DB_USER }} \
-d ${{ secrets.DB_NAME }} \
-f "$file" \
-v DB_NAME=${{ secrets.DB_NAME }} \
-v ON_ERROR_STOP=1
done
- name: Skipped table creation (existent tickets table)
if: steps.check_table.outputs.table_exist == 't'
run: echo ""