85 lines
2.4 KiB
TypeScript
85 lines
2.4 KiB
TypeScript
|
import * as github from '@actions/github'
|
||
|
import { makeEnv } from './lib/makeEnv'
|
||
|
import { nicelog } from './lib/nicelog'
|
||
|
|
||
|
// Do not use `process.env` directly in this script. Add your variable to `makeEnv` and use it via
|
||
|
// `env` instead. This makes sure that all required env vars are present.
|
||
|
const env = makeEnv(['CLOUDFLARE_ACCOUNT_ID', 'CLOUDFLARE_API_TOKEN', 'GH_TOKEN'])
|
||
|
|
||
|
type ListWorkersResult = {
|
||
|
success: boolean
|
||
|
result: { id: string }[]
|
||
|
}
|
||
|
|
||
|
const _isPrClosedCache = new Map<number, boolean>()
|
||
|
async function isPrClosedForAWhile(prNumber: number) {
|
||
|
if (_isPrClosedCache.has(prNumber)) {
|
||
|
return _isPrClosedCache.get(prNumber)!
|
||
|
}
|
||
|
const prResult = await github.getOctokit(env.GH_TOKEN).rest.pulls.get({
|
||
|
owner: 'tldraw',
|
||
|
repo: 'tldraw',
|
||
|
pull_number: prNumber,
|
||
|
})
|
||
|
const twoDays = 1000 * 60 * 60 * 24 * 2
|
||
|
const result =
|
||
|
prResult.data.state === 'closed' &&
|
||
|
Date.now() - new Date(prResult.data.closed_at!).getTime() > twoDays
|
||
|
_isPrClosedCache.set(prNumber, result)
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
async function ListPreviewWorkerDeployments() {
|
||
|
const res = await fetch(
|
||
|
`https://api.cloudflare.com/client/v4/accounts/${env.CLOUDFLARE_ACCOUNT_ID}/workers/scripts`,
|
||
|
{
|
||
|
headers: {
|
||
|
Authorization: `Bearer ${env.CLOUDFLARE_API_TOKEN}`,
|
||
|
'Content-Type': 'application/json',
|
||
|
},
|
||
|
}
|
||
|
)
|
||
|
|
||
|
const data = (await res.json()) as ListWorkersResult
|
||
|
|
||
|
if (!data.success) {
|
||
|
throw new Error('Failed to list workers ' + JSON.stringify(data))
|
||
|
}
|
||
|
|
||
|
return data.result.map((r) => r.id).filter((id) => id.match(/^pr-(\d+)-/))
|
||
|
}
|
||
|
|
||
|
async function deletePreviewWorkerDeployment(id: string) {
|
||
|
const res = await fetch(
|
||
|
`https://api.cloudflare.com/client/v4/accounts/${env.CLOUDFLARE_ACCOUNT_ID}/workers/scripts/${id}`,
|
||
|
{
|
||
|
method: 'DELETE',
|
||
|
headers: {
|
||
|
Authorization: `Bearer ${env.CLOUDFLARE_API_TOKEN}`,
|
||
|
'Content-Type': 'application/json',
|
||
|
},
|
||
|
}
|
||
|
)
|
||
|
|
||
|
if (!res.ok) {
|
||
|
throw new Error('Failed to delete worker ' + JSON.stringify(res))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function main() {
|
||
|
const previewDeployments = await ListPreviewWorkerDeployments()
|
||
|
for (const deployment of previewDeployments) {
|
||
|
const prNumber = Number(deployment.match(/^pr-(\d+)-/)![1])
|
||
|
if (await isPrClosedForAWhile(prNumber)) {
|
||
|
nicelog(`Deleting ${deployment} because PR is closed`)
|
||
|
await deletePreviewWorkerDeployment(deployment)
|
||
|
} else {
|
||
|
nicelog(`Skipping ${deployment} because PR is still open`)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
main()
|
||
|
|
||
|
// clean up cloudflare preview deploys
|