53
53
- name : Get PR number, title, and branch name
54
54
id : pr_info
55
55
run : |
56
- set -euxo pipefail
56
+ set -e pipefail
57
57
PR_NUMBER=${{ github.event.inputs.pr_number || github.event.pull_request.number }}
58
58
PR_TITLE=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/coder/coder/pulls/$PR_NUMBER | jq -r '.title')
59
59
PR_BRANCH=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/coder/coder/pulls/$PR_NUMBER | jq -r '.head.ref')
65
65
- name : Set required tags
66
66
id : set_tags
67
67
run : |
68
- set -euxo pipefail
68
+ set -e pipefail
69
69
echo "CODER_BASE_IMAGE_TAG=$CODER_BASE_IMAGE_TAG" >> $GITHUB_OUTPUT
70
70
echo "CODER_IMAGE_TAG=$CODER_IMAGE_TAG" >> $GITHUB_OUTPUT
71
71
env :
@@ -74,15 +74,15 @@ jobs:
74
74
75
75
- name : Set up kubeconfig
76
76
run : |
77
- set -euxo pipefail
77
+ set -e pipefail
78
78
mkdir -p ~/.kube
79
79
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG }}" > ~/.kube/config
80
80
export KUBECONFIG=~/.kube/config
81
81
82
82
- name : Check if the helm deployment already exists
83
83
id : check_deployment
84
84
run : |
85
- set -euxo pipefail
85
+ set -e pipefail
86
86
if helm status "pr${{ steps.pr_info.outputs.PR_NUMBER }}" --namespace "pr${{ steps.pr_info.outputs.PR_NUMBER }}" > /dev/null 2>&1; then
87
87
echo "Deployment already exists. Skipping deployment."
88
88
new=false
@@ -151,7 +151,7 @@ jobs:
151
151
- name : Print number of changed files
152
152
if : github.event_name == 'workflow_dispatch' || steps.check_deployment.outputs.NEW == 'false'
153
153
run : |
154
- set -euxo pipefail
154
+ set -e pipefail
155
155
echo "Total number of changed files: ${{ steps.filter.outputs.all_count }}"
156
156
echo "Number of ignored files: ${{ steps.filter.outputs.ignored_count }}"
157
157
@@ -193,7 +193,7 @@ jobs:
193
193
194
194
- name : Build and push Linux amd64 Docker image
195
195
run : |
196
- set -euxo pipefail
196
+ set -e pipefail
197
197
go mod download
198
198
make gen/mark-fresh
199
199
export DOCKER_IMAGE_NO_PREREQUISITES=true
@@ -224,15 +224,15 @@ jobs:
224
224
steps :
225
225
- name : Set up kubeconfig
226
226
run : |
227
- set -euxo pipefail
227
+ set -e pipefail
228
228
mkdir -p ~/.kube
229
229
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG }}" > ~/.kube/config
230
230
export KUBECONFIG=~/.kube/config
231
231
232
232
- name : Check if image exists
233
233
if : needs.get_info.outputs.NEW == 'true'
234
234
run : |
235
- set -euxo pipefail
235
+ set -e pipefail
236
236
foundTag=$(curl -fsSL https://github.com/coder/coder/pkgs/container/coder-preview | grep -o ${{ env.CODER_IMAGE_TAG }} | head -n 1)
237
237
if [ -z "$foundTag" ]; then
238
238
echo "Image not found"
@@ -257,7 +257,7 @@ jobs:
257
257
- name : Create PR namespace
258
258
if : needs.get_info.outputs.NEW == 'true'
259
259
run : |
260
- set -euxo pipefail
260
+ set -e pipefail
261
261
# try to delete the namespace, but don't fail if it doesn't exist
262
262
kubectl delete namespace "pr${{ env.PR_NUMBER }}" || true
263
263
kubectl create namespace "pr${{ env.PR_NUMBER }}"
@@ -312,6 +312,90 @@ jobs:
312
312
kubectl create secret generic coder-db-url -n pr${{ env.PR_NUMBER }} \
313
313
--from-literal=url="postgres://coder:coder@coder-db-postgresql.pr${{ env.PR_NUMBER }}.svc.cluster.local:5432/coder?sslmode=disable"
314
314
315
+ - name : Create a kubeconfig for the workspace
316
+ if : needs.get_info.outputs.NEW == 'true'
317
+ # This service account will be used to grant full access to the namespace from the workspace
318
+ run : |
319
+ set -e pipefail
320
+ # Create service account, role, rolebinding and secret
321
+ cat <<EOF | kubectl apply -f -
322
+ apiVersion: v1
323
+ kind: ServiceAccount
324
+ metadata:
325
+ name: coder-workspace
326
+ namespace: pr${{ env.PR_NUMBER }}
327
+ secrets:
328
+ - name: coder-workspace-token
329
+
330
+ ---
331
+ apiVersion: rbac.authorization.k8s.io/v1
332
+ kind: Role
333
+ metadata:
334
+ name: coder-workspace
335
+ namespace: pr${{ env.PR_NUMBER }}
336
+ rules:
337
+ - apiGroups: ["*"]
338
+ resources: ["*"]
339
+ verbs: ["*"]
340
+
341
+ ---
342
+ apiVersion: rbac.authorization.k8s.io/v1
343
+ kind: RoleBinding
344
+ metadata:
345
+ name: coder-workspace
346
+ namespace: pr${{ env.PR_NUMBER }}
347
+ subjects:
348
+ - kind: ServiceAccount
349
+ name: coder-workspace
350
+ namespace: pr${{ env.PR_NUMBER }}
351
+ roleRef:
352
+ apiGroup: rbac.authorization.k8s.io
353
+ kind: Role
354
+ name: coder-workspace
355
+
356
+ ---
357
+ apiVersion: v1
358
+ kind: Secret
359
+ metadata:
360
+ name: coder-workspace-token
361
+ namespace: pr${{ env.PR_NUMBER }}
362
+ annotations:
363
+ kubernetes.io/service-account.name: coder-workspace
364
+ type: kubernetes.io/service-account-token
365
+ EOF
366
+
367
+ # Get the token for the service account
368
+ TOKEN=$(kubectl -n pr${{ env.PR_NUMBER }} get secret coder-workspace-token -o jsonpath='{.data.token}' | base64 --decode)
369
+
370
+ # get CLUSTER_CA and CLUSTER_ENDPOINT
371
+ CLUSTER_CA=$(kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.certificate-authority-data}')
372
+ CLUSTER_ENDPOINT=$(kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.server}')
373
+
374
+ # Create a kubeconfig for the namespace to be used in the workspace
375
+ cat <<EOF > namespace-kubeconfig.yaml
376
+ apiVersion: v1
377
+ kind: Config
378
+ clusters:
379
+ - cluster:
380
+ certificate-authority-data: $CLUSTER_CA
381
+ server: $CLUSTER_ENDPOINT
382
+ name: pr${{ env.PR_NUMBER }}
383
+ contexts:
384
+ - context:
385
+ cluster: pr${{ env.PR_NUMBER }}
386
+ namespace: pr${{ env.PR_NUMBER }}
387
+ user: coder-workspace
388
+ name: pr${{ env.PR_NUMBER }}
389
+ current-context: pr${{ env.PR_NUMBER }}
390
+ users:
391
+ - name: coder-workspace
392
+ user:
393
+ token: $TOKEN
394
+ EOF
395
+
396
+ # Create a secret from the kubeconfig
397
+ kubectl create secret generic coder-namespace-kubeconfig -n pr${{ env.PR_NUMBER }} --from-file=kubeconfig=./namespace-kubeconfig.yaml
398
+
315
399
- name : Create values.yaml
316
400
if : github.event_name == 'workflow_dispatch'
317
401
run : |
@@ -332,6 +416,11 @@ jobs:
332
416
enable: true
333
417
secretName: pr${{ env.PR_NUMBER }}-tls
334
418
wildcardSecretName: pr${{ env.PR_NUMBER }}-tls
419
+ volumeMounts:
420
+ - name: coder-namespace-kubeconfig
421
+ mountPath: /home/coder/.kube/config
422
+ subPath: kubeconfig
423
+ readOnly: true
335
424
env:
336
425
- name: "CODER_ACCESS_URL"
337
426
value: "https://${{ env.PR_DEPLOYMENT_ACCESS_URL }}"
@@ -356,7 +445,7 @@ jobs:
356
445
357
446
- name : Install/Upgrade Helm chart
358
447
run : |
359
- set -euxo pipefail
448
+ set -e pipefail
360
449
if [[ ${{ github.event_name }} == "workflow_dispatch" ]]; then
361
450
helm upgrade --install "pr${{ env.PR_NUMBER }}" ./helm \
362
451
--namespace "pr${{ env.PR_NUMBER }}" \
@@ -384,7 +473,7 @@ jobs:
384
473
- name : Get Coder binary
385
474
if : needs.get_info.outputs.NEW == 'true'
386
475
run : |
387
- set -euxo pipefail
476
+ set -e pipefail
388
477
389
478
DEST="${HOME}/coder"
390
479
URL="https://${{ env.PR_DEPLOYMENT_ACCESS_URL }}/bin/coder-linux-amd64"
@@ -407,53 +496,11 @@ jobs:
407
496
"${DEST}" version
408
497
mv "${DEST}" /usr/local/bin/coder
409
498
410
- - name : Create a service account, role and rolebinding for coder-workspace
411
- if : needs.get_info.outputs.NEW == 'true'
412
- # This service account will be used to grant full access to the namespace from the workspace
413
- run : |
414
- set -euxo pipefail
415
- cat <<EOF | kubectl apply -f -
416
- apiVersion: v1
417
- kind: ServiceAccount
418
- metadata:
419
- name: coder-workspace
420
- namespace: pr${{ env.PR_NUMBER }}
421
- EOF
422
- cat <<EOF | kubectl apply -f -
423
- apiVersion: rbac.authorization.k8s.io/v1
424
- kind: Role
425
- metadata:
426
- name: coder-workspace
427
- namespace: pr${{ env.PR_NUMBER }}
428
- rules:
429
- - apiGroups: ["*"]
430
- resources: ["*"]
431
- verbs: ["*"]
432
- EOF
433
- cat <<EOF | kubectl apply -f -
434
- apiVersion: rbac.authorization.k8s.io/v1
435
- kind: RoleBinding
436
- metadata:
437
- name: coder-workspace
438
- namespace: pr${{ env.PR_NUMBER }}
439
- subjects:
440
- - kind: ServiceAccount
441
- name: coder-workspace
442
- namespace: pr${{ env.PR_NUMBER }}
443
- roleRef:
444
- apiGroup: rbac.authorization.k8s.io
445
- kind: Role
446
- name: coder-workspace
447
- EOF
448
- # Get the token for the service account
449
- TOKENNAME=$(kubectl -n your-namespace get serviceaccount/restricted-user -o=jsonpath='{.secrets[0].name}')
450
- TOKEN=$(kubectl -n your-namespace get secret $TOKENNAME -o=jsonpath='{.data.token}' | base64 -d)
451
-
452
499
- name : Create first user, template and workspace
453
500
if : needs.get_info.outputs.NEW == 'true'
454
501
id : setup_deployment
455
502
run : |
456
- set -euxo pipefail
503
+ set -e pipefail
457
504
458
505
# Create first user
459
506
0 commit comments