[SG-32440] Configure render.com previews for all client PRs (#32574)

Co-authored-by: gitstart-sourcegraph <gitstart@users.noreply.github.com>
This commit is contained in:
GitStart-SourceGraph 2022-03-29 16:26:03 +03:00 committed by GitHub
parent 644229db0c
commit a043e2f767
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 234 additions and 0 deletions

25
.github/workflows/pr-preview.yml vendored Normal file
View File

@ -0,0 +1,25 @@
name: PR Preview
on:
pull_request:
types: [opened, synchronize, closed]
jobs:
preview-deployment:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Delete PR preview app
if: github.event.action == 'closed'
run: ./dev/ci/render-pr-preview.sh -d
env:
RENDER_COM_API_KEY: ${{ secrets.RENDER_COM_API_KEY }}
RENDER_COM_OWNER_ID: ${{ secrets.RENDER_COM_OWNER_ID }}
BUILDKITE_PULL_REQUEST_REPO: "https://github.com/${{ github.repository }}"
BUILDKITE_BRANCH: ${{ github.head_ref }}

197
dev/ci/render-pr-preview.sh Executable file
View File

@ -0,0 +1,197 @@
#!/usr/bin/env bash
set -e
# Env variables:
# - RENDER_COM_API_KEY (required)
# - RENDER_COM_OWNER_ID (required)
# - BUILDKITE_BRANCH (optional)
# - BUILDKITE_PULL_REQUEST_REPO (optional)
# - BUILDKITE_PULL_REQUEST (optional)
# - RENDER_PREVIEW_GITHUB_TOKEN (optional)
print_usage() {
echo "Usage: [ -b BRANCH_NAME ] [ -r REPO_URL ] [ -d ]" 1>&2
echo "-b: GitHub branch name" 1>&2
echo "-r: GitHub repository url" 1>&2
echo "-d: Use this flag to delete preview apps" 1>&2
}
urlencode() {
echo "$1" | curl -Gso /dev/null -w "%{url_effective}" --data-urlencode @- "" | cut -c 3- | sed -e 's/%0A//'
}
# branch_name: BUILDKITE_BRANCH or current git branch
branch_name="${BUILDKITE_BRANCH}"
if [ -z "${branch_name}" ]; then
branch_name=$(git rev-parse --abbrev-ref HEAD)
fi
# repo_url: BUILDKITE_PULL_REQUEST_REPO or current git remote `origin` url
# Should be in formats:
# - https://github.com/sourcegraph/sourcegraph
# - git://github.com/sourcegraph/sourcegraph.git
repo_url="${BUILDKITE_PULL_REQUEST_REPO}"
if [ -z "${repo_url}" ]; then
repo_url=$(git config --get remote.origin.url)
fi
while getopts 'b:r:d' flag; do
case "${flag}" in
d) is_deleting="true" ;;
b) branch_name="${OPTARG}" ;;
r) repo_url="${OPTARG}" ;;
*)
print_usage
exit 1
;;
esac
done
# Get `{owner}/{repo}` part from GitHub repository url
if [[ "$repo_url" =~ ^(https|git):\/\/github\.com\/(.*)$ ]]; then
owner_and_repo="${BASH_REMATCH[2]//\.git/}"
else
echo "Couldn't find owner_and_repo"
exit 1
fi
render_api_key="${RENDER_COM_API_KEY}"
render_owner_id="${RENDER_COM_OWNER_ID}"
pr_number="${BUILDKITE_PULL_REQUEST}"
github_api_key="${RENDER_PREVIEW_GITHUB_TOKEN}"
if [[ -z "${render_api_key}" || -z "${render_owner_id}" ]]; then
echo "RENDER_COM_API_KEY or RENDER_COM_OWNER_ID is not set"
exit 1
fi
# App name to show on render.com dashboard and use to create
# default url: https://<app_name_slug>.onrender.com
pr_preview_app_name="sg-web-${branch_name}"
# Get service id of preview app on render.com with app name (if exists)
renderServiceId=$(curl -sS --request GET \
--url "https://api.render.com/v1/services?limit=1&type=web_service&name=$(urlencode "$pr_preview_app_name")" \
--header 'Accept: application/json' \
--header "Authorization: Bearer ${render_api_key}" | jq -r '.[].service.id')
# Delete preview app with `-d` flag set
if [ "${is_deleting}" = "true" ]; then
if [ -z "${renderServiceId}" ]; then
echo "Render app not found"
exit 0
fi
curl -sSf -o /dev/null --request DELETE \
--url "https://api.render.com/v1/services/${renderServiceId}" \
--header 'Accept: application/json' \
--header "Authorization: Bearer ${render_api_key}"
echo "Render app is deleted!"
exit 0
fi
# Create PR app if it hasn't existed yet and get the app url
if [ -z "${renderServiceId}" ]; then
echo "Creating new pr preview app..."
# New app is created with following envs
# - ENTERPRISE=1
# - NODE_ENV=production
# - PORT=3080 // render.com uses this env for mapping default https port
# - ENTERPRISE=1
# - SOURCEGRAPH_API_URL=https://k8s.sgdev.org
# - WEBPACK_SERVE_INDEX=true
pr_preview_url=$(curl -sSf --request POST \
--url https://api.render.com/v1/services \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${render_api_key}" \
--data "
{
\"autoDeploy\": \"yes\",
\"envVars\": [
{
\"key\": \"ENTERPRISE\",
\"value\": \"1\"
},
{
\"key\": \"NODE_ENV\",
\"value\": \"production\"
},
{
\"key\": \"PORT\",
\"value\": \"3080\"
},
{
\"key\": \"SOURCEGRAPH_API_URL\",
\"value\": \"https://k8s.sgdev.org\"
},
{
\"key\": \"WEBPACK_SERVE_INDEX\",
\"value\": \"true\"
}
],
\"serviceDetails\": {
\"pullRequestPreviewsEnabled\": \"no\",
\"envSpecificDetails\": {
\"buildCommand\": \"dev/ci/yarn-build.sh client/web\",
\"startCommand\": \"yarn workspace @sourcegraph/web serve:prod\"
},
\"numInstances\": 1,
\"plan\": \"starter\",
\"region\": \"oregon\",
\"env\": \"node\"
},
\"type\": \"web_service\",
\"name\": \"${pr_preview_app_name}\",
\"ownerId\": \"${render_owner_id}\",
\"repo\": \"${repo_url}\",
\"branch\": \"${branch_name}\"
}
" | jq -r '.service.serviceDetails.url')
else
echo "Found preview id: ${renderServiceId}, getting preview url..."
pr_preview_url=$(curl -sSf --request GET \
--url "https://api.render.com/v1/services/${renderServiceId}" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header "Authorization: Bearer ${render_api_key}" | jq -r '.serviceDetails.url')
fi
echo "Preview url: ${pr_preview_url}"
if [[ -n "${github_api_key}" && -n "${pr_number}" ]]; then
# GitHub pull request number and GitHub api token are set
# Appending `App Preview` section into PR description if it hasn't existed yet
github_pr_api_url="https://api.github.com/repos/${owner_and_repo}/pulls/${pr_number}"
pr_description=$(curl -sSf --request GET \
--url "${github_pr_api_url}" \
--user "apikey:${github_api_key}" \
--header 'Accept: application/vnd.github.v3+json' \
--header 'Content-Type: application/json' | jq -r '.body')
if [[ "${pr_description}" != *"## App preview"* ]]; then
echo "Updating PR #${pr_number} in ${owner_and_repo} description"
pr_description=$(echo -e "${pr_description}\n## App preview:\n- [Link](${pr_preview_url})\n" | jq -Rs .)
curl -sSf -o /dev/null --request PATCH \
--url "${github_pr_api_url}" \
--user "apikey:${github_api_key}" \
--header 'Accept: application/vnd.github.v3+json' \
--header 'Content-Type: application/json' \
--data "{ \"body\": ${pr_description} }"
else
echo "PR #${pr_number} in ${owner_and_repo} description already has \"App preview\" section"
fi
fi

View File

@ -21,6 +21,7 @@ The default run type.
- Pipeline for `Client` changes:
- **Pipeline setup**: Trigger async
- Client PR preview
- **Linters and static analysis**: Prettier, Misc linters, Yarn deduplicate lint
- **Client checks**: Puppeteer tests prep, Puppeteer tests chunk #1, Puppeteer tests chunk #2, Puppeteer tests chunk #3, Puppeteer tests chunk #4, Puppeteer tests chunk #5, Puppeteer tests chunk #6, Puppeteer tests chunk #7, Puppeteer tests chunk #8, Puppeteer tests chunk #9, Puppeteer tests finalize, Upload Storybook to Chromatic, Test (all), Build, Enterprise build, Test (client/web), Puppeteer tests for chrome extension, Test (client/browser), ESLint, Build TS, Stylelint
- Upload build trace

View File

@ -815,3 +815,12 @@ func uploadBuildeventTrace() operations.Operation {
)
}
}
// Request render.com to create client preview app for current PR
// Preview is deleted from render.com in GitHub Action when PR is closed
func prPreview() operations.Operation {
return func(pipeline *bk.Pipeline) {
pipeline.AddStep(":globe_with_meridians: Client PR preview",
bk.Cmd("dev/ci/render-pr-preview.sh"))
}
}

View File

@ -92,6 +92,8 @@ func GeneratePipeline(c Config) (*bk.Pipeline, error) {
// set it up separately from CoreTestOperations
ops.Merge(operations.NewNamedSet(operations.PipelineSetupSetName,
triggerAsync(buildOptions)))
ops.Append(prPreview())
}
ops.Merge(CoreTestOperations(c.Diff, CoreTestOperationsOptions{MinimumUpgradeableVersion: minimumUpgradeableVersion}))