mirror of https://github.com/coder/coder.git
ci: improve deploy-pr workflow (#8735)
This commit is contained in:
parent
32829080ac
commit
bc55ffdf0d
|
@ -8,6 +8,10 @@ on:
|
|||
pr_number:
|
||||
description: "PR number"
|
||||
required: true
|
||||
skip_build:
|
||||
description: "Skip build job"
|
||||
required: false
|
||||
default: false
|
||||
|
||||
env:
|
||||
REPO: ghcr.io/coder/coder-preview
|
||||
|
@ -62,6 +66,7 @@ jobs:
|
|||
|
||||
- name: Comment on PR
|
||||
id: comment_id
|
||||
if: github.event_name == 'issue_comment'
|
||||
uses: peter-evans/create-or-update-comment@v3
|
||||
with:
|
||||
issue-number: ${{ steps.pr_info.outputs.PR_NUMBER }}
|
||||
|
@ -72,6 +77,9 @@ jobs:
|
|||
|
||||
build:
|
||||
needs: pr_commented
|
||||
# Skips the build job if the workflow was triggered by a workflow_dispatch event and the skip_build input is set to true
|
||||
# or if the workflow was triggered by an issue_comment event and the comment body contains --skip-build
|
||||
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)
|
||||
runs-on: ${{ github.repository_owner == 'coder' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
|
||||
env:
|
||||
DOCKER_CLI_EXPERIMENTAL: "enabled"
|
||||
|
@ -119,16 +127,32 @@ jobs:
|
|||
|
||||
deploy:
|
||||
needs: [build, pr_commented]
|
||||
if: needs.build.result == 'success'
|
||||
# Run deploy job only if build job was successful or skipped
|
||||
if: always() && (needs.build.result == 'success' || needs.build.result == 'skipped')
|
||||
runs-on: "ubuntu-latest"
|
||||
env:
|
||||
CODER_IMAGE_TAG: ${{ needs.pr_commented.outputs.CODER_IMAGE_TAG }}
|
||||
PR_NUMBER: ${{ needs.pr_commented.outputs.PR_NUMBER }}
|
||||
PR_TITLE: ${{ needs.pr_commented.outputs.PR_TITLE }}
|
||||
PR_URL: ${{ needs.pr_commented.outputs.PR_URL }}
|
||||
PR_BRANCH: ${{ needs.pr_commented.outputs.PR_BRANCH }}
|
||||
PR_DEPLOYMENT_ACCESS_URL: "https://pr${{ needs.pr_commented.outputs.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
|
||||
steps:
|
||||
- name: Check if image exists
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
foundTag=$(curl -fsSL https://github.com/coder/coder/pkgs/container/coder-preview | grep -o ${{ env.CODER_IMAGE_TAG }} | head -n 1)
|
||||
if [ -z "$foundTag" ]; then
|
||||
echo "Image not found"
|
||||
echo "${{ env.CODER_IMAGE_TAG }} not found in ghcr.io/coder/coder-preview"
|
||||
echo "Please remove --skip-build from the comment or ./scripts/deploy-pr.sh"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ env.PR_BRANCH }}
|
||||
|
||||
- name: Set up kubeconfig
|
||||
run: |
|
||||
|
@ -157,6 +181,7 @@ jobs:
|
|||
spec:
|
||||
tls:
|
||||
- hosts:
|
||||
- "${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
|
||||
- "*.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
|
||||
secretName: pr${{ env.PR_NUMBER }}-tls
|
||||
rules:
|
||||
|
@ -173,32 +198,39 @@ jobs:
|
|||
EOF
|
||||
kubectl apply -f ingress.yaml
|
||||
|
||||
- name: Create values.yaml
|
||||
run: |
|
||||
cat <<EOF > pr-deploy-values.yaml
|
||||
coder:
|
||||
image:
|
||||
repo: ${{ env.REPO }}
|
||||
tag: pr${{ env.PR_NUMBER }}
|
||||
pullPolicy: Always
|
||||
service:
|
||||
type: ClusterIP
|
||||
env:
|
||||
- name: "CODER_ACCESS_URL"
|
||||
value: "https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
|
||||
- name: "CODER_WILDCARD_ACCESS_URL"
|
||||
value: "*--pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
|
||||
- name: "CODER_EXPERIMENTS"
|
||||
value: "*"
|
||||
- name: "CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS"
|
||||
value: "true"
|
||||
- name: "CODER_OAUTH2_GITHUB_CLIENT_ID"
|
||||
value: "${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_ID }}"
|
||||
- name: "CODER_OAUTH2_GITHUB_CLIENT_SECRET"
|
||||
value: "${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_SECRET }}"
|
||||
- name: "CODER_OAUTH2_GITHUB_ALLOWED_ORGS"
|
||||
value: "coder"
|
||||
EOF
|
||||
|
||||
- name: Install Helm chart
|
||||
run: |
|
||||
helm upgrade --install pr${{ env.PR_NUMBER }} ./helm \
|
||||
helm upgrade --install "pr${{ env.PR_NUMBER }}" ./helm \
|
||||
--namespace "pr${{ env.PR_NUMBER }}" \
|
||||
--set coder.image.repo=${{ env.REPO }} \
|
||||
--set coder.image.tag=pr${{ env.PR_NUMBER }} \
|
||||
--set coder.service.type=ClusterIP \
|
||||
--set coder.serviceAccount.enableDeployments=true \
|
||||
--set coder.env[0].name=CODER_ACCESS_URL \
|
||||
--set coder.env[0].value="https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}" \
|
||||
--set coder.env[1].name=CODER_WILDCARD_ACCESS_URL \
|
||||
--set coder.env[1].value="*--pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}" \
|
||||
--set coder.env[2].name=CODER_EXPERIMENTS \
|
||||
--set coder.env[2].value="*" \
|
||||
--values ./pr-deploy-values.yaml \
|
||||
--force
|
||||
# Uncomment this when https://github.com/coder/coder/issues/8714 is resolved
|
||||
# --set coder.env[3].name=CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS \
|
||||
# --set coder.env[3].value=true \
|
||||
# --set coder.env[4].name=CODER_OAUTH2_GITHUB_CLIENT_ID \
|
||||
# --set coder.env[4].value=${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_ID }} \
|
||||
# --set coder.env[5].name=CODER_OAUTH2_GITHUB_CLIENT_SECRET \
|
||||
# --set coder.env[5].value=${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_SECRET }} \
|
||||
# --set coder.env[6].name=CODER_OAUTH2_GITHUB_ALLOWED_ORGS \
|
||||
# --set coder.env[6].value=coder \
|
||||
# --set coder.env[7].name=CODER_OAUTH2_GITHUB_REDIRECT_URI \
|
||||
# --set coder.env[7].value="https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}/gitauth/github/callback
|
||||
|
||||
- name: Install coder-logstream-kube
|
||||
run: |
|
||||
|
@ -207,28 +239,95 @@ jobs:
|
|||
--namespace "pr${{ env.PR_NUMBER }}" \
|
||||
--set url="https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
|
||||
|
||||
- name: Get Coder binary
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
|
||||
DEST="${HOME}/coder"
|
||||
URL="${{ env.PR_DEPLOYMENT_ACCESS_URL }}/bin/coder-linux-amd64"
|
||||
|
||||
mkdir -p "$(dirname ${DEST})"
|
||||
|
||||
COUNT=0
|
||||
until $(curl --output /dev/null --silent --head --fail "$URL"); do
|
||||
printf '.'
|
||||
sleep 5
|
||||
COUNT=$((COUNT+1))
|
||||
if [ $COUNT -ge 60 ]; then
|
||||
echo "Timed out waiting for URL to be available"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
curl -fsSL "$URL" -o "${DEST}"
|
||||
chmod +x "${DEST}"
|
||||
"${DEST}" version
|
||||
|
||||
- name: Create first user, template and workspace
|
||||
id: setup_deployment
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
|
||||
# Create first user
|
||||
|
||||
# create a masked random password 12 characters long
|
||||
password=$(openssl rand -base64 16 | tr -d "=+/" | cut -c1-12)
|
||||
|
||||
# add mask so that the password is not printed to the logs
|
||||
echo "::add-mask::$password"
|
||||
echo "password=$password" >> $GITHUB_OUTPUT
|
||||
|
||||
/home/runner/coder login \
|
||||
--first-user-username pr${{ env.PR_NUMBER }} \
|
||||
--first-user-email ${{ env.PR_NUMBER }}@coder.com \
|
||||
--first-user-password $password \
|
||||
--first-user-trial \
|
||||
--use-token-as-session \
|
||||
${{ env.PR_DEPLOYMENT_ACCESS_URL }}
|
||||
|
||||
# Create template
|
||||
/home/runner/coder templates init --id kubernetes && cd ./kubernetes/ && /home/runner/coder templates create -y --variable namespace=pr${{ env.PR_NUMBER }}
|
||||
|
||||
# Create workspace
|
||||
cat <<EOF > workspace.yaml
|
||||
cpu: "2"
|
||||
memory: "4"
|
||||
home_disk_size: "2"
|
||||
EOF
|
||||
|
||||
/home/runner/coder create --template="kubernetes" pr${{ env.PR_NUMBER }} --rich-parameter-file ./workspace.yaml -y
|
||||
/home/runner/coder stop pr${{ env.PR_NUMBER }} -y
|
||||
|
||||
- name: Send Slack notification
|
||||
run: |
|
||||
curl -s -o /dev/null -X POST -H 'Content-type: application/json' \
|
||||
-d '{
|
||||
"pr_number": "'"${{ env.PR_NUMBER }}"'",
|
||||
"pr_url": "'"${{ env.PR_URL }}"'",
|
||||
"pr_title": "'"${{ env.PR_TITLE }}"'",
|
||||
"pr_access_url": "'"${{ env.PR_DEPLOYMENT_ACCESS_URL }}"'" }' ${{ secrets.PR_DEPLOYMENTS_SLACK_WEBHOOK }}
|
||||
-d \
|
||||
'{
|
||||
"pr_number": "'"${{ env.PR_NUMBER }}"'",
|
||||
"pr_url": "'"${{ env.PR_URL }}"'",
|
||||
"pr_title": "'"${{ env.PR_TITLE }}"'",
|
||||
"pr_access_url": "'"${{ env.PR_DEPLOYMENT_ACCESS_URL }}"'",
|
||||
"pr_username": "'"pr${{ env.PR_NUMBER }}"'",
|
||||
"pr_email": "'"${{ env.PR_NUMBER }}@coder.com"'",
|
||||
"pr_password": "'"${{ steps.setup_deployment.outputs.password }}"'",
|
||||
"pr_actor": "'"${{ github.actor }}"'"
|
||||
}' \
|
||||
${{ secrets.PR_DEPLOYMENTS_SLACK_WEBHOOK }}
|
||||
echo "Slack notification sent"
|
||||
env:
|
||||
PR_DEPLOYMENT_ACCESS_URL: "https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
|
||||
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v2
|
||||
if: github.event_name == 'issue_comment'
|
||||
id: fc
|
||||
with:
|
||||
issue-number: ${{ env.PR_NUMBER }}
|
||||
comment-author: "github-actions[bot]"
|
||||
body-includes: This deployment will be deleted when the PR is closed
|
||||
direction: last
|
||||
|
||||
- name: Comment on PR
|
||||
uses: peter-evans/create-or-update-comment@v3
|
||||
if: github.event_name == 'issue_comment'
|
||||
with:
|
||||
issue-number: ${{ env.PR_NUMBER }}
|
||||
edit-mode: replace
|
||||
|
@ -238,6 +337,3 @@ jobs:
|
|||
:rocket: Access the deployment link [here](${{ env.PR_DEPLOYMENT_ACCESS_URL }}).
|
||||
:warning: This deployment will be deleted when the PR is closed.
|
||||
reactions: rocket
|
||||
|
||||
env:
|
||||
PR_DEPLOYMENT_ACCESS_URL: "https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
#!/usr/bin/env bash
|
||||
# Usage: ./deploy-pr.sh --skip-build
|
||||
# deploys the current branch to a PR environment and posts login credentials to
|
||||
# [#pr-deployments](https://codercom.slack.com/archives/C05DNE982E8) Slack channel
|
||||
# if --skip-build is passed, the build step will be skipped and the last build image will be used
|
||||
|
||||
set -euox pipefail
|
||||
|
||||
branchName=$(gh pr view --json headRefName | jq -r .headRefName)
|
||||
|
||||
if [[ "$branchName" == "main" ]]; then
|
||||
prNumber=$(git rev-parse --short HEAD)
|
||||
else
|
||||
prNumber=$(gh pr view --json number | jq -r .number)
|
||||
fi
|
||||
|
||||
# if --skip-build is passed, the build job will be skipped and the last built image will be used
|
||||
if [[ "$*" == *--skip-build* ]]; then
|
||||
skipBuild=true
|
||||
#check if the image exists
|
||||
foundTag=$(curl -fsSL https://github.com/coder/coder/pkgs/container/coder-preview | grep -o "$prNumber" | head -n 1)
|
||||
if [ -z "${foundTag}" ]; then
|
||||
echo "Image not found"
|
||||
echo "${prNumber} tag not found in ghcr.io/coder/coder-preview"
|
||||
echo "Please remove --skip-build and try again"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
skipBuild=false
|
||||
fi
|
||||
|
||||
gh workflow run pr-deploy.yaml --ref "${branchName}" -f pr_number="${prNumber}" -f skip_build="${skipBuild}"
|
Loading…
Reference in New Issue