-
Notifications
You must be signed in to change notification settings - Fork 0
326 lines (326 loc) · 14.9 KB
/
deploy-cluster-2.yml
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
name: Deploy Cluster 2
on:
workflow_call:
inputs:
DOCKER_TAG:
required: true
type: string
APP_NAME:
description: "The app name used in for helm. Should contain a reference to the environment for this deployment"
required: true
type: string
APP_ROOT:
required: true
type: string
SERVICE_ID:
required: false
type: string
PUBLIC_URL:
required: false
type: string
KUBE_NAMESPACE:
required: false
type: string
KUBE_INGRESS_BASE_DOMAIN:
type: string
description: 'The ingress domain associated with the cluster the credentials are for'
required: false
POSTGRES_ENABLED:
required: false
type: boolean
POSTGRES_VERSION:
required: false
type: string
POSTGRES_HOST:
required: false
type: string
POSTGRES_USER:
type: string
description: 'User for the deployed PostgreSQL database'
required: false
POSTGRES_DB:
type: string
description: 'Database name for the deployed PostgreSQL database'
required: false
POSTGRES_SIZE:
required: false
type: string
environment:
required: false
type: string
default: ''
default_port:
required: false
type: string
default: '5000'
fetch-depth:
required: false
type: number
default: 0
submodules:
required: false
type: string
default: 'false'
do_deploy:
required: false
type: boolean
default: true
do_not_generate_additional_host_names:
required: false
type: string
default: 'false'
secrets:
C2_KUBE_CONFIG:
description: 'The kubctl config file with credentials to access the your kubernetes'
required: true
KUBE_NAMESPACE:
description: 'Namespace to deploy in (deprecated, use environment variable, not secret)'
required: false
C2_KUBE_INGRESS_BASE_DOMAIN:
description: 'The ingress domain associated with the cluster the credentials are for (deprecated, use environment variable, not secret)'
required: false
DATABASE_URL:
description: 'Database credentials in URL fromat'
required: false
POSTGRES_USER:
description: 'User for the deployed PostgreSQL database (deprecated, use environment variable, not secret)'
required: false
POSTGRES_DB:
description: 'Database name for the deployed PostgreSQL database (deprecated, use environment variable, not secret)'
required: false
POSTGRES_PASSWORD:
description: 'Password name for the deployed PostgreSQL database'
required: false
workflow_dispatch: {}
repository_dispatch:
types: [run]
jobs:
deploy-cluster-2:
# This workflow depends on the DOCKER_TAG passed pointing to the right container image
runs-on: 'ubuntu-latest'
if: ${{ inputs.do_deploy }}
environment:
name: ${{ inputs.environment }}
url: ${{ inputs.PUBLIC_URL || vars.PUBLIC_URL }}
steps:
- uses: actions/checkout@v4
name: Checkout gl-autodevops-minimal
with:
repository: ${{ github.repository_owner }}/gl-autodevops-minimal-port
# This step will have access to the sources of the caller in a sub directory!
- uses: actions/checkout@v4
name: Checkout
with:
path: caller
submodules: ${{ inputs.submodules }}
- name: Kubernetes credentials
run: |
mkdir ${HOME}/.kube
echo ${{ secrets.C2_KUBE_CONFIG }} | base64 --decode > ${HOME}/.kube/config
chmod 0600 ${HOME}/.kube/config
KUBE_NAMESPACE="${{ inputs.KUBE_NAMESPACE || secrets.KUBE_NAMESPACE || vars.KUBE_NAMESPACE }}"
if [ "$KUBE_NAMESPACE"x == 'x' ]
then KUBE_NAMESPACE="${{ inputs.APP_NAME }}"
fi
echo "KUBE_NAMESPACE=$KUBE_NAMESPACE" >> $GITHUB_ENV
kubectl config set-context --current --namespace=$KUBE_NAMESPACE
kubectl get pod
- name: Create tags based on git data
id: meta
uses: docker/metadata-action@v5
with:
images: |
${{ inputs.DOCKER_TAG }}
tags: |
type=raw,value={{sha}}
- if: inputs.POSTGRES_ENABLED || vars.POSTGRES_ENABLED || false
name: Deploy PostgreSQL
# --set volumePermissions.enabled=true is only needed for older cotainers like 9.6(.16).
# should be removed once only newer postgres versions are used
run: |
helm repo add bitnami https://charts.bitnami.com/bitnami
helm upgrade --install --atomic --wait --version 12.2.2 \
--set volumePermissions.enabled=true \
--set fullnameOverride="${{ inputs.APP_NAME }}-postgres" \
--set auth.username="${{ inputs.POSTGRES_USER || secrets.POSTGRES_USER || vars.POSTGRES_USER }}" \
--set auth.password="${{ secrets.POSTGRES_PASSWORD }}" \
--set auth.database="${{ inputs.POSTGRES_DB || secrets.POSTGRES_DB || vars.POSTGRES_DB }}" \
--set image.tag="${{ inputs.POSTGRES_VERSION || vars.POSTGRES_VERSION || '9.6.16' }}" \
--set persistence.size="${{ inputs.POSTGRES_SIZE || vars.POSTGRES_SIZE || '1Gi' }}" \
--namespace="${{ env.KUBE_NAMESPACE }}" \
"${{ inputs.APP_NAME }}-postgres" \
bitnami/postgresql
echo 'POSTGRES_ENABLED=${{ inputs.POSTGRES_ENABLED || vars.POSTGRES_ENABLED }}' >> $GITHUB_ENV
echo 'POSTGRES_HOST=${{ inputs.APP_NAME }}-postgres' >> $GITHUB_ENV
echo 'POSTGRES_USER=${{ inputs.POSTGRES_USER || secrets.POSTGRES_USER || vars.POSTGRES_USER }}' >> $GITHUB_ENV
echo 'POSTGRES_PASSWORD=${{ secrets.POSTGRES_PASSWORD }}' >> $GITHUB_ENV
echo 'POSTGRES_DB=${{ inputs.POSTGRES_DB || secrets.POSTGRES_DB || vars.POSTGRES_DB }}' >> $GITHUB_ENV
echo 'POSTGRES_VERSION=${{ inputs.POSTGRES_VERSION || vars.POSTGRES_VERSION || '9.6.16' }}' >> $GITHUB_ENV
echo 'POSTGRES_SIZE=${{ inputs.POSTGRES_SIZE || vars.POSTGRES_SIZE || '1Gi' }}' >> $GITHUB_ENV
echo 'DATABASE_URL=postgres://${{ secrets.POSTGRES_USER || vars.POSTGRES_USER }}:${{ secrets.POSTGRES_PASSWORD }}@${{ env.POSTGRES_HOST }}:5432/${{ secrets.POSTGRES_DB || vars.POSTGRES_DB }}' >> $GITHUB_ENV
- if: (vars.POSTGRES_HOST != '' || inputs.POSTGRES_HOST != '') && vars.POSTGRES_DB != ''
name: Set use external PostgreSQL server
run: |
echo 'POSTGRES_ENABLED=false' >> $GITHUB_ENV
echo 'POSTGRES_HOST=${{ inputs.POSTGRES_HOST || vars.POSTGRES_HOST }}' >> $GITHUB_ENV
- name: Set PostgreSQL server access credentials as environment variable
run: |
echo 'DEPLOY_DATABASE=${{ vars.DEPLOY_DATABASE || (vars.POSTGRES_HOST == '' && inputs.POSTGRES_HOST == '' && env.POSTGRES_ENABLED == '') }}' >> $GITHUB_ENV
echo 'POSTGRES_USER=${{ inputs.POSTGRES_USER || secrets.POSTGRES_USER || vars.POSTGRES_USER }}' >> $GITHUB_ENV
echo 'POSTGRES_PASSWORD=${{ secrets.POSTGRES_PASSWORD }}' >> $GITHUB_ENV
echo 'POSTGRES_DB=${{ inputs.POSTGRES_DB || secrets.POSTGRES_DB || vars.POSTGRES_DB }}' >> $GITHUB_ENV
DATABASE_URL="${{ secrets.DATABASE_URL }}"
if [ -z $DATABASE_URL ]
then if [ "${POSTGRES_HOST}x" != "x" ]; then echo "DATABASE_URL=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}}:5432/${POSTGRES_DB}" >> $GITHUB_ENV; fi
else echo 'DATABASE_URL=${{ secrets.DATABASE_URL }}' >> $GITHUB_ENV
fi
- name: Create auto-deploy-values.yaml
run: |
if [ -f caller/.github/auto-deploy-values.yaml ]
then cp caller/.github/auto-deploy-values.yaml tmp-auto-deploy-values.yaml
elif [ -f caller/.gitlab/auto-deploy-values.yaml ]
then cp caller/.gitlab/auto-deploy-values.yaml tmp-auto-deploy-values.yaml
else
cat > tmp-auto-deploy-values.yaml <<EOF
replicaCount: 1
image:
repository: \$repository
tag: "\$tag"
pullPolicy: Always
extraLabels:
"ID": "\$service_id"
gitlab:
app: "\$app_name"
envURL: "\$repo_url"
service:
enabled: true
name: "web"
url: "\$public_url"
EOF
if [ '${{ inputs.do_not_generate_additional_host_names }}x' = 'falsex' ]
then
cat >> tmp-auto-deploy-values.yaml <<EOF
additionalHosts:
- \${app_name_in_url}-\${ref_name}.\${kube_ingress_base_domain}
EOF
fi
cat >> tmp-auto-deploy-values.yaml <<EOF
type: ClusterIP
externalPort: ${{ inputs.default_port }}
internalPort: ${{ inputs.default_port }}
ingress:
enabled: true
path: "/"
annotations:
kubernetes.io/ingressClassName: "nginx"
EOF
if [ '${{ inputs.APP_ROOT }}x' != '/x' ]
then echo ' nginx.ingress.kubernetes.io/app-root: ${{ inputs.APP_ROOT }}' >> tmp-auto-deploy-values.yaml
fi
cat >> tmp-auto-deploy-values.yaml <<EOF
livenessProbe:
path: "${{ inputs.APP_ROOT }}"
initialDelaySeconds: 15
timeoutSeconds: 15
scheme: "HTTP"
probeType: "httpGet"
readinessProbe:
path: "${{ inputs.APP_ROOT }}"
initialDelaySeconds: 5
timeoutSeconds: 3
scheme: "HTTP"
probeType: "httpGet"
EOF
fi
kube_ingress_base_domain="${{ inputs.C2_KUBE_INGRESS_BASE_DOMAIN || vars.C2_KUBE_INGRESS_BASE_DOMAIN || vars.KUBE_INGRESS_BASE_DOMAIN }}"
environment_short="$(echo -n ${{ github.ref_name }} | sed 's/feature[_/]//' | tr '_' '-' | tr '[:upper:]' '[:lower:]' | cut -c1-24 | sed 's~-*$~~')"
public_url="${{ inputs.PUBLIC_URL || vars.PUBLIC_URL }}"
if [ "${public_url}x" == 'x' ]
then public_url=https://${environment_short}.${kube_ingress_base_domain}
fi
repo_url="${{ github.repositoryUrl }}" \
ref_name=$(echo -n "${{ github.ref_name }}" | tr '/' '-' | tr '_' '-' | tr '[:upper:]' '[:lower:]' | cut -c1-24 | sed 's~-*$~~') \
environment_short="$environment_short" \
kube_ingress_base_domain="${{ inputs.C2_KUBE_INGRESS_BASE_DOMAIN || secrets.C2_KUBE_INGRESS_BASE_DOMAIN || vars.C2_KUBE_INGRESS_BASE_DOMAIN || vars.KUBE_INGRESS_BASE_DOMAIN }}" \
public_url="$public_url" \
service_id="${{ inputs.SERVICE_ID || vars.SERVICE_ID }}" \
docker_tag="${{ steps.meta.outputs.tags }}" \
repository=${docker_tag/:*/} \
tag=${docker_tag/*:/} \
app_name="${{ inputs.APP_NAME }}" \
app_name_in_url=$(echo -n "${app_name// /-}" | tr '_' '-' | tr '[:upper:]' '[:lower:]' ) \
envsubst '$repo_url $ref_name $environment_short $kube_ingress_base_domain $public_url $service_id $docker_tag $repository $tag $app_name $app_name_in_url $POSTGRES_ENABLED $POSTGRES_HOST $POSTGRES_USER $POSTGRES_PASSWORD $POSTGRES_DB $POSTGRES_VERSION $POSTGRES_SIZE $DATABASE_URL $DEPLOY_DATABASE' < tmp-auto-deploy-values.yaml > auto-deploy-values.yaml
- name: Prepare environment variables as K8s secret
env:
SECRETS_CONTEXT: ${{ toJson(secrets) }}
VARS_CONTEXT: ${{ toJson(vars) }}
PUBLIC_URL: ${{ inputs.PUBLIC_URL }}
run: |
secret_name=$(echo -n "${{ inputs.APP_NAME }}" | tr '[:upper:]' '[:lower:]' | tr '_' '-' )
cat > secrets.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
name: $secret_name
type: Opaque
data:
EOF
k8s_secrets="$(echo -n "$SECRETS_CONTEXT" | jq -r '[to_entries[]|select(.key|startswith("K8S_SECRET_"))]|map(" \(.key|sub("K8S_SECRET_"; "")): \(.value|tostring|@base64)")|.[]')"
k8s_vars="$(echo -n "$VARS_CONTEXT" | jq -r '[to_entries[]|select(.key|startswith("K8S_SECRET_"))]|map(" \(.key|sub("K8S_SECRET_"; "")): \(.value|tostring|@base64)")|.[]')"
k8s_service_id="$(echo -n "$VARS_CONTEXT" | jq -r '[to_entries[]|select(.key == "SERVICE_ID")]|map(" \(.key): \(.value|tostring|@base64)")|.[]')"
if [ "${PUBLIC_URL}x" == "x" ]
then k8s_public_url="$(echo -n "$VARS_CONTEXT" | jq -r '[to_entries[]|select(.key == "PUBLIC_URL")]|map(" \(.key): \(.value|tostring|@base64)")|.[]')"
else k8s_public_url=" PUBLIC_URL: $(echo -n $PUBLIC_URL|base64 -w0)"
fi
k8s_secrets_lc="$(echo -n "$SECRETS_CONTEXT" | jq -r '[to_entries[]|select(.key|startswith("LC_K8S_SECRET_"))]|map(" \(.key|sub("LC_K8S_SECRET_"; "")|ascii_downcase): \(.value|tostring|@base64)")|.[]')"
k8s_vars_lc="$(echo -n "$VARS_CONTEXT" | jq -r '[to_entries[]|select(.key|startswith("LC_K8S_SECRET_"))]|map(" \(.key|sub("LC_K8S_SECRET_"; "")|ascii_downcase): \(.value|tostring|@base64)")|.[]')"
if [ "$k8s_secrets$k8s_vars$$k8s_service_id$k8s_public_urlk8s_secrets_lc$k8s_vars_lc$POSTGRES_HOST$DATABASE_URL$DEPLOY_DATABASE"x == 'x' ]
then echo ' {}' >> secrets.yaml
else printf "$k8s_secrets\n$k8s_vars\n$k8s_service_id\n$k8s_public_url\n$k8s_secrets_lc\n$k8s_vars_lc\n" >> secrets.yaml
fi
if [ "${POSTGRES_HOST}x" != "x" ]
then POSTGRES_USER=$(echo -n "${POSTGRES_USER}" | base64 -w0)
POSTGRES_PASSWORD=$(echo -n "${POSTGRES_PASSWORD}" | base64 -w0)
POSTGRES_DB=$(echo -n "${POSTGRES_DB}" | base64 -w0)
POSTGRES_HOST=$(echo -n "${POSTGRES_HOST}" | base64 -w0)
cat >> secrets.yaml <<EOF
POSTGRES_USER: $POSTGRES_USER
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
POSTGRES_DB: $POSTGRES_DB
POSTGRES_HOST: $POSTGRES_HOST
EOF
fi
if [ "${DATABASE_URL}x" != "x" ]
then DATABASE_URL=$(echo -n "${DATABASE_URL}" | base64 -w0)
cat >> secrets.yaml <<EOF
DATABASE_URL: $DATABASE_URL
EOF
fi
if [ "${DEPLOY_DATABASE}x" != "x" ]
then DEPLOY_DATABASE=$(echo -n "${DEPLOY_DATABASE}" | base64 -w0)
cat >> secrets.yaml <<EOF
DEPLOY_DATABASE: $DEPLOY_DATABASE
EOF
fi
kubectl replace -f secrets.yaml -n "${{ env.KUBE_NAMESPACE }}" --force
rm secrets.yaml
- name: Deploy using helm and the local helm chart
env:
SECRETS_CONTEXT: ${{ toJson(secrets) }}
run: |
if [ -f "caller/chart/Chart.yaml" ]
then chart="caller/chart"
else chart=".github/auto-deploy-app"
fi
release_name=$(echo -n "${{ inputs.APP_NAME }}" | tr '[:upper:]' '[:lower:]' | tr '_' '-' | cut -c1-24 | sed 's~-*$~~')
helm upgrade $release_name \
--values auto-deploy-values.yaml --install --atomic --wait \
--set application.database_url="$DATABASE_URL" \
--set application.secretName="${{ inputs.APP_NAME }}" ${{ secrets.HELM_UPGRADE_EXTRA_ARGS || vars.HELM_UPGRADE_EXTRA_ARGS }} \
$chart
- name: auto-deploy-values.yaml
uses: actions/upload-artifact@v4
if: always()
with:
name: ${{ inputs.APP_NAME }}-auto-deploy-values-yaml
path: auto-deploy-values.yaml