2024-01-16 14:38:05 +00:00
|
|
|
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)!
|
|
|
|
}
|
2024-01-31 16:37:51 +00:00
|
|
|
|
|
|
|
let prResult
|
|
|
|
try {
|
|
|
|
prResult = await github.getOctokit(env.GH_TOKEN).rest.pulls.get({
|
|
|
|
owner: 'tldraw',
|
|
|
|
repo: 'tldraw',
|
|
|
|
pull_number: prNumber,
|
|
|
|
})
|
|
|
|
} catch (err: any) {
|
|
|
|
if (err.status === 404) {
|
|
|
|
_isPrClosedCache.set(prNumber, true)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
throw err
|
|
|
|
}
|
2024-01-16 14:38:05 +00:00
|
|
|
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) {
|
2024-01-31 16:37:51 +00:00
|
|
|
throw new Error('Failed to delete worker ' + JSON.stringify(await res.json()))
|
2024-01-16 14:38:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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`)
|
|
|
|
}
|
|
|
|
}
|
2024-01-31 16:37:51 +00:00
|
|
|
|
|
|
|
nicelog('Done')
|
2024-01-16 14:38:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
main()
|
|
|
|
|
|
|
|
// clean up cloudflare preview deploys
|