1
- # This action will trigger when a PR is commentted containing /review -pr by a member of the org .
1
+ # This action will trigger when a PR is commented on with `/deploy -pr` or when the workflow is manually triggered .
2
2
name : Deploy PR
3
3
on :
4
4
issue_comment :
8
8
pr_number :
9
9
description : " PR number"
10
10
required : true
11
+ skip_build :
12
+ description : " Skip build job"
13
+ required : false
14
+ default : false
11
15
12
16
env :
13
17
REPO : ghcr.io/coder/coder-preview
62
66
63
67
- name : Comment on PR
64
68
id : comment_id
69
+ if : github.event_name == 'issue_comment'
65
70
uses : peter-evans/create-or-update-comment@v3
66
71
with :
67
72
issue-number : ${{ steps.pr_info.outputs.PR_NUMBER }}
72
77
73
78
build :
74
79
needs : pr_commented
80
+ # Skips the build job if the workflow was triggered by a workflow_dispatch event and the skip_build input is set to true
81
+ # or if the workflow was triggered by an issue_comment event and the comment body contains --skip-build
82
+ if : (github.event_name == 'workflow_dispatch' && github.event.inputs.skip_build == 'false') || (github.event_name == 'issue_comment' && contains(github.event.comment.body, '--skip-build') != true)
75
83
runs-on : ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
76
84
env :
77
85
DOCKER_CLI_EXPERIMENTAL : " enabled"
@@ -119,16 +127,32 @@ jobs:
119
127
120
128
deploy :
121
129
needs : [build, pr_commented]
122
- if : needs.build.result == 'success'
130
+ # Run deploy job only if build job was successful or skipped
131
+ if : always() && (needs.build.result == 'success' || needs.build.result == 'skipped') && needs.pr_commented.result == 'success'
123
132
runs-on : " ubuntu-latest"
124
133
env :
125
134
CODER_IMAGE_TAG : ${{ needs.pr_commented.outputs.CODER_IMAGE_TAG }}
126
135
PR_NUMBER : ${{ needs.pr_commented.outputs.PR_NUMBER }}
127
136
PR_TITLE : ${{ needs.pr_commented.outputs.PR_TITLE }}
128
137
PR_URL : ${{ needs.pr_commented.outputs.PR_URL }}
138
+ PR_BRANCH : ${{ needs.pr_commented.outputs.PR_BRANCH }}
139
+ PR_DEPLOYMENT_ACCESS_URL : " https://pr${{ needs.pr_commented.outputs.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
129
140
steps :
141
+ - name : Check if image exists
142
+ run : |
143
+ set -euxo pipefail
144
+ foundTag=$(curl -fsSL https://github.com/coder/coder/pkgs/container/coder-preview | grep -o ${{ env.CODER_IMAGE_TAG }} | head -n 1)
145
+ if [ -z "$foundTag" ]; then
146
+ echo "Image not found"
147
+ echo "${{ env.CODER_IMAGE_TAG }} not found in ghcr.io/coder/coder-preview"
148
+ echo "Please remove --skip-build from the comment or ./scripts/deploy-pr.sh"
149
+ exit 1
150
+ fi
151
+
130
152
- name : Checkout
131
153
uses : actions/checkout@v3
154
+ with :
155
+ ref : ${{ env.PR_BRANCH }}
132
156
133
157
- name : Set up kubeconfig
134
158
run : |
@@ -157,6 +181,7 @@ jobs:
157
181
spec:
158
182
tls:
159
183
- hosts:
184
+ - "${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
160
185
- "*.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
161
186
secretName: pr${{ env.PR_NUMBER }}-tls
162
187
rules:
@@ -173,32 +198,56 @@ jobs:
173
198
EOF
174
199
kubectl apply -f ingress.yaml
175
200
201
+ - name : Set up PostgreSQL database
202
+ run : |
203
+ helm repo add bitnami https://charts.bitnami.com/bitnami
204
+ helm install coder-db bitnami/postgresql \
205
+ --namespace pr${{ env.PR_NUMBER }} \
206
+ --set auth.username=coder \
207
+ --set auth.password=coder \
208
+ --set auth.database=coder \
209
+ --set persistence.size=10Gi
210
+ kubectl create secret generic coder-db-url -n pr${{ env.PR_NUMBER }} \
211
+ --from-literal=url="postgres://coder:[email protected] ${{ env.PR_NUMBER }}.svc.cluster.local:5432/coder?sslmode=disable"
212
+
213
+ - name : Create values.yaml
214
+ run : |
215
+ cat <<EOF > pr-deploy-values.yaml
216
+ coder:
217
+ image:
218
+ repo: ${{ env.REPO }}
219
+ tag: pr${{ env.PR_NUMBER }}
220
+ pullPolicy: Always
221
+ service:
222
+ type: ClusterIP
223
+ env:
224
+ - name: "CODER_ACCESS_URL"
225
+ value: "https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
226
+ - name: "CODER_WILDCARD_ACCESS_URL"
227
+ value: "*--pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
228
+ - name: "CODER_EXPERIMENTS"
229
+ value: "*"
230
+ - name: CODER_PG_CONNECTION_URL
231
+ valueFrom:
232
+ secretKeyRef:
233
+ name: coder-db-url
234
+ key: url
235
+ - name: "CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS"
236
+ value: "true"
237
+ - name: "CODER_OAUTH2_GITHUB_CLIENT_ID"
238
+ value: "${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_ID }}"
239
+ - name: "CODER_OAUTH2_GITHUB_CLIENT_SECRET"
240
+ value: "${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_SECRET }}"
241
+ - name: "CODER_OAUTH2_GITHUB_ALLOWED_ORGS"
242
+ value: "coder"
243
+ EOF
244
+
176
245
- name : Install Helm chart
177
246
run : |
178
- helm upgrade --install pr${{ env.PR_NUMBER }} ./helm \
247
+ helm upgrade --install " pr${{ env.PR_NUMBER }}" ./helm \
179
248
--namespace "pr${{ env.PR_NUMBER }}" \
180
- --set coder.image.repo=${{ env.REPO }} \
181
- --set coder.image.tag=pr${{ env.PR_NUMBER }} \
182
- --set coder.service.type=ClusterIP \
183
- --set coder.serviceAccount.enableDeployments=true \
184
- --set coder.env[0].name=CODER_ACCESS_URL \
185
- --set coder.env[0].value="https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}" \
186
- --set coder.env[1].name=CODER_WILDCARD_ACCESS_URL \
187
- --set coder.env[1].value="*--pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}" \
188
- --set coder.env[2].name=CODER_EXPERIMENTS \
189
- --set coder.env[2].value="*" \
249
+ --values ./pr-deploy-values.yaml \
190
250
--force
191
- # Uncomment this when https://github.com/coder/coder/issues/8714 is resolved
192
- # --set coder.env[3].name=CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS \
193
- # --set coder.env[3].value=true \
194
- # --set coder.env[4].name=CODER_OAUTH2_GITHUB_CLIENT_ID \
195
- # --set coder.env[4].value=${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_ID }} \
196
- # --set coder.env[5].name=CODER_OAUTH2_GITHUB_CLIENT_SECRET \
197
- # --set coder.env[5].value=${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_SECRET }} \
198
- # --set coder.env[6].name=CODER_OAUTH2_GITHUB_ALLOWED_ORGS \
199
- # --set coder.env[6].value=coder \
200
- # --set coder.env[7].name=CODER_OAUTH2_GITHUB_REDIRECT_URI \
201
- # --set coder.env[7].value="https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}/gitauth/github/callback
202
251
203
252
- name : Install coder-logstream-kube
204
253
run : |
@@ -207,28 +256,95 @@ jobs:
207
256
--namespace "pr${{ env.PR_NUMBER }}" \
208
257
--set url="https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
209
258
259
+ - name : Get Coder binary
260
+ run : |
261
+ set -euxo pipefail
262
+
263
+ DEST="${HOME}/coder"
264
+ URL="${{ env.PR_DEPLOYMENT_ACCESS_URL }}/bin/coder-linux-amd64"
265
+
266
+ mkdir -p "$(dirname ${DEST})"
267
+
268
+ COUNT=0
269
+ until $(curl --output /dev/null --silent --head --fail "$URL"); do
270
+ printf '.'
271
+ sleep 5
272
+ COUNT=$((COUNT+1))
273
+ if [ $COUNT -ge 60 ]; then
274
+ echo "Timed out waiting for URL to be available"
275
+ exit 1
276
+ fi
277
+ done
278
+
279
+ curl -fsSL "$URL" -o "${DEST}"
280
+ chmod +x "${DEST}"
281
+ "${DEST}" version
282
+
283
+ - name : Create first user, template and workspace
284
+ id : setup_deployment
285
+ run : |
286
+ set -euxo pipefail
287
+
288
+ # Create first user
289
+
290
+ # create a masked random password 12 characters long
291
+ password=$(openssl rand -base64 16 | tr -d "=+/" | cut -c1-12)
292
+
293
+ # add mask so that the password is not printed to the logs
294
+ echo "::add-mask::$password"
295
+ echo "password=$password" >> $GITHUB_OUTPUT
296
+
297
+ /home/runner/coder login \
298
+ --first-user-username pr${{ env.PR_NUMBER }} \
299
+ --first-user-email ${{ env.PR_NUMBER }}@coder.com \
300
+ --first-user-password $password \
301
+ --first-user-trial \
302
+ --use-token-as-session \
303
+ ${{ env.PR_DEPLOYMENT_ACCESS_URL }}
304
+
305
+ # Create template
306
+ /home/runner/coder templates init --id kubernetes && cd ./kubernetes/ && /home/runner/coder templates create -y --variable namespace=pr${{ env.PR_NUMBER }}
307
+
308
+ # Create workspace
309
+ cat <<EOF > workspace.yaml
310
+ cpu: "2"
311
+ memory: "4"
312
+ home_disk_size: "2"
313
+ EOF
314
+
315
+ /home/runner/coder create --template="kubernetes" pr${{ env.PR_NUMBER }} --rich-parameter-file ./workspace.yaml -y
316
+ /home/runner/coder stop pr${{ env.PR_NUMBER }} -y
317
+
210
318
- name : Send Slack notification
211
319
run : |
212
320
curl -s -o /dev/null -X POST -H 'Content-type: application/json' \
213
- -d '{
214
- "pr_number": "'"${{ env.PR_NUMBER }}"'",
215
- "pr_url": "'"${{ env.PR_URL }}"'",
216
- "pr_title": "'"${{ env.PR_TITLE }}"'",
217
- "pr_access_url": "'"${{ env.PR_DEPLOYMENT_ACCESS_URL }}"'" }' ${{ secrets.PR_DEPLOYMENTS_SLACK_WEBHOOK }}
321
+ -d \
322
+ '{
323
+ "pr_number": "'"${{ env.PR_NUMBER }}"'",
324
+ "pr_url": "'"${{ env.PR_URL }}"'",
325
+ "pr_title": "'"${{ env.PR_TITLE }}"'",
326
+ "pr_access_url": "'"${{ env.PR_DEPLOYMENT_ACCESS_URL }}"'",
327
+ "pr_username": "'"pr${{ env.PR_NUMBER }}"'",
328
+ "pr_email": "'"${{ env.PR_NUMBER }}@coder.com"'",
329
+ "pr_password": "'"${{ steps.setup_deployment.outputs.password }}"'",
330
+ "pr_actor": "'"${{ github.actor }}"'"
331
+ }' \
332
+ ${{ secrets.PR_DEPLOYMENTS_SLACK_WEBHOOK }}
218
333
echo "Slack notification sent"
219
- env :
220
- PR_DEPLOYMENT_ACCESS_URL : " https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
221
334
222
335
- name : Find Comment
223
336
uses : peter-evans/find-comment@v2
337
+ if : github.event_name == 'issue_comment'
224
338
id : fc
225
339
with :
226
340
issue-number : ${{ env.PR_NUMBER }}
227
341
comment-author : " github-actions[bot]"
228
342
body-includes : This deployment will be deleted when the PR is closed
343
+ direction : last
229
344
230
345
- name : Comment on PR
231
346
uses : peter-evans/create-or-update-comment@v3
347
+ if : github.event_name == 'issue_comment'
232
348
with :
233
349
issue-number : ${{ env.PR_NUMBER }}
234
350
edit-mode : replace
@@ -238,6 +354,3 @@ jobs:
238
354
:rocket: Access the deployment link [here](${{ env.PR_DEPLOYMENT_ACCESS_URL }}).
239
355
:warning: This deployment will be deleted when the PR is closed.
240
356
reactions : rocket
241
-
242
- env :
243
- PR_DEPLOYMENT_ACCESS_URL : " https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
0 commit comments