Skip to content

Instantly share code, notes, and snippets.

@borispoehland
Last active June 8, 2024 13:44
Show Gist options
  • Save borispoehland/2738d2edd62e83f332260a80eb5a9335 to your computer and use it in GitHub Desktop.
Save borispoehland/2738d2edd62e83f332260a80eb5a9335 to your computer and use it in GitHub Desktop.
Vercel Webhook to call to pause the project after the spending limit is reached
import crypto from 'crypto'
const { INTEGRATION_SECRET, VERCEL_TEAM_ID, VERCEL_TOKEN } = process.env
function sha1(data: Buffer, secret: string): string {
return crypto.createHmac('sha1', secret).update(data).digest('hex')
}
export async function POST(request: Request) {
if (typeof INTEGRATION_SECRET != 'string') {
throw new Error('No integration secret found')
}
const rawBody = await request.text()
const rawBodyBuffer = Buffer.from(rawBody, 'utf-8')
const bodySignature = sha1(rawBodyBuffer, INTEGRATION_SECRET)
if (bodySignature !== request.headers.get('x-vercel-signature')) {
return Response.json({
code: 'invalid_signature',
error: "signature didn't match",
})
}
const { projects } = (await fetch(
`https://api.vercel.com/v9/projects?teamId=${VERCEL_TEAM_ID}`,
{
headers: {
Authorization: `Bearer ${VERCEL_TOKEN}`,
},
}
).then((res) => res.json())) as { projects: { id: string }[] }
let isSuccess = true
for (const project of projects) {
const pauseProject = await fetch(
`https://api.vercel.com/v1/projects/${project.id}/pause?teamId=${VERCEL_TEAM_ID}`,
{
headers: {
Authorization: `Bearer ${VERCEL_TOKEN}`,
},
method: 'POST',
}
)
if (!pauseProject.ok) {
// send me a backup notification to my email
console.error(pauseProject.statusText)
isSuccess = false
}
}
return Response.json({ code: 'paused_all', data: isSuccess })
}
// /api/project/pause/route.ts
import crypto from 'crypto'
const { INTEGRATION_SECRET, VERCEL_PROJECT_ID, VERCEL_TEAM_ID, VERCEL_TOKEN } =
process.env
function sha1(data: Buffer, secret: string): string {
return crypto.createHmac('sha1', secret).update(data).digest('hex')
}
export async function POST(request: Request) {
if (typeof INTEGRATION_SECRET != 'string') {
throw new Error('No integration secret found')
}
const rawBody = await request.text()
const rawBodyBuffer = Buffer.from(rawBody, 'utf-8')
const bodySignature = sha1(rawBodyBuffer, INTEGRATION_SECRET)
if (bodySignature !== request.headers.get('x-vercel-signature')) {
return Response.json({
code: 'invalid_signature',
error: "signature didn't match",
})
}
const pauseProject = await fetch(
`https://api.vercel.com/v1/projects/${VERCEL_PROJECT_ID}/pause?teamId=${VERCEL_TEAM_ID}`,
{
headers: {
Authorization: `Bearer ${VERCEL_TOKEN}`,
'Content-Type': 'application/json',
},
method: 'POST',
}
)
if (!pauseProject.ok) {
// send me a backup notification to my email
console.error(pauseProject.statusText)
}
return Response.json({ code: 'paused', data: pauseProject.ok })
}
@naeem-qv
Copy link

Do we still need to manually pause/resume projects or is it automatically handled now??
I'm told its automatic now by some YouTuber.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment