[SG-33486] Periodically clean up old preview services (#33859)

* feat: prepare github action and script to clean up render.com pr preview

Co-authored-by: gitstart-sourcegraph <gitstart@users.noreply.github.com>
This commit is contained in:
GitStart-SourceGraph 2022-04-20 20:14:57 +05:30 committed by GitHub
parent 357dc4d5a9
commit 403ef1afbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 132 additions and 4 deletions

View File

@ -2,10 +2,15 @@ name: PR Preview
on:
pull_request:
types: [opened, synchronize, closed]
types: [closed]
schedule:
# At minute 0 past every 12th hour
- cron: '0 */12 * * *'
jobs:
preview-deployment:
remove-pr-preview-app:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
@ -15,11 +20,26 @@ jobs:
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 }}
clean-up-inactive-pr-preview-apps:
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 1
- name: Clean up inactive PR preview apps
# This job removes PR preview apps which don't have any updates in last 5 days
run: ./dev/ci/render-pr-preview-cleanup.sh -e 5
env:
RENDER_COM_API_KEY: ${{ secrets.RENDER_COM_API_KEY }}
RENDER_COM_OWNER_ID: ${{ secrets.RENDER_COM_OWNER_ID }}

View File

@ -0,0 +1,96 @@
#!/usr/bin/env bash
set -e
# Env variables:
# - RENDER_COM_API_KEY (required)
# - RENDER_COM_OWNER_ID (required)
print_usage() {
echo "Usage: [-e EXPIRE_AFTER_DAYS]" 1>&2
echo "-e: Number of days since the last time PR previews were updated (defaults: 5 days)" 1>&2
}
urlencode() {
echo "$1" | curl -Gso /dev/null -w "%{url_effective}" --data-urlencode @- "" | cut -c 3- | sed -e 's/%0A//'
}
get_days_ago_in_ISO() {
unameOut="$(uname -s)"
case "${unameOut}" in
Linux*) machine=Linux ;;
Darwin*) machine=Mac ;;
*) ;;
esac
# `date` in macos is different from Linux
if [[ $machine = "Mac" ]]; then
date -u "-v-$1d" +"%Y-%m-%dT%H:%M:%SZ"
else
date -d "$1 days ago" +"%Y-%m-%dT%H:%M:%SZ"
fi
}
expire_after_days="5"
while getopts 'e:' flag; do
case "${flag}" in
e) expire_after_days="${OPTARG}" ;;
*)
print_usage
exit 1
;;
esac
done
render_api_key="${RENDER_COM_API_KEY}"
render_owner_id="${RENDER_COM_OWNER_ID}"
expiration_date_ISO=$(get_days_ago_in_ISO "$expire_after_days")
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
# Get id list of services which are created before expiration date
# We should take care about render.com rate limit (https://api-docs.render.com/reference/rate-limiting)
# GET 100/minute
# DELETE 30/minute
cursor=""
ids=()
# Collect ids of all services which are updated before expiration date and `not_suspended`
# We use `updatedBefore` since the services are updated on deployments
for (( ; ; )); do
# render.com API > List services: https://api-docs.render.com/reference/get-services
service_list=$(curl -sSf --request GET \
--url "https://api.render.com/v1/services?type=web_service&updatedBefore=$(urlencode "$expiration_date_ISO")&suspended=not_suspended&ownerId=${render_owner_id}&limit=100&cursor=${cursor}" \
--header 'Accept: application/json' \
--header "Authorization: Bearer ${render_api_key}")
num_of_records=$(echo "$service_list" | jq -r '. | length')
if [ "${num_of_records}" == "0" ]; then
break
fi
while IFS='' read -r line; do
ids+=("$line")
done < <(echo "$service_list" | jq -r '.[].service.id')
cursor=$(echo "$service_list" | jq -r '.[-1].cursor')
done
for service_id in "${ids[@]}"; do
echo "Deleting service: $service_id"
curl -sSf -o /dev/null --request DELETE \
--url "https://api.render.com/v1/services/${service_id}" \
--header 'Accept: application/json' \
--header "Authorization: Bearer ${render_api_key}"
# To make sure we don't reach the limitation of 30/minute DELETE requests
sleep 2
done

View File

@ -28,3 +28,15 @@ We do not create client PR previews [if Go or GraphQL is changed](https://source
## Why does a search query fail with an error?
The preview app is deployed with `SOURCEGRAPHDOTCOM_MODE=false`, which means that the user should be authenticated to use all web application features similar to [the dogfood instance](https://k8s.sgdev.org/). Make sure that you're logged in. If it doesn't fix the issue, please report it in Slack.
## Why is my preview inactive?
Previews are made inactive, when they exceeds the preview liftime. This is done to save resource (which is required to keep preview active over an extended period) from beign spent on redundant previews.
## Where to find the script that cleans up previews?
The preview cleanup script is located [here](https://sourcegraph.com/github.com/sourcegraph/sourcegraph/-/blob/dev/ci/render-pr-preview-cleanup.sh)
## What is the default cleanup schedule and the default preview lifetime?
The Default cleanup schedule runs every 12th hour, where default preview lifetime is 5 days. This can be modified through the `-e` (e.g `-e 5` for 5 days) flag passed to the preview script. Preview would also be removed once a PR gets closed or merged.