mirror of https://github.com/coder/coder.git
ci: upgrade pr deployments workflow (#8924)
This commit is contained in:
parent
4d8152d543
commit
114ad4624e
|
@ -0,0 +1,13 @@
|
|||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: pr${PR_NUMBER}-tls
|
||||
namespace: pr-deployment-certs
|
||||
spec:
|
||||
secretName: pr${PR_NUMBER}-tls
|
||||
issuerRef:
|
||||
name: letsencrypt
|
||||
kind: ClusterIssuer
|
||||
dnsNames:
|
||||
- "${PR_HOSTNAME}"
|
||||
- "*.${PR_HOSTNAME}"
|
|
@ -0,0 +1,31 @@
|
|||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: coder-workspace-pr${PR_NUMBER}
|
||||
namespace: pr${PR_NUMBER}
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: coder-workspace-pr${PR_NUMBER}
|
||||
namespace: pr${PR_NUMBER}
|
||||
rules:
|
||||
- apiGroups: ["*"]
|
||||
resources: ["*"]
|
||||
verbs: ["*"]
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: coder-workspace-pr${PR_NUMBER}
|
||||
namespace: pr${PR_NUMBER}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: coder-workspace-pr${PR_NUMBER}
|
||||
namespace: pr${PR_NUMBER}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: coder-workspace-pr${PR_NUMBER}
|
|
@ -0,0 +1,313 @@
|
|||
terraform {
|
||||
required_providers {
|
||||
coder = {
|
||||
source = "coder/coder"
|
||||
version = "~> 0.11.0"
|
||||
}
|
||||
kubernetes = {
|
||||
source = "hashicorp/kubernetes"
|
||||
version = "~> 2.22"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "coder" {
|
||||
}
|
||||
|
||||
variable "namespace" {
|
||||
type = string
|
||||
description = "The Kubernetes namespace to create workspaces in (must exist prior to creating workspaces)"
|
||||
}
|
||||
|
||||
data "coder_parameter" "cpu" {
|
||||
name = "cpu"
|
||||
display_name = "CPU"
|
||||
description = "The number of CPU cores"
|
||||
default = "2"
|
||||
icon = "/icon/memory.svg"
|
||||
mutable = true
|
||||
option {
|
||||
name = "2 Cores"
|
||||
value = "2"
|
||||
}
|
||||
option {
|
||||
name = "4 Cores"
|
||||
value = "4"
|
||||
}
|
||||
option {
|
||||
name = "6 Cores"
|
||||
value = "6"
|
||||
}
|
||||
option {
|
||||
name = "8 Cores"
|
||||
value = "8"
|
||||
}
|
||||
}
|
||||
|
||||
data "coder_parameter" "memory" {
|
||||
name = "memory"
|
||||
display_name = "Memory"
|
||||
description = "The amount of memory in GB"
|
||||
default = "2"
|
||||
icon = "/icon/memory.svg"
|
||||
mutable = true
|
||||
option {
|
||||
name = "2 GB"
|
||||
value = "2"
|
||||
}
|
||||
option {
|
||||
name = "4 GB"
|
||||
value = "4"
|
||||
}
|
||||
option {
|
||||
name = "6 GB"
|
||||
value = "6"
|
||||
}
|
||||
option {
|
||||
name = "8 GB"
|
||||
value = "8"
|
||||
}
|
||||
}
|
||||
|
||||
data "coder_parameter" "home_disk_size" {
|
||||
name = "home_disk_size"
|
||||
display_name = "Home disk size"
|
||||
description = "The size of the home disk in GB"
|
||||
default = "10"
|
||||
type = "number"
|
||||
icon = "/emojis/1f4be.png"
|
||||
mutable = false
|
||||
validation {
|
||||
min = 1
|
||||
max = 99999
|
||||
}
|
||||
}
|
||||
|
||||
provider "kubernetes" {
|
||||
config_path = null
|
||||
}
|
||||
|
||||
data "coder_workspace" "me" {}
|
||||
|
||||
resource "coder_agent" "main" {
|
||||
os = "linux"
|
||||
arch = "amd64"
|
||||
startup_script_timeout = 180
|
||||
startup_script = <<-EOT
|
||||
set -e
|
||||
|
||||
# install and start code-server
|
||||
curl -fsSL https://code-server.dev/install.sh | sh -s -- --method=standalone --prefix=/tmp/code-server
|
||||
/tmp/code-server/bin/code-server --auth none --port 13337 >/tmp/code-server.log 2>&1 &
|
||||
|
||||
EOT
|
||||
|
||||
# The following metadata blocks are optional. They are used to display
|
||||
# information about your workspace in the dashboard. You can remove them
|
||||
# if you don't want to display any information.
|
||||
# For basic resources, you can use the `coder stat` command.
|
||||
# If you need more control, you can write your own script.
|
||||
metadata {
|
||||
display_name = "CPU Usage"
|
||||
key = "0_cpu_usage"
|
||||
script = "coder stat cpu"
|
||||
interval = 10
|
||||
timeout = 1
|
||||
}
|
||||
|
||||
metadata {
|
||||
display_name = "RAM Usage"
|
||||
key = "1_ram_usage"
|
||||
script = "coder stat mem"
|
||||
interval = 10
|
||||
timeout = 1
|
||||
}
|
||||
|
||||
metadata {
|
||||
display_name = "Home Disk"
|
||||
key = "3_home_disk"
|
||||
script = "coder stat disk --path $${HOME}"
|
||||
interval = 60
|
||||
timeout = 1
|
||||
}
|
||||
|
||||
metadata {
|
||||
display_name = "CPU Usage (Host)"
|
||||
key = "4_cpu_usage_host"
|
||||
script = "coder stat cpu --host"
|
||||
interval = 10
|
||||
timeout = 1
|
||||
}
|
||||
|
||||
metadata {
|
||||
display_name = "Memory Usage (Host)"
|
||||
key = "5_mem_usage_host"
|
||||
script = "coder stat mem --host"
|
||||
interval = 10
|
||||
timeout = 1
|
||||
}
|
||||
|
||||
metadata {
|
||||
display_name = "Load Average (Host)"
|
||||
key = "6_load_host"
|
||||
# get load avg scaled by number of cores
|
||||
script = <<EOT
|
||||
echo "`cat /proc/loadavg | awk '{ print $1 }'` `nproc`" | awk '{ printf "%0.2f", $1/$2 }'
|
||||
EOT
|
||||
interval = 60
|
||||
timeout = 1
|
||||
}
|
||||
}
|
||||
|
||||
# code-server
|
||||
resource "coder_app" "code-server" {
|
||||
agent_id = coder_agent.main.id
|
||||
slug = "code-server"
|
||||
display_name = "code-server"
|
||||
icon = "/icon/code.svg"
|
||||
url = "http://localhost:13337?folder=/home/coder"
|
||||
subdomain = false
|
||||
share = "owner"
|
||||
|
||||
healthcheck {
|
||||
url = "http://localhost:13337/healthz"
|
||||
interval = 3
|
||||
threshold = 10
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_persistent_volume_claim" "home" {
|
||||
metadata {
|
||||
name = "coder-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}-home"
|
||||
namespace = var.namespace
|
||||
labels = {
|
||||
"app.kubernetes.io/name" = "coder-pvc"
|
||||
"app.kubernetes.io/instance" = "coder-pvc-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
|
||||
"app.kubernetes.io/part-of" = "coder"
|
||||
//Coder-specific labels.
|
||||
"com.coder.resource" = "true"
|
||||
"com.coder.workspace.id" = data.coder_workspace.me.id
|
||||
"com.coder.workspace.name" = data.coder_workspace.me.name
|
||||
"com.coder.user.id" = data.coder_workspace.me.owner_id
|
||||
"com.coder.user.username" = data.coder_workspace.me.owner
|
||||
}
|
||||
annotations = {
|
||||
"com.coder.user.email" = data.coder_workspace.me.owner_email
|
||||
}
|
||||
}
|
||||
wait_until_bound = false
|
||||
spec {
|
||||
access_modes = ["ReadWriteOnce"]
|
||||
resources {
|
||||
requests = {
|
||||
storage = "${data.coder_parameter.home_disk_size.value}Gi"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "kubernetes_deployment" "main" {
|
||||
count = data.coder_workspace.me.start_count
|
||||
depends_on = [
|
||||
kubernetes_persistent_volume_claim.home
|
||||
]
|
||||
wait_for_rollout = false
|
||||
metadata {
|
||||
name = "coder-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
|
||||
namespace = var.namespace
|
||||
labels = {
|
||||
"app.kubernetes.io/name" = "coder-workspace"
|
||||
"app.kubernetes.io/instance" = "coder-workspace-${lower(data.coder_workspace.me.owner)}-${lower(data.coder_workspace.me.name)}"
|
||||
"app.kubernetes.io/part-of" = "coder"
|
||||
"com.coder.resource" = "true"
|
||||
"com.coder.workspace.id" = data.coder_workspace.me.id
|
||||
"com.coder.workspace.name" = data.coder_workspace.me.name
|
||||
"com.coder.user.id" = data.coder_workspace.me.owner_id
|
||||
"com.coder.user.username" = data.coder_workspace.me.owner
|
||||
}
|
||||
annotations = {
|
||||
"com.coder.user.email" = data.coder_workspace.me.owner_email
|
||||
}
|
||||
}
|
||||
|
||||
spec {
|
||||
replicas = 1
|
||||
selector {
|
||||
match_labels = {
|
||||
"app.kubernetes.io/name" = "coder-workspace"
|
||||
}
|
||||
}
|
||||
|
||||
template {
|
||||
metadata {
|
||||
labels = {
|
||||
"app.kubernetes.io/name" = "coder-workspace"
|
||||
}
|
||||
}
|
||||
spec {
|
||||
security_context {
|
||||
run_as_user = 1000
|
||||
fs_group = 1000
|
||||
}
|
||||
|
||||
service_account_name = "coder-workspace-${var.namespace}"
|
||||
container {
|
||||
name = "dev"
|
||||
image = "bencdr/devops-tools"
|
||||
image_pull_policy = "Always"
|
||||
command = ["sh", "-c", coder_agent.main.init_script]
|
||||
security_context {
|
||||
run_as_user = "1000"
|
||||
}
|
||||
env {
|
||||
name = "CODER_AGENT_TOKEN"
|
||||
value = coder_agent.main.token
|
||||
}
|
||||
resources {
|
||||
requests = {
|
||||
"cpu" = "250m"
|
||||
"memory" = "512Mi"
|
||||
}
|
||||
limits = {
|
||||
"cpu" = "${data.coder_parameter.cpu.value}"
|
||||
"memory" = "${data.coder_parameter.memory.value}Gi"
|
||||
}
|
||||
}
|
||||
volume_mount {
|
||||
mount_path = "/home/coder"
|
||||
name = "home"
|
||||
read_only = false
|
||||
}
|
||||
}
|
||||
|
||||
volume {
|
||||
name = "home"
|
||||
persistent_volume_claim {
|
||||
claim_name = kubernetes_persistent_volume_claim.home.metadata.0.name
|
||||
read_only = false
|
||||
}
|
||||
}
|
||||
|
||||
affinity {
|
||||
// This affinity attempts to spread out all workspace pods evenly across
|
||||
// nodes.
|
||||
pod_anti_affinity {
|
||||
preferred_during_scheduling_ignored_during_execution {
|
||||
weight = 1
|
||||
pod_affinity_term {
|
||||
topology_key = "kubernetes.io/hostname"
|
||||
label_selector {
|
||||
match_expressions {
|
||||
key = "app.kubernetes.io/name"
|
||||
operator = "In"
|
||||
values = ["coder-workspace"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
coder:
|
||||
image:
|
||||
repo: "${REPO}"
|
||||
tag: "pr${PR_NUMBER}"
|
||||
pullPolicy: Always
|
||||
service:
|
||||
type: ClusterIP
|
||||
ingress:
|
||||
enable: true
|
||||
className: traefik
|
||||
host: "${PR_HOSTNAME}"
|
||||
wildcardHost: "*.${PR_HOSTNAME}"
|
||||
tls:
|
||||
enable: true
|
||||
secretName: "pr${PR_NUMBER}-tls"
|
||||
wildcardSecretName: "pr${PR_NUMBER}-tls"
|
||||
env:
|
||||
- name: "CODER_ACCESS_URL"
|
||||
value: "https://${PR_HOSTNAME}"
|
||||
- name: "CODER_WILDCARD_ACCESS_URL"
|
||||
value: "*.${PR_HOSTNAME}"
|
||||
- name: "CODER_EXPERIMENTS"
|
||||
value: "${EXPERIMENTS}"
|
||||
- name: CODER_PG_CONNECTION_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: coder-db-url
|
||||
key: url
|
||||
- name: "CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS"
|
||||
value: "true"
|
||||
- name: "CODER_OAUTH2_GITHUB_CLIENT_ID"
|
||||
value: "${PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_ID}"
|
||||
- name: "CODER_OAUTH2_GITHUB_CLIENT_SECRET"
|
||||
value: "${PR_DEPLOYMENTS_GITHUB_OAUTH_CLIENT_SECRET}"
|
||||
- name: "CODER_OAUTH2_GITHUB_ALLOWED_ORGS"
|
||||
value: "coder"
|
||||
- name: "CODER_DERP_CONFIG_URL"
|
||||
value: "https://controlplane.tailscale.com/derpmap/default"
|
|
@ -4,24 +4,28 @@
|
|||
# 3. when a PR is updated
|
||||
name: Deploy PR
|
||||
on:
|
||||
pull_request:
|
||||
types: synchronize
|
||||
push:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: "PR number"
|
||||
type: number
|
||||
required: true
|
||||
skip_build:
|
||||
description: "Skip build job"
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
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
|
||||
|
@ -29,43 +33,70 @@ env:
|
|||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
pull-requests: write
|
||||
pull-requests: write # needed for commenting on PRs
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-PR-${{ github.event.pull_request.number || github.event.inputs.pr_number }}
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
check_pr:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
PR_OPEN: ${{ steps.check_pr.outputs.pr_open }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- 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:
|
||||
if: github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request'
|
||||
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 }}
|
||||
PR_BRANCH: ${{ steps.pr_info.outputs.PR_BRANCH }}
|
||||
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.filter.outputs.all_count > steps.filter.outputs.ignored_count || steps.check_deployment.outputs.new }}
|
||||
NEW: ${{ steps.check_deployment.outputs.NEW }}
|
||||
BUILD: ${{ steps.filter.outputs.all_count > steps.filter.outputs.ignored_count || steps.check_deployment.outputs.NEW }}
|
||||
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Get PR number, title, and branch name
|
||||
id: pr_info
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
PR_NUMBER=${{ github.event.inputs.pr_number || github.event.pull_request.number }}
|
||||
PR_TITLE=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/coder/coder/pulls/$PR_NUMBER | jq -r '.title')
|
||||
PR_BRANCH=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" https://api.github.com/repos/coder/coder/pulls/$PR_NUMBER | jq -r '.head.ref')
|
||||
echo "PR_URL=https://github.com/coder/coder/pull/$PR_NUMBER" >> $GITHUB_OUTPUT
|
||||
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" >> $GITHUB_OUTPUT
|
||||
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_OUTPUT
|
||||
echo "PR_TITLE=$PR_TITLE" >> $GITHUB_OUTPUT
|
||||
echo "PR_BRANCH=$PR_BRANCH" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set required tags
|
||||
id: set_tags
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
set -euo pipefail
|
||||
echo "CODER_BASE_IMAGE_TAG=$CODER_BASE_IMAGE_TAG" >> $GITHUB_OUTPUT
|
||||
echo "CODER_IMAGE_TAG=$CODER_IMAGE_TAG" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
|
@ -74,7 +105,7 @@ jobs:
|
|||
|
||||
- name: Set up kubeconfig
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
set -euo pipefail
|
||||
mkdir -p ~/.kube
|
||||
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG }}" > ~/.kube/config
|
||||
export KUBECONFIG=~/.kube/config
|
||||
|
@ -82,53 +113,21 @@ jobs:
|
|||
- name: Check if the helm deployment already exists
|
||||
id: check_deployment
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
set -euo pipefail
|
||||
if helm status "pr${{ steps.pr_info.outputs.PR_NUMBER }}" --namespace "pr${{ steps.pr_info.outputs.PR_NUMBER }}" > /dev/null 2>&1; then
|
||||
echo "Deployment already exists. Skipping deployment."
|
||||
new=false
|
||||
NEW=false
|
||||
else
|
||||
echo "Deployment doesn't exist."
|
||||
new=true
|
||||
NEW=true
|
||||
fi
|
||||
echo "new=$new" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v2
|
||||
if: github.event_name == 'workflow_dispatch' || steps.check_deployment.outputs.NEW == 'false'
|
||||
id: fc
|
||||
with:
|
||||
issue-number: ${{ steps.pr_info.outputs.PR_NUMBER }}
|
||||
comment-author: "github-actions[bot]"
|
||||
body-includes: ":rocket:"
|
||||
direction: last
|
||||
|
||||
- name: Comment on PR
|
||||
id: comment_id
|
||||
if: github.event_name == 'workflow_dispatch' || steps.check_deployment.outputs.NEW == 'false'
|
||||
uses: peter-evans/create-or-update-comment@v3
|
||||
with:
|
||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
issue-number: ${{ steps.pr_info.outputs.PR_NUMBER }}
|
||||
edit-mode: replace
|
||||
body: |
|
||||
---
|
||||
:rocket: Deploying PR ${{ steps.pr_info.outputs.PR_NUMBER }} ...
|
||||
---
|
||||
reactions: eyes
|
||||
reactions-edit-mode: replace
|
||||
|
||||
- name: Checkout
|
||||
if: github.event_name == 'workflow_dispatch' || steps.check_deployment.outputs.NEW == 'false'
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ steps.pr_info.outputs.PR_BRANCH }}
|
||||
fetch-depth: 0
|
||||
echo "NEW=$NEW" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Check changed files
|
||||
if: github.event_name == 'workflow_dispatch' || steps.check_deployment.outputs.NEW == 'false'
|
||||
uses: dorny/paths-filter@v2
|
||||
id: filter
|
||||
with:
|
||||
base: ${{ github.ref }}
|
||||
filters: |
|
||||
all:
|
||||
- "**"
|
||||
|
@ -149,47 +148,76 @@ jobs:
|
|||
- "scripts/**/*[^D][^o][^c][^k][^e][^r][^f][^i][^l][^e][.][b][^a][^s][^e]*"
|
||||
|
||||
- name: Print number of changed files
|
||||
if: github.event_name == 'workflow_dispatch' || steps.check_deployment.outputs.NEW == 'false'
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
set -euo pipefail
|
||||
echo "Total number of changed files: ${{ steps.filter.outputs.all_count }}"
|
||||
echo "Number of ignored files: ${{ steps.filter.outputs.ignored_count }}"
|
||||
|
||||
- name: Print job outputs
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Print all outputs of this job
|
||||
echo "PR_NUMBER=${{ steps.pr_info.outputs.PR_NUMBER }}"
|
||||
echo "PR_TITLE=${{ steps.pr_info.outputs.PR_TITLE }}"
|
||||
echo "PR_URL=${{ steps.pr_info.outputs.PR_URL }}"
|
||||
echo "CODER_BASE_IMAGE_TAG=${{ steps.set_tags.outputs.CODER_BASE_IMAGE_TAG }}"
|
||||
echo "CODER_IMAGE_TAG=${{ steps.set_tags.outputs.CODER_IMAGE_TAG }}"
|
||||
echo "NEW=${{ steps.check_deployment.outputs.NEW }}"
|
||||
echo "BUILD=${{ steps.filter.outputs.all_count > steps.filter.outputs.ignored_count || steps.check_deployment.outputs.NEW || github.event.inputs.build == 'true' }}"
|
||||
echo "GITHUB_REF=${{ github.ref }}"
|
||||
|
||||
comment-pr:
|
||||
needs: [check_pr, get_info]
|
||||
if: ${{ needs.get_info.outputs.BUILD == 'true' || github.event.inputs.deploy == 'true' || github.event.inputs.build == 'true' }}
|
||||
runs-on: "ubuntu-latest"
|
||||
steps:
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v2
|
||||
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@v3
|
||||
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
|
||||
# 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
|
||||
# always run the build job if a pull_request event triggered the workflow
|
||||
if: |
|
||||
(github.event_name == 'workflow_dispatch' && github.event.inputs.skip_build == 'false') ||
|
||||
(github.event_name == 'pull_request' && needs.get_info.result == 'success' && needs.get_info.outputs.NEW == 'false')
|
||||
# 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' && 'buildjet-8vcpu-ubuntu-2204' || 'ubuntu-latest' }}
|
||||
env:
|
||||
DOCKER_CLI_EXPERIMENTAL: "enabled"
|
||||
CODER_IMAGE_TAG: ${{ needs.get_info.outputs.CODER_IMAGE_TAG }}
|
||||
PR_NUMBER: ${{ needs.get_info.outputs.PR_NUMBER }}
|
||||
PR_BRANCH: ${{ needs.get_info.outputs.PR_BRANCH }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ env.PR_BRANCH }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node
|
||||
if: needs.get_info.outputs.BUILD == 'true'
|
||||
uses: ./.github/actions/setup-node
|
||||
|
||||
- name: Setup Go
|
||||
if: needs.get_info.outputs.BUILD == 'true'
|
||||
uses: ./.github/actions/setup-go
|
||||
|
||||
- name: Setup sqlc
|
||||
if: needs.get_info.outputs.BUILD == 'true'
|
||||
uses: ./.github/actions/setup-sqlc
|
||||
|
||||
- name: GHCR Login
|
||||
if: needs.get_info.outputs.BUILD == 'true'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
|
@ -197,9 +225,8 @@ jobs:
|
|||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push Linux amd64 Docker image
|
||||
if: needs.get_info.outputs.BUILD == 'true'
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
set -euo pipefail
|
||||
go mod download
|
||||
make gen/mark-fresh
|
||||
export DOCKER_IMAGE_NO_PREREQUISITES=true
|
||||
|
@ -217,35 +244,42 @@ jobs:
|
|||
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') &&
|
||||
(github.event_name == 'workflow_dispatch' || needs.get_info.outputs.NEW == 'false')
|
||||
always() && (needs.build.result == 'success' || needs.build.result == 'skipped') &&
|
||||
(needs.get_info.outputs.BUILD == 'true' || github.event.inputs.deploy == 'true')
|
||||
runs-on: "ubuntu-latest"
|
||||
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_BRANCH: ${{ needs.get_info.outputs.PR_BRANCH }}
|
||||
PR_DEPLOYMENT_ACCESS_URL: "pr${{ needs.get_info.outputs.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
|
||||
PR_HOSTNAME: "pr${{ needs.get_info.outputs.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
|
||||
steps:
|
||||
- name: Set up kubeconfig
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
set -euo pipefail
|
||||
mkdir -p ~/.kube
|
||||
echo "${{ secrets.PR_DEPLOYMENTS_KUBECONFIG }}" > ~/.kube/config
|
||||
export KUBECONFIG=~/.kube/config
|
||||
|
||||
- name: Check if image exists
|
||||
if: needs.get_info.outputs.NEW == 'true'
|
||||
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)
|
||||
set -euo pipefail
|
||||
foundTag=$(
|
||||
gh api /orgs/coder/packages/container/coder-preview/versions |
|
||||
jq -r --arg tag "pr${{ env.PR_NUMBER }}" '.[] |
|
||||
select(.metadata.container.tags == [$tag]) |
|
||||
.metadata.container.tags[0]'
|
||||
)
|
||||
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 and try again"
|
||||
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'
|
||||
|
@ -253,43 +287,27 @@ jobs:
|
|||
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":"*.${{ env.PR_DEPLOYMENT_ACCESS_URL }}","content":"${{ env.PR_DEPLOYMENT_ACCESS_URL }}","ttl":1,"proxied":false}'
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ env.PR_BRANCH }}
|
||||
--data '{"type":"CNAME","name":"*.${{ env.PR_HOSTNAME }}","content":"${{ env.PR_HOSTNAME }}","ttl":1,"proxied":false}'
|
||||
|
||||
- name: Create PR namespace
|
||||
if: needs.get_info.outputs.NEW == 'true'
|
||||
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
set -euo pipefail
|
||||
# try to delete the namespace, but don't fail if it doesn't exist
|
||||
kubectl delete namespace "pr${{ env.PR_NUMBER }}" || true
|
||||
kubectl create namespace "pr${{ env.PR_NUMBER }}"
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Check and Create Certificate
|
||||
if: needs.get_info.outputs.NEW == 'true'
|
||||
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${{ env.PR_NUMBER }}-tls -n pr-deployment-certs > /dev/null 2>&1; then
|
||||
echo "Certificate doesn't exist. Creating a new one."
|
||||
cat <<EOF | kubectl apply -f -
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: pr${{ env.PR_NUMBER }}-tls
|
||||
namespace: pr-deployment-certs
|
||||
spec:
|
||||
secretName: pr${{ env.PR_NUMBER }}-tls
|
||||
issuerRef:
|
||||
name: letsencrypt
|
||||
kind: ClusterIssuer
|
||||
dnsNames:
|
||||
- "${{ env.PR_DEPLOYMENT_ACCESS_URL }}"
|
||||
- "*.${{ env.PR_DEPLOYMENT_ACCESS_URL }}"
|
||||
EOF
|
||||
envsubst < ./.github/pr-deployments/certificate.yaml | kubectl apply -f -
|
||||
else
|
||||
echo "Certificate exists. Skipping certificate creation."
|
||||
fi
|
||||
|
@ -306,7 +324,7 @@ jobs:
|
|||
)
|
||||
|
||||
- name: Set up PostgreSQL database
|
||||
if: needs.get_info.outputs.NEW == 'true'
|
||||
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 \
|
||||
|
@ -318,82 +336,45 @@ jobs:
|
|||
kubectl create secret generic coder-db-url -n pr${{ env.PR_NUMBER }} \
|
||||
--from-literal=url="postgres://coder:coder@coder-db-postgresql.pr${{ env.PR_NUMBER }}.svc.cluster.local:5432/coder?sslmode=disable"
|
||||
|
||||
- name: Create values.yaml
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
- 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: |
|
||||
cat <<EOF > pr-deploy-values.yaml
|
||||
coder:
|
||||
image:
|
||||
repo: ${{ env.REPO }}
|
||||
tag: pr${{ env.PR_NUMBER }}
|
||||
pullPolicy: Always
|
||||
service:
|
||||
type: ClusterIP
|
||||
ingress:
|
||||
enable: true
|
||||
className: traefik
|
||||
host: ${{ env.PR_DEPLOYMENT_ACCESS_URL }}
|
||||
wildcardHost: "*.${{ env.PR_DEPLOYMENT_ACCESS_URL }}"
|
||||
tls:
|
||||
enable: true
|
||||
secretName: pr${{ env.PR_NUMBER }}-tls
|
||||
wildcardSecretName: pr${{ env.PR_NUMBER }}-tls
|
||||
env:
|
||||
- name: "CODER_ACCESS_URL"
|
||||
value: "https://${{ env.PR_DEPLOYMENT_ACCESS_URL }}"
|
||||
- name: "CODER_WILDCARD_ACCESS_URL"
|
||||
value: "*.${{ env.PR_DEPLOYMENT_ACCESS_URL }}"
|
||||
- name: "CODER_EXPERIMENTS"
|
||||
value: "${{ github.event.inputs.experiments }}"
|
||||
- name: CODER_PG_CONNECTION_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: coder-db-url
|
||||
key: url
|
||||
- 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
|
||||
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 -euxo pipefail
|
||||
if [[ ${{ github.event_name }} == "workflow_dispatch" ]]; then
|
||||
helm upgrade --install "pr${{ env.PR_NUMBER }}" ./helm \
|
||||
--namespace "pr${{ env.PR_NUMBER }}" \
|
||||
--values ./pr-deploy-values.yaml \
|
||||
--force
|
||||
else
|
||||
if [[ ${{ needs.get_info.outputs.BUILD }} == "true" ]]; then
|
||||
helm upgrade --install "pr${{ env.PR_NUMBER }}" ./helm \
|
||||
--namespace "pr${{ env.PR_NUMBER }}" \
|
||||
--reuse-values \
|
||||
--force
|
||||
else
|
||||
echo "Skipping helm upgrade, as there is no new image to deploy"
|
||||
fi
|
||||
fi
|
||||
set -euo pipefail
|
||||
helm upgrade --install "pr${{ env.PR_NUMBER }}" ./helm/coder \
|
||||
--namespace "pr${{ env.PR_NUMBER }}" \
|
||||
--values ./pr-deploy-values.yaml \
|
||||
--force
|
||||
|
||||
- name: Install coder-logstream-kube
|
||||
if: needs.get_info.outputs.NEW == 'true'
|
||||
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${{ env.PR_NUMBER }}" \
|
||||
--set url="https://pr${{ env.PR_NUMBER }}.${{ secrets.PR_DEPLOYMENTS_DOMAIN }}"
|
||||
--set url="https://${{ env.PR_HOSTNAME }}"
|
||||
|
||||
- name: Get Coder binary
|
||||
if: needs.get_info.outputs.NEW == 'true'
|
||||
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
set -euo pipefail
|
||||
|
||||
DEST="${HOME}/coder"
|
||||
URL="https://${{ env.PR_DEPLOYMENT_ACCESS_URL }}/bin/coder-linux-amd64"
|
||||
URL="https://${{ env.PR_HOSTNAME }}/bin/coder-linux-amd64"
|
||||
|
||||
mkdir -p "$(dirname ${DEST})"
|
||||
|
||||
|
@ -414,10 +395,10 @@ jobs:
|
|||
mv "${DEST}" /usr/local/bin/coder
|
||||
|
||||
- name: Create first user, template and workspace
|
||||
if: needs.get_info.outputs.NEW == 'true'
|
||||
if: needs.get_info.outputs.NEW == 'true' || github.event.inputs.deploy == 'true'
|
||||
id: setup_deployment
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
set -euo pipefail
|
||||
|
||||
# Create first user
|
||||
|
||||
|
@ -429,28 +410,24 @@ jobs:
|
|||
echo "password=$password" >> $GITHUB_OUTPUT
|
||||
|
||||
coder login \
|
||||
--first-user-username test \
|
||||
--first-user-username coder \
|
||||
--first-user-email pr${{ env.PR_NUMBER }}@coder.com \
|
||||
--first-user-password $password \
|
||||
--first-user-trial \
|
||||
--use-token-as-session \
|
||||
https://${{ env.PR_DEPLOYMENT_ACCESS_URL }}
|
||||
https://${{ env.PR_HOSTNAME }}
|
||||
|
||||
# Create template
|
||||
coder templates init --id kubernetes && cd ./kubernetes/ && coder templates create -y --variable namespace=pr${{ env.PR_NUMBER }}
|
||||
cd ./.github/pr-deployments/template
|
||||
terraform init
|
||||
coder templates create -y --variable namespace=pr${{ env.PR_NUMBER }} kubernetes
|
||||
|
||||
# Create workspace
|
||||
cat <<EOF > workspace.yaml
|
||||
cpu: "2"
|
||||
memory: "4"
|
||||
home_disk_size: "2"
|
||||
EOF
|
||||
|
||||
coder create --template="kubernetes" test --rich-parameter-file ./workspace.yaml -y
|
||||
coder stop test -y
|
||||
coder create --template="kubernetes" kube --parameter cpu=2 --parameter memory=4 --parameter home_disk_size=2 -y
|
||||
coder stop kube -y
|
||||
|
||||
- name: Send Slack notification
|
||||
if: needs.get_info.outputs.NEW == 'true'
|
||||
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 \
|
||||
|
@ -458,7 +435,7 @@ jobs:
|
|||
"pr_number": "'"${{ env.PR_NUMBER }}"'",
|
||||
"pr_url": "'"${{ env.PR_URL }}"'",
|
||||
"pr_title": "'"${{ env.PR_TITLE }}"'",
|
||||
"pr_access_url": "'"https://${{ env.PR_DEPLOYMENT_ACCESS_URL }}"'",
|
||||
"pr_access_url": "'"https://${{ env.PR_HOSTNAME }}"'",
|
||||
"pr_username": "'"test"'",
|
||||
"pr_email": "'"pr${{ env.PR_NUMBER }}@coder.com"'",
|
||||
"pr_password": "'"${{ steps.setup_deployment.outputs.password }}"'",
|
||||
|
|
|
@ -84,11 +84,12 @@ You can test your changes by creating a PR deployment. There are two ways to do
|
|||
|
||||
1. By running `./scripts/deploy-pr.sh`
|
||||
2. By manually triggering the [`pr-deploy.yaml`](https://github.com/coder/coder/actions/workflows/pr-deploy.yaml) GitHub Action workflow
|
||||
![Deploy PR manually](./images/pr-deploy-manual.png)
|
||||
![Deploy PR manually](./images/deploy-pr-manually.png)
|
||||
|
||||
#### Available options
|
||||
|
||||
- `-s` or `--skip-build`, force prevents the build of the Docker image.(generally not needed as we are intelligently checking if the image needs to be built)
|
||||
- `-d` or `--deploy`, force deploys the PR by deleting the existing deployment.
|
||||
- `-b` or `--build`, force builds the Docker image. (generally not needed as we are intelligently checking if the image needs to be built)
|
||||
- `-e EXPERIMENT1,EXPERIMENT2` or `--experiments EXPERIMENT1,EXPERIMENT2`, will enable the specified experiments. (defaults to `*`)
|
||||
- `-n` or `--dry-run` will display the context without deployment. e.g., branch name and PR number, etc.
|
||||
- `-y` or `--yes`, will skip the CLI confirmation prompt.
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
Binary file not shown.
Before Width: | Height: | Size: 26 KiB |
|
@ -1,21 +1,26 @@
|
|||
#!/usr/bin/env bash
|
||||
# Usage: ./deploy-pr.sh [--skip-build -s] [--dry-run -n] [--yes -y]
|
||||
# Usage: ./deploy-pr.sh [--dry-run -n] [--yes -y] [--experiments -e <experiments>] [--build -b] [--deploy -d]
|
||||
# deploys the current branch to a PR environment and posts login credentials to
|
||||
# [#pr-deployments](https://codercom.slack.com/archives/C05DNE982E8) Slack channel
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# default settings
|
||||
skipBuild=false
|
||||
dryRun=false
|
||||
confirm=true
|
||||
build=false
|
||||
deploy=false
|
||||
experiments=""
|
||||
|
||||
# parse arguments
|
||||
while (("$#")); do
|
||||
case "$1" in
|
||||
-s | --skip-build)
|
||||
skipBuild=true
|
||||
-b | --build)
|
||||
build=true
|
||||
shift
|
||||
;;
|
||||
-d | --deploy)
|
||||
deploy=true
|
||||
shift
|
||||
;;
|
||||
-n | --dry-run)
|
||||
|
@ -63,30 +68,20 @@ fi
|
|||
branchName=$(gh pr view --json headRefName | jq -r .headRefName)
|
||||
prNumber=$(gh pr view --json number | jq -r .number)
|
||||
|
||||
if $skipBuild; then
|
||||
#check if the image exists
|
||||
foundTag=$(curl -fsSL https://github.com/coder/coder/pkgs/container/coder-preview | grep -o "$prNumber" | head -n 1) || true
|
||||
echo "foundTag is: '${foundTag}'"
|
||||
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
|
||||
fi
|
||||
|
||||
if $dryRun; then
|
||||
if [[ "$dryRun" = true ]]; then
|
||||
echo "dry run"
|
||||
echo "branchName: ${branchName}"
|
||||
echo "prNumber: ${prNumber}"
|
||||
echo "skipBuild: ${skipBuild}"
|
||||
echo "experiments: ${experiments}"
|
||||
echo "build: ${build}"
|
||||
echo "deploy: ${deploy}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "branchName: ${branchName}"
|
||||
echo "prNumber: ${prNumber}"
|
||||
echo "skipBuild: ${skipBuild}"
|
||||
echo "experiments: ${experiments}"
|
||||
echo "build: ${build}"
|
||||
echo "deploy: ${deploy}"
|
||||
|
||||
gh workflow run pr-deploy.yaml --ref "${branchName}" -f "pr_number=${prNumber}" -f "skip_build=${skipBuild}" -f "experiments=${experiments}"
|
||||
gh workflow run pr-deploy.yaml --ref "${branchName}" -f "pr_number=${prNumber}" -f "experiments=${experiments}" -f "build=${build}" -f "deploy=${deploy}"
|
||||
|
|
Loading…
Reference in New Issue