Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 25 additions & 12 deletions .github/scripts/eng-analytics-weekly-digest.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ async function depotUsageSpend(startAt, endAt) {
Authorization: `Bearer ${DEPOT_TOKEN}`,
},
body: JSON.stringify({ startAt: startAt.toISOString(), endAt: endAt.toISOString() }),
signal: AbortSignal.timeout(60_000),
signal: AbortSignal.timeout(30_000),
}).catch(() => null)
if (!res?.ok) {
throw Object.assign(new Error(`Depot GetUsage failed${res ? ` with ${res.status}` : ''}`), {
Expand Down Expand Up @@ -117,6 +117,25 @@ async function spend(startAt, endAt) {
return { ...usage, total: usage.runners + usage.depotCi + usage.containerBuilds }
}

function calendarMonths(startAt, endAt) {
const ranges = []
for (let from = startAt; from < endAt; ) {
const nextMonth = new Date(Date.UTC(from.getUTCFullYear(), from.getUTCMonth() + 1, 1))
const to = nextMonth < endAt ? nextMonth : endAt
ranges.push([from, to])
from = to
}
return ranges
}

async function contractSpend(startAt, endAt) {
let used = 0
for (const [from, to] of calendarMonths(startAt, endAt)) {
used += (await spend(from, to)).total
}
return used
}

function contractDates(weekEnd) {
const start = new Date(`${DEPOT_CONTRACT_START}T00:00:00Z`)
const end = new Date(`${DEPOT_CONTRACT_END}T00:00:00Z`)
Expand Down Expand Up @@ -149,19 +168,13 @@ async function readSpend(weekStart, weekEnd) {
if (!contract) {
console.warn('Depot contract variables missing or invalid. Posting without the contract sentence.')
}
const [weeks, used] = await Promise.all([
Promise.all([spend(weekStart, weekEnd), spend(new Date(weekStart.getTime() - WEEK_MS), weekStart)]).catch(
unavailable('Spend')
),
contract &&
spend(contract.start, weekEnd)
.then((contractSpend) => contractSpend.total)
.catch(unavailable('Contract spend')),
])
if (!weeks) {
const lastWeek = await spend(weekStart, weekEnd).catch(unavailable('Spend'))
const priorWeek =
lastWeek && (await spend(new Date(weekStart.getTime() - WEEK_MS), weekStart).catch(unavailable('Spend')))
if (!priorWeek) {
return null
}
const [lastWeek, priorWeek] = weeks
const used = contract && (await contractSpend(contract.start, weekEnd).catch(unavailable('Contract spend')))
return { lastWeek, priorWeek, contract: used == null ? null : { ...contract, used } }
}

Expand Down
32 changes: 25 additions & 7 deletions .github/scripts/eng-analytics-weekly-digest.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ async function runDigest(t, { env = {}, depotUsage = DEPOT_USAGE, workflowHealth
const requests = []
const logs = []
let blocks
let depotInFlight = 0
let maxDepotInFlight = 0
t.mock.method(console, 'info', (message) => logs.push(message))
t.mock.method(console, 'warn', (message) => logs.push(message))
t.mock.method(globalThis, 'fetch', async (url, options) => {
Expand All @@ -92,12 +94,18 @@ async function runDigest(t, { env = {}, depotUsage = DEPOT_USAGE, workflowHealth
return Response.json(OVERVIEW)
}
if (href.startsWith('https://api.depot.dev/')) {
const answer = depotUsage[JSON.parse(options.body).startAt]
const usage = Array.isArray(answer) ? answer.shift() : answer
if (usage instanceof Error) {
throw usage
maxDepotInFlight = Math.max(maxDepotInFlight, ++depotInFlight)
try {
await new Promise((resolve) => setImmediate(resolve))
const answer = depotUsage[JSON.parse(options.body).startAt] ?? {}
const usage = Array.isArray(answer) ? answer.shift() : answer
if (usage instanceof Error) {
throw usage
}
return usage instanceof Response ? usage : Response.json(usage)
} finally {
depotInFlight--
}
return usage instanceof Response ? usage : Response.json(usage)
}
assert.equal(href, 'https://slack.com/api/chat.postMessage')
blocks = JSON.parse(options.body).blocks
Expand All @@ -114,7 +122,7 @@ async function runDigest(t, { env = {}, depotUsage = DEPOT_USAGE, workflowHealth
t.mock.timers.tick(30_000)
}
await run
return { blocks, logs, requests }
return { blocks, logs, requests, maxDepotInFlight }
} finally {
for (const [key, value] of Object.entries(previousEnv)) {
if (value === undefined) {
Expand All @@ -139,7 +147,17 @@ describe('weekly engineering analytics digest', () => {
],
]) {
it(`reports Depot spend for complete UTC weeks and the contract${name}`, async (t) => {
const { blocks, requests } = await runDigest(t, override)
const { blocks, requests, maxDepotInFlight } = await runDigest(t, override)
assert.equal(maxDepotInFlight, 1)
const contractRanges = requests
.filter((request) => request.url.startsWith('https://api.depot.dev/'))
.map((request) => JSON.parse(request.body))
.slice(-10)
assert.deepEqual(
contractRanges.map((range) => range.startAt.slice(0, 10)),
Array.from({ length: 10 }, (_, i) => `2026-${String(i + 1).padStart(2, '0')}-01`)
)
assert.equal(contractRanges.at(-1).endAt, '2026-10-05T00:00:00.000Z')
const overviewUrl = new URL(requests.find((request) => request.url.includes('/repo_overview/')).url)
assert.equal(overviewUrl.searchParams.get('date_from'), WEEK)
assert.equal(overviewUrl.searchParams.get('date_to'), '2026-10-05T00:00:00.000Z')
Expand Down
Loading