diff --git a/.github/workflows/pr-deploy.yaml b/.github/workflows/pr-deploy.yaml index ee4d274341e3f..95485abfbe898 100644 --- a/.github/workflows/pr-deploy.yaml +++ b/.github/workflows/pr-deploy.yaml @@ -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 < 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 < 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 }}" diff --git a/scripts/deploy-pr.sh b/scripts/deploy-pr.sh new file mode 100755 index 0000000000000..cd847a5b25591 --- /dev/null +++ b/scripts/deploy-pr.sh @@ -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}" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy