mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
1276b9d9b7
[//]: # (dependabot-start) ⚠️ **Dependabot is rebasing this PR** ⚠️ Rebasing might not happen immediately, so don't worry if this takes some time. Note: if you make any changes to this PR yourself, they will take precedence over the rebase. --- [//]: # (dependabot-end) Bumps the github-actions group with 2 updates: [step-security/harden-runner](https://github.com/step-security/harden-runner) and [actions/setup-java](https://github.com/actions/setup-java). Updates `step-security/harden-runner` from 2.14.0 to 2.14.1 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/step-security/harden-runner/releases">step-security/harden-runner's releases</a>.</em></p> <blockquote> <h2>v2.14.1</h2> <h2>What's Changed</h2> <ol> <li> <p>In some self-hosted environments, the agent could briefly fall back to public DNS resolvers during startup if the system DNS was not yet available. This behavior was unintended for GitHub-hosted runners and has now been fixed to prevent any use of public DNS resolvers.</p> </li> <li> <p>Fixed npm audit vulnerabilities</p> </li> </ol> <p><strong>Full Changelog</strong>: <a href="https://github.com/step-security/harden-runner/compare/v2.14.0...v2.14.1">https://github.com/step-security/harden-runner/compare/v2.14.0...v2.14.1</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/step-security/harden-runner/commit/e3f713f2d8f53843e71c69a996d56f51aa9adfb9"><code>e3f713f</code></a> Merge pull request <a href="https://redirect.github.com/step-security/harden-runner/issues/631">#631</a> from step-security/rc-31</li> <li><a href="https://github.com/step-security/harden-runner/commit/423acdda6fd4f75f197b7c305a3f2e3d700dc00b"><code>423acdd</code></a> chore: fix npm audit vulnerabilities</li> <li><a href="https://github.com/step-security/harden-runner/commit/0ddb86cf0353b79dbed5bb8cef4103700cea70a7"><code>0ddb86c</code></a> update agent</li> <li>See full diff in <a href="https://github.com/step-security/harden-runner/compare/20cf305ff2072d973412fa9b1e3a4f227bda3c76...e3f713f2d8f53843e71c69a996d56f51aa9adfb9">compare view</a></li> </ul> </details> <br /> Updates `actions/setup-java` from 5.1.0 to 5.2.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/setup-java/releases">actions/setup-java's releases</a>.</em></p> <blockquote> <h2>v5.2.0</h2> <h2>What's Changed</h2> <h3>Enhancement</h3> <ul> <li>Retry on HTTP 522 Connection timed out by <a href="https://github.com/findepi"><code>@findepi</code></a> in <a href="https://redirect.github.com/actions/setup-java/pull/964">actions/setup-java#964</a></li> </ul> <h3>Documentation Changes</h3> <ul> <li>Update gradle caching by <a href="https://github.com/priya-kinthali"><code>@priya-kinthali</code></a> in <a href="https://redirect.github.com/actions/setup-java/pull/972">actions/setup-java#972</a></li> <li>Update checkout to v6 by <a href="https://github.com/mahabaleshwars"><code>@mahabaleshwars</code></a> in <a href="https://redirect.github.com/actions/setup-java/pull/973">actions/setup-java#973</a></li> </ul> <h3>Dependency Updates</h3> <ul> <li>Upgrade <code>@actions/cache</code> to v5 by <a href="https://github.com/salmanmkc"><code>@salmanmkc</code></a> in <a href="https://redirect.github.com/actions/setup-java/pull/968">actions/setup-java#968</a></li> <li>Upgrade actions/checkout from 5 to 6 by <a href="https://github.com/dependabot"><code>@dependabot</code></a> in <a href="https://redirect.github.com/actions/setup-java/pull/961">actions/setup-java#961</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/findepi"><code>@findepi</code></a> made their first contribution in <a href="https://redirect.github.com/actions/setup-java/pull/964">actions/setup-java#964</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/setup-java/compare/v5...v5.2.0">https://github.com/actions/setup-java/compare/v5...v5.2.0</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/setup-java/commit/be666c2fcd27ec809703dec50e508c2fdc7f6654"><code>be666c2</code></a> Chore: Version Update and Checkout Update to v6 (<a href="https://redirect.github.com/actions/setup-java/issues/973">#973</a>)</li> <li><a href="https://github.com/actions/setup-java/commit/f7a6fefba97e80156950e16f2a9dafc8579b7d05"><code>f7a6fef</code></a> Bump actions/checkout from 5 to 6 (<a href="https://redirect.github.com/actions/setup-java/issues/961">#961</a>)</li> <li><a href="https://github.com/actions/setup-java/commit/d81c4e45f3ac973cc936d79104023e20054ba578"><code>d81c4e4</code></a> Upgrade <code>@actions/cache</code> to v5 (<a href="https://redirect.github.com/actions/setup-java/issues/968">#968</a>)</li> <li><a href="https://github.com/actions/setup-java/commit/1b1bbe1085cb6ab21b5b19b7bebc091a9430026a"><code>1b1bbe1</code></a> readme update (<a href="https://redirect.github.com/actions/setup-java/issues/972">#972</a>)</li> <li><a href="https://github.com/actions/setup-java/commit/5d7b2146334bacf88728daaa70414a99f5164e0f"><code>5d7b214</code></a> Retry on HTTP 522 Connection timed out (<a href="https://redirect.github.com/actions/setup-java/issues/964">#964</a>)</li> <li>See full diff in <a href="https://github.com/actions/setup-java/compare/f2beeb24e141e01a676f977032f5a29d81c9e27e...be666c2fcd27ec809703dec50e508c2fdc7f6654">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
529 lines
20 KiB
YAML
529 lines
20 KiB
YAML
# This action will trigger when
|
|
# 1. when the workflow is manually triggered
|
|
# 2. ./scripts/deploy_pr.sh is run locally
|
|
# 3. when a PR is updated
|
|
name: Deploy PR
|
|
on:
|
|
push:
|
|
branches-ignore:
|
|
- main
|
|
- "temp-cherry-pick-*"
|
|
workflow_dispatch:
|
|
inputs:
|
|
experiments:
|
|
description: "Experiments to enable"
|
|
required: false
|
|
type: string
|
|
default: "*"
|
|
build:
|
|
description: "Force new build"
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
deploy:
|
|
description: "Force new deployment"
|
|
required: false
|
|
type: boolean
|
|
default: false
|
|
|
|
env:
|
|
REPO: ghcr.io/coder/coder-preview
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
check_pr:
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
PR_OPEN: ${{ steps.check_pr.outputs.pr_open }}
|
|
steps:
|
|
- name: Harden Runner
|
|
uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1
|
|
with:
|
|
egress-policy: audit
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Check if PR is open
|
|
id: check_pr
|
|
run: |
|
|
set -euo pipefail
|
|
pr_open=true
|
|
if [[ "$(gh pr view --json state | jq -r '.state')" != "OPEN" ]]; then
|
|
echo "PR doesn't exist or is closed."
|
|
pr_open=false
|
|
fi
|
|
echo "pr_open=$pr_open" >> "$GITHUB_OUTPUT"
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
get_info:
|
|
needs: check_pr
|
|
if: ${{ needs.check_pr.outputs.PR_OPEN == 'true' }}
|
|
outputs:
|
|
PR_NUMBER: ${{ steps.pr_info.outputs.PR_NUMBER }}
|
|
PR_TITLE: ${{ steps.pr_info.outputs.PR_TITLE }}
|
|
PR_URL: ${{ steps.pr_info.outputs.PR_URL }}
|
|
CODER_BASE_IMAGE_TAG: ${{ steps.set_tags.outputs.CODER_BASE_IMAGE_TAG }}
|
|
CODER_IMAGE_TAG: ${{ steps.set_tags.outputs.CODER_IMAGE_TAG }}
|
|
NEW: ${{ steps.check_deployment.outputs.NEW }}
|
|
BUILD: ${{ steps.build_conditionals.outputs.first_or_force_build == 'true' || steps.build_conditionals.outputs.automatic_rebuild == 'true' }}
|
|
|
|
runs-on: "ubuntu-latest"
|
|
steps:
|
|
- name: Harden Runner
|
|
uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1
|
|
with:
|
|
egress-policy: audit
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
|
|
- name: Get PR number, title, and branch name
|
|
id: pr_info
|
|
run: |
|
|
set -euo pipefail
|
|
PR_NUMBER=$(gh pr view --json number | jq -r '.number')
|
|
PR_TITLE=$(gh pr view --json title | jq -r '.title')
|
|
PR_URL=$(gh pr view --json url | jq -r '.url')
|
|
{
|
|
echo "PR_URL=$PR_URL"
|
|
echo "PR_NUMBER=$PR_NUMBER"
|
|
echo "PR_TITLE=$PR_TITLE"
|
|
} >> "$GITHUB_OUTPUT"
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Set required tags
|
|
id: set_tags
|
|
run: |
|
|
set -euo pipefail
|
|
echo "CODER_BASE_IMAGE_TAG=$CODER_BASE_IMAGE_TAG" >> "$GITHUB_OUTPUT"
|
|
echo "CODER_IMAGE_TAG=$CODER_IMAGE_TAG" >> "$GITHUB_OUTPUT"
|
|
env:
|
|
CODER_BASE_IMAGE_TAG: ghcr.io/coder/coder-preview-base:pr${{ steps.pr_info.outputs.PR_NUMBER }}
|
|
CODER_IMAGE_TAG: ghcr.io/coder/coder-preview:pr${{ steps.pr_info.outputs.PR_NUMBER }}
|
|
|
|
- name: Set up kubeconfig
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p ~/.kube
|
|
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG_BASE64 }}" | base64 --decode > ~/.kube/config
|
|
chmod 600 ~/.kube/config
|
|
export KUBECONFIG=~/.kube/config
|
|
|
|
- name: Check if the helm deployment already exists
|
|
id: check_deployment
|
|
run: |
|
|
set -euo pipefail
|
|
if helm status "pr${PR_NUMBER}" --namespace "pr${PR_NUMBER}" > /dev/null 2>&1; then
|
|
echo "Deployment already exists. Skipping deployment."
|
|
NEW=false
|
|
else
|
|
echo "Deployment doesn't exist."
|
|
NEW=true
|
|
fi
|
|
echo "NEW=$NEW" >> "$GITHUB_OUTPUT"
|
|
env:
|
|
PR_NUMBER: ${{ steps.pr_info.outputs.PR_NUMBER }}
|
|
|
|
- name: Check changed files
|
|
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
|
|
id: filter
|
|
with:
|
|
base: ${{ github.ref }}
|
|
filters: |
|
|
all:
|
|
- "**"
|
|
ignored:
|
|
- "docs/**"
|
|
- "README.md"
|
|
- "examples/web-server/**"
|
|
- "examples/monitoring/**"
|
|
- "examples/lima/**"
|
|
- ".github/**"
|
|
- "offlinedocs/**"
|
|
- ".devcontainer/**"
|
|
- "helm/**"
|
|
- "*[^g][^o][^.][^s][^u][^m]*"
|
|
- "*[^g][^o][^.][^m][^o][^d]*"
|
|
- "*[^M][^a][^k][^e][^f][^i][^l][^e]*"
|
|
- "scripts/**/*[^D][^o][^c][^k][^e][^r][^f][^i][^l][^e]*"
|
|
- "scripts/**/*[^D][^o][^c][^k][^e][^r][^f][^i][^l][^e][.][b][^a][^s][^e]*"
|
|
|
|
- name: Print number of changed files
|
|
run: |
|
|
set -euo pipefail
|
|
echo "Total number of changed files: ${ALL_COUNT}"
|
|
echo "Number of ignored files: ${IGNORED_COUNT}"
|
|
env:
|
|
ALL_COUNT: ${{ steps.filter.outputs.all_count }}
|
|
IGNORED_COUNT: ${{ steps.filter.outputs.ignored_count }}
|
|
|
|
- name: Build conditionals
|
|
id: build_conditionals
|
|
run: |
|
|
set -euo pipefail
|
|
# build if the workflow is manually triggered and the deployment doesn't exist (first build or force rebuild)
|
|
echo "first_or_force_build=${{ (github.event_name == 'workflow_dispatch' && steps.check_deployment.outputs.NEW == 'true') || github.event.inputs.build == 'true' }}" >> "$GITHUB_OUTPUT"
|
|
# build if the deployment already exist and there are changes in the files that we care about (automatic updates)
|
|
echo "automatic_rebuild=${{ steps.check_deployment.outputs.NEW == 'false' && steps.filter.outputs.all_count > steps.filter.outputs.ignored_count }}" >> "$GITHUB_OUTPUT"
|
|
|
|
comment-pr:
|
|
needs: get_info
|
|
if: needs.get_info.outputs.BUILD == 'true' || github.event.inputs.deploy == 'true'
|
|
runs-on: "ubuntu-latest"
|
|
permissions:
|
|
pull-requests: write # needed for commenting on PRs
|
|
steps:
|
|
- name: Harden Runner
|
|
uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1
|
|
with:
|
|
egress-policy: audit
|
|
|
|
- name: Find Comment
|
|
uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4.0.0
|
|
id: fc
|
|
with:
|
|
issue-number: ${{ needs.get_info.outputs.PR_NUMBER }}
|
|
comment-author: "github-actions[bot]"
|
|
body-includes: ":rocket:"
|
|
direction: last
|
|
|
|
- name: Comment on PR
|
|
id: comment_id
|
|
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
|
|
with:
|
|
comment-id: ${{ steps.fc.outputs.comment-id }}
|
|
issue-number: ${{ needs.get_info.outputs.PR_NUMBER }}
|
|
edit-mode: replace
|
|
body: |
|
|
---
|
|
:rocket: Deploying PR ${{ needs.get_info.outputs.PR_NUMBER }} ...
|
|
---
|
|
reactions: eyes
|
|
reactions-edit-mode: replace
|
|
|
|
build:
|
|
needs: get_info
|
|
# Run build job only if there are changes in the files that we care about or if the workflow is manually triggered with --build flag
|
|
if: needs.get_info.outputs.BUILD == 'true'
|
|
runs-on: ${{ github.repository_owner == 'coder' && 'depot-ubuntu-22.04-8' || 'ubuntu-latest' }}
|
|
permissions:
|
|
# Necessary to push docker images to ghcr.io.
|
|
packages: write
|
|
# This concurrency only cancels build jobs if a new build is triggred. It will avoid cancelling the current deployemtn in case of docs changes.
|
|
concurrency:
|
|
group: build-${{ github.workflow }}-${{ github.ref }}-${{ needs.get_info.outputs.BUILD }}
|
|
cancel-in-progress: true
|
|
env:
|
|
DOCKER_CLI_EXPERIMENTAL: "enabled"
|
|
CODER_IMAGE_TAG: ${{ needs.get_info.outputs.CODER_IMAGE_TAG }}
|
|
steps:
|
|
- name: Harden Runner
|
|
uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1
|
|
with:
|
|
egress-policy: audit
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
|
|
- name: Setup Node
|
|
uses: ./.github/actions/setup-node
|
|
|
|
- name: Setup Go
|
|
uses: ./.github/actions/setup-go
|
|
|
|
- name: Setup sqlc
|
|
uses: ./.github/actions/setup-sqlc
|
|
|
|
- name: GHCR Login
|
|
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Build and push Linux amd64 Docker image
|
|
run: |
|
|
set -euo pipefail
|
|
go mod download
|
|
make gen/mark-fresh
|
|
export DOCKER_IMAGE_NO_PREREQUISITES=true
|
|
version="$(./scripts/version.sh)"
|
|
CODER_IMAGE_BUILD_BASE_TAG="$(CODER_IMAGE_BASE=coder-base ./scripts/image_tag.sh --version "$version")"
|
|
export CODER_IMAGE_BUILD_BASE_TAG
|
|
make -j build/coder_linux_amd64
|
|
./scripts/build_docker.sh \
|
|
--arch amd64 \
|
|
--target "${CODER_IMAGE_TAG}" \
|
|
--version "$version" \
|
|
--push \
|
|
build/coder_linux_amd64
|
|
|
|
deploy:
|
|
needs: [build, get_info]
|
|
# Run deploy job only if build job was successful or skipped
|
|
if: |
|
|
always() && (needs.build.result == 'success' || needs.build.result == 'skipped') &&
|
|
(needs.get_info.outputs.BUILD == 'true' || github.event.inputs.deploy == 'true')
|
|
runs-on: "ubuntu-latest"
|
|
permissions:
|
|
pull-requests: write # needed for commenting on PRs
|
|
env:
|
|
CODER_IMAGE_TAG: ${{ needs.get_info.outputs.CODER_IMAGE_TAG }}
|
|
PR_NUMBER: ${{ needs.get_info.outputs.PR_NUMBER }}
|
|
PR_TITLE: ${{ needs.get_info.outputs.PR_TITLE }}
|
|
PR_URL: ${{ needs.get_info.outputs.PR_URL }}
|
|
PR_HOSTNAME: "pr${{ needs.get_info.outputs.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
|
|
steps:
|
|
- name: Harden Runner
|
|
uses: step-security/harden-runner@e3f713f2d8f53843e71c69a996d56f51aa9adfb9 # v2.14.1
|
|
with:
|
|
egress-policy: audit
|
|
|
|
- name: Set up kubeconfig
|
|
run: |
|
|
set -euo pipefail
|
|
mkdir -p ~/.kube
|
|
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG_BASE64 }}" | base64 --decode > ~/.kube/config
|
|
chmod 600 ~/.kube/config
|
|
export KUBECONFIG=~/.kube/config
|
|
|
|
- name: Check if image exists
|
|
run: |
|
|
set -euo pipefail
|
|
foundTag=$(
|
|
gh api /orgs/coder/packages/container/coder-preview/versions |
|
|
jq -r --arg tag "pr${PR_NUMBER}" '.[] |
|
|
select(.metadata.container.tags == [$tag]) |
|
|
.metadata.container.tags[0]'
|
|
)
|
|
if [ -z "$foundTag" ]; then
|
|
echo "Image not found"
|
|
echo "${CODER_IMAGE_TAG} not found in ghcr.io/coder/coder-preview"
|
|
exit 1
|
|
else
|
|
echo "Image found"
|
|
echo "$foundTag tag found in ghcr.io/coder/coder-preview"
|
|
fi
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Add DNS record to Cloudflare
|
|
if: needs.get_info.outputs.NEW == 'true'
|
|
run: |
|
|
curl -X POST "https://api.cloudflare.com/client/v4/zones/${{ secrets.PR_DEPLOYMENTS_ZONE_ID }}/dns_records" \
|
|
-H "Authorization: Bearer ${{ secrets.PR_DEPLOYMENTS_CLOUDFLARE_API_TOKEN }}" \
|
|
-H "Content-Type:application/json" \
|
|
--data '{"type":"CNAME","name":"*.'"${PR_HOSTNAME}"'","content":"'"${PR_HOSTNAME}"'","ttl":1,"proxied":false}'
|
|
|
|
- name: Create PR namespace
|
|
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
|
|
run: |
|
|
set -euo pipefail
|
|
# try to delete the namespace, but don't fail if it doesn't exist
|
|
kubectl delete namespace "pr${PR_NUMBER}" || true
|
|
kubectl create namespace "pr${PR_NUMBER}"
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- name: Check and Create Certificate
|
|
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
|
|
run: |
|
|
# Using kubectl to check if a Certificate resource already exists
|
|
# we are doing this to avoid letsenrypt rate limits
|
|
if ! kubectl get certificate "pr${PR_NUMBER}-tls" -n pr-deployment-certs > /dev/null 2>&1; then
|
|
echo "Certificate doesn't exist. Creating a new one."
|
|
envsubst < ./.github/pr-deployments/certificate.yaml | kubectl apply -f -
|
|
else
|
|
echo "Certificate exists. Skipping certificate creation."
|
|
fi
|
|
echo "Copy certificate from pr-deployment-certs to pr${PR_NUMBER} namespace"
|
|
until kubectl get secret "pr${PR_NUMBER}-tls" -n pr-deployment-certs &> /dev/null
|
|
do
|
|
echo "Waiting for secret pr${PR_NUMBER}-tls to be created..."
|
|
sleep 5
|
|
done
|
|
(
|
|
kubectl get secret "pr${PR_NUMBER}-tls" -n pr-deployment-certs -o json |
|
|
jq 'del(.metadata.namespace,.metadata.creationTimestamp,.metadata.resourceVersion,.metadata.selfLink,.metadata.uid,.metadata.managedFields)' |
|
|
kubectl -n "pr${PR_NUMBER}" apply -f -
|
|
)
|
|
|
|
- name: Set up PostgreSQL database
|
|
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
|
|
run: |
|
|
helm repo add bitnami https://charts.bitnami.com/bitnami
|
|
helm install coder-db bitnami/postgresql \
|
|
--namespace "pr${PR_NUMBER}" \
|
|
--set image.repository=bitnamilegacy/postgresql \
|
|
--set auth.username=coder \
|
|
--set auth.password=coder \
|
|
--set auth.database=coder \
|
|
--set persistence.size=10Gi
|
|
kubectl create secret generic coder-db-url -n "pr${PR_NUMBER}" \
|
|
--from-literal=url="postgres://coder:coder@coder-db-postgresql.pr${PR_NUMBER}.svc.cluster.local:5432/coder?sslmode=disable"
|
|
|
|
- name: Create a service account, role, and rolebinding for the PR namespace
|
|
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
|
|
run: |
|
|
set -euo pipefail
|
|
# Create service account, role, rolebinding
|
|
envsubst < ./.github/pr-deployments/rbac.yaml | kubectl apply -f -
|
|
|
|
- name: Create values.yaml
|
|
env:
|
|
EXPERIMENTS: ${{ github.event.inputs.experiments }}
|
|
PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_ID: ${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_ID }}
|
|
PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_SECRET: ${{ secrets.PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_SECRET }}
|
|
run: |
|
|
set -euo pipefail
|
|
envsubst < ./.github/pr-deployments/values.yaml > ./pr-deploy-values.yaml
|
|
|
|
- name: Install/Upgrade Helm chart
|
|
run: |
|
|
set -euo pipefail
|
|
helm dependency update --skip-refresh ./helm/coder
|
|
helm upgrade --install "pr${PR_NUMBER}" ./helm/coder \
|
|
--namespace "pr${PR_NUMBER}" \
|
|
--values ./pr-deploy-values.yaml \
|
|
--force
|
|
|
|
- name: Install coder-logstream-kube
|
|
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
|
|
run: |
|
|
helm repo add coder-logstream-kube https://helm.coder.com/logstream-kube
|
|
helm upgrade --install coder-logstream-kube coder-logstream-kube/coder-logstream-kube \
|
|
--namespace "pr${PR_NUMBER}" \
|
|
--set url="https://${PR_HOSTNAME}"
|
|
|
|
- name: Get Coder binary
|
|
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
DEST="${HOME}/coder"
|
|
URL="https://${PR_HOSTNAME}/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
|
|
sudo mv "${DEST}" /usr/local/bin/coder
|
|
|
|
- name: Create first user
|
|
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
|
|
id: setup_deployment
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
# 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"
|
|
|
|
coder login \
|
|
--first-user-username "pr${PR_NUMBER}-admin" \
|
|
--first-user-email "pr${PR_NUMBER}@coder.com" \
|
|
--first-user-password "$password" \
|
|
--first-user-trial=false \
|
|
--use-token-as-session \
|
|
"https://${PR_HOSTNAME}"
|
|
|
|
# Create a user for the github.actor
|
|
# TODO: update once https://github.com/coder/coder/issues/15466 is resolved
|
|
# coder users create \
|
|
# --username ${GITHUB_ACTOR} \
|
|
# --login-type github
|
|
|
|
# promote the user to admin role
|
|
# coder org members edit-role ${GITHUB_ACTOR} organization-admin
|
|
# TODO: update once https://github.com/coder/internal/issues/207 is resolved
|
|
|
|
- name: Send Slack notification
|
|
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
|
|
run: |
|
|
curl -s -o /dev/null -X POST -H 'Content-type: application/json' \
|
|
-d \
|
|
'{
|
|
"pr_number": "'"${PR_NUMBER}"'",
|
|
"pr_url": "'"${PR_URL}"'",
|
|
"pr_title": "'"${PR_TITLE}"'",
|
|
"pr_access_url": "'"https://${PR_HOSTNAME}"'",
|
|
"pr_username": "'"pr${PR_NUMBER}-admin"'",
|
|
"pr_email": "'"pr${PR_NUMBER}@coder.com"'",
|
|
"pr_password": "'"${PASSWORD}"'",
|
|
"pr_actor": "'"${GITHUB_ACTOR}"'"
|
|
}' \
|
|
${{ secrets.PR_DEPLOYMENTS_SLACK_WEBHOOK }}
|
|
echo "Slack notification sent"
|
|
env:
|
|
PASSWORD: ${{ steps.setup_deployment.outputs.password }}
|
|
|
|
- name: Find Comment
|
|
uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4.0.0
|
|
id: fc
|
|
with:
|
|
issue-number: ${{ env.PR_NUMBER }}
|
|
comment-author: "github-actions[bot]"
|
|
body-includes: ":rocket:"
|
|
direction: last
|
|
|
|
- name: Comment on PR
|
|
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
|
|
env:
|
|
STATUS: ${{ needs.get_info.outputs.NEW == 'true' && 'Created' || 'Updated' }}
|
|
with:
|
|
issue-number: ${{ env.PR_NUMBER }}
|
|
edit-mode: replace
|
|
comment-id: ${{ steps.fc.outputs.comment-id }}
|
|
body: |
|
|
---
|
|
:heavy_check_mark: PR ${{ env.PR_NUMBER }} ${{ env.STATUS }} successfully.
|
|
:rocket: Access the credentials [here](${{ secrets.PR_DEPLOYMENTS_SLACK_CHANNEL_URL }}).
|
|
---
|
|
cc: @${{ github.actor }}
|
|
reactions: rocket
|
|
reactions-edit-mode: replace
|
|
|
|
- name: Create template and workspace
|
|
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
|
|
run: |
|
|
set -euo pipefail
|
|
cd .github/pr-deployments/template
|
|
coder templates push -y --variable "namespace=pr${PR_NUMBER}" kubernetes
|
|
|
|
# Create workspace
|
|
coder create --template="kubernetes" kube --parameter cpu=2 --parameter memory=4 --parameter home_disk_size=2 -y
|
|
coder stop kube -y
|