From f1163733aaf2425a1906825ca72114bca1208db1 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Mon, 31 Jul 2023 11:10:34 -0400 Subject: [PATCH] Purge old deployment environments (#40027) --- .../purge-old-deployment-environments.js | 65 +++++++++++++++++++ .../purge-old-deployment-environments.yml | 43 ++++++++++++ 2 files changed, 108 insertions(+) create mode 100755 .github/actions-scripts/purge-old-deployment-environments.js create mode 100644 .github/workflows/purge-old-deployment-environments.yml diff --git a/.github/actions-scripts/purge-old-deployment-environments.js b/.github/actions-scripts/purge-old-deployment-environments.js new file mode 100755 index 0000000000..aeb48f80e2 --- /dev/null +++ b/.github/actions-scripts/purge-old-deployment-environments.js @@ -0,0 +1,65 @@ +#!/usr/bin/env node + +import assert from 'node:assert/strict' + +import { getOctokit } from '@actions/github' + +main() +async function main() { + const DRY_RUN = Boolean(JSON.parse(process.env.DRY_RUN || 'false')) + const MAX_DELETIONS = parseInt(JSON.parse(process.env.MAX_DELETIONS || '10')) + const MIN_AGE_DAYS = parseInt(process.env.MIN_AGE_DAYS || '90', 10) + + const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/') + if (!owner || !repo) { + throw new Error('GITHUB_REPOSITORY environment variable not set') + } + const token = process.env.GITHUB_TOKEN + if (!token) { + throw new Error(`GITHUB_TOKEN environment variable not set`) + } + const github = getOctokit(token) + + // The sort order is not explicitly listed for this API endpoint. + // In practice it appears to list those that are oldest first. + // But to guarantee that it reaches the oldest, we paginate over + // all of them. + const environments = await github.paginate('GET /repos/{owner}/{repo}/environments', { + owner, + repo, + }) + + let countDeletions = 0 + for (const environment of environments) { + const ageDays = (Date.now() - Date.parse(environment.created_at)) / 1000 / 60 / 60 / 24 + if (ageDays > MIN_AGE_DAYS) { + console.log( + `Deleting environment ${environment.name} created ${Math.ceil(ageDays)} days ago`, + DRY_RUN ? '(DRY RUN)' : '', + ) + if (!DRY_RUN) { + const { status } = await github.request( + 'DELETE /repos/{owner}/{repo}/environments/{name}', + { + owner, + repo, + name: environment.name, + }, + ) + assert(status === 204, `Expected status 204, got ${status}`) + } + countDeletions++ + if (MAX_DELETIONS && countDeletions >= MAX_DELETIONS) { + console.log(`Reached max number of deletions: ${MAX_DELETIONS}`) + break + } + } else { + console.log( + `Environment ${environment.name} (${environment.id}) created ${Math.ceil( + ageDays, + )} days ago, is *not* old enough`, + ) + } + } + console.log(`Deleted ${countDeletions} environments`, DRY_RUN ? '(DRY RUN)' : '') +} diff --git a/.github/workflows/purge-old-deployment-environments.yml b/.github/workflows/purge-old-deployment-environments.yml new file mode 100644 index 0000000000..b101d22929 --- /dev/null +++ b/.github/workflows/purge-old-deployment-environments.yml @@ -0,0 +1,43 @@ +name: Purge old deployment environments + +# **What it does**: +# Deletes old deployment environments. A deployment environment exists +# for the sake of a Azure Preview environment. Those Azure Preview environments +# and cleaned up by a separate process. +# **Why we have it**: To keep things neat and tidy. +# **Who does it impact**: Docs engineering. + +on: + workflow_dispatch: + schedule: + - cron: '20 16 * * *' # Run every day at 16:20 UTC / 8:20 PST + +permissions: + contents: write + +jobs: + purge-old-deployment-environments: + if: ${{ github.repository == 'github/docs-internal' || github.repository == 'github/docs' }} + runs-on: ubuntu-latest + steps: + - name: Checkout out repo + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + + - uses: ./.github/actions/node-npm-setup + + - name: Run purge script + if: ${{ env.FREEZE != 'true' }} + env: + GITHUB_REPOSITORY: ${{ github.repository }} + # Necessary to be able to delete deployment environments + GITHUB_TOKEN: ${{ secrets.DOCS_BOT_PAT_WORKFLOW_READORG }} + run: .github/actions-scripts/purge-old-deployment-environments.js + + - name: Send Slack notification if workflow fails + uses: someimportantcompany/github-actions-slack-message@1d367080235edfa53df415bd8e0bbab480f29bad + if: ${{ failure() && env.FREEZE != 'true' }} + with: + channel: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }} + bot-token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }} + color: failure + text: The last "Purge old deployment environments" run for ${{github.repository}} failed. See https://github.com/${{github.repository}}/actions/workflows/purge-old-deployment-environments.yml