Skip to content

Commit 7fb6023

Browse files
committed
Revert "fix: add 1-hour TTL cache for GitHub API requests to avoid rate limiting"
This reverts commit 92f1cca.
1 parent 133968d commit 7fb6023

File tree

2 files changed

+87
-98
lines changed

2 files changed

+87
-98
lines changed

packages/build-infra/lib/github-releases.mjs

Lines changed: 72 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
* Shared utilities for fetching GitHub releases.
33
*/
44

5-
import { createTtlCache } from '@socketsecurity/lib/cache-with-ttl'
65
import { safeMkdir } from '@socketsecurity/lib/fs'
76
import { httpDownload, httpRequest } from '@socketsecurity/lib/http-request'
87
import { getDefaultLogger } from '@socketsecurity/lib/logger'
@@ -13,13 +12,6 @@ const logger = getDefaultLogger()
1312
const OWNER = 'SocketDev'
1413
const REPO = 'socket-btm'
1514

16-
// Cache GitHub API responses for 1 hour to avoid rate limiting.
17-
const cache = createTtlCache({
18-
memoize: true,
19-
prefix: 'github-releases',
20-
ttl: 60 * 60 * 1000, // 1 hour.
21-
})
22-
2315
/**
2416
* Get GitHub authentication headers if token is available.
2517
*
@@ -46,56 +38,52 @@ function getAuthHeaders() {
4638
* @returns {Promise<string|null>} - Latest release tag or null if not found.
4739
*/
4840
export async function getLatestRelease(tool, { quiet = false } = {}) {
49-
const cacheKey = `latest-release:${tool}`
50-
51-
return await cache.getOrFetch(cacheKey, async () => {
52-
return await pRetry(
53-
async () => {
54-
const response = await httpRequest(
55-
`https://api.github.com/repos/${OWNER}/${REPO}/releases?per_page=100`,
56-
{
57-
headers: getAuthHeaders(),
58-
},
59-
)
60-
61-
if (!response.ok) {
62-
throw new Error(`Failed to fetch releases: ${response.status}`)
63-
}
41+
return await pRetry(
42+
async () => {
43+
const response = await httpRequest(
44+
`https://api.github.com/repos/${OWNER}/${REPO}/releases?per_page=100`,
45+
{
46+
headers: getAuthHeaders(),
47+
},
48+
)
6449

65-
const releases = JSON.parse(response.body)
50+
if (!response.ok) {
51+
throw new Error(`Failed to fetch releases: ${response.status}`)
52+
}
6653

67-
// Find the first release matching the tool prefix.
68-
for (const release of releases) {
69-
const { tag_name: tag } = release
70-
if (tag.startsWith(`${tool}-`)) {
71-
if (!quiet) {
72-
logger.info(` Found release: ${tag}`)
73-
}
74-
return tag
54+
const releases = JSON.parse(response.body)
55+
56+
// Find the first release matching the tool prefix.
57+
for (const release of releases) {
58+
const { tag_name: tag } = release
59+
if (tag.startsWith(`${tool}-`)) {
60+
if (!quiet) {
61+
logger.info(` Found release: ${tag}`)
7562
}
63+
return tag
7664
}
77-
78-
// No matching release found in the list.
65+
}
66+
67+
// No matching release found in the list.
68+
if (!quiet) {
69+
logger.info(` No ${tool} release found in latest 100 releases`)
70+
}
71+
return null
72+
},
73+
{
74+
backoffFactor: 1,
75+
baseDelayMs: 5000,
76+
onRetry: (attempt, error) => {
7977
if (!quiet) {
80-
logger.info(` No ${tool} release found in latest 100 releases`)
78+
logger.info(
79+
` Retry attempt ${attempt + 1}/3 for ${tool} release list...`,
80+
)
81+
logger.warn(` Attempt ${attempt + 1}/3 failed: ${error.message}`)
8182
}
82-
return null
8383
},
84-
{
85-
backoffFactor: 1,
86-
baseDelayMs: 5000,
87-
onRetry: (attempt, error) => {
88-
if (!quiet) {
89-
logger.info(
90-
` Retry attempt ${attempt + 1}/3 for ${tool} release list...`,
91-
)
92-
logger.warn(` Attempt ${attempt + 1}/3 failed: ${error.message}`)
93-
}
94-
},
95-
retries: 2,
96-
},
97-
)
98-
})
84+
retries: 2,
85+
},
86+
)
9987
}
10088

10189
/**
@@ -115,50 +103,46 @@ export async function getReleaseAssetUrl(
115103
assetName,
116104
{ quiet = false } = {},
117105
) {
118-
const cacheKey = `asset-url:${tag}:${assetName}`
119-
120-
return await cache.getOrFetch(cacheKey, async () => {
121-
return await pRetry(
122-
async () => {
123-
const response = await httpRequest(
124-
`https://api.github.com/repos/${OWNER}/${REPO}/releases/tags/${tag}`,
125-
{
126-
headers: getAuthHeaders(),
127-
},
128-
)
129-
130-
if (!response.ok) {
131-
throw new Error(`Failed to fetch release ${tag}: ${response.status}`)
132-
}
106+
return await pRetry(
107+
async () => {
108+
const response = await httpRequest(
109+
`https://api.github.com/repos/${OWNER}/${REPO}/releases/tags/${tag}`,
110+
{
111+
headers: getAuthHeaders(),
112+
},
113+
)
133114

134-
const release = JSON.parse(response.body)
115+
if (!response.ok) {
116+
throw new Error(`Failed to fetch release ${tag}: ${response.status}`)
117+
}
135118

136-
// Find the matching asset.
137-
const asset = release.assets.find(a => a.name === assetName)
119+
const release = JSON.parse(response.body)
138120

139-
if (!asset) {
140-
throw new Error(`Asset ${assetName} not found in release ${tag}`)
141-
}
121+
// Find the matching asset.
122+
const asset = release.assets.find(a => a.name === assetName)
142123

124+
if (!asset) {
125+
throw new Error(`Asset ${assetName} not found in release ${tag}`)
126+
}
127+
128+
if (!quiet) {
129+
logger.info(` Found asset: ${assetName}`)
130+
}
131+
132+
return asset.browser_download_url
133+
},
134+
{
135+
backoffFactor: 1,
136+
baseDelayMs: 5000,
137+
onRetry: (attempt, error) => {
143138
if (!quiet) {
144-
logger.info(` Found asset: ${assetName}`)
139+
logger.info(` Retry attempt ${attempt + 1}/3 for asset URL...`)
140+
logger.warn(` Attempt ${attempt + 1}/3 failed: ${error.message}`)
145141
}
146-
147-
return asset.browser_download_url
148142
},
149-
{
150-
backoffFactor: 1,
151-
baseDelayMs: 5000,
152-
onRetry: (attempt, error) => {
153-
if (!quiet) {
154-
logger.info(` Retry attempt ${attempt + 1}/3 for asset URL...`)
155-
logger.warn(` Attempt ${attempt + 1}/3 failed: ${error.message}`)
156-
}
157-
},
158-
retries: 2,
159-
},
160-
)
161-
})
143+
retries: 2,
144+
},
145+
)
162146
}
163147

164148
/**

packages/cli/src/commands/patch/cmd-patch.mts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,21 @@ async function run(
6262
process.exitCode = 1
6363

6464
// Forward all arguments to socket-patch via DLX.
65-
const { spawnPromise } = await spawnSocketPatchDlx([...argv], {
66-
stdio: 'inherit',
67-
})
65+
const { spawnPromise } = await spawnSocketPatchDlx([...argv])
6866

69-
// Wait for the spawn to complete and set exit code.
70-
const result = await spawnPromise
67+
// Handle exit codes and signals using event-based pattern.
68+
// See https://nodejs.org/api/child_process.html#event-exit.
69+
spawnPromise.process.on(
70+
'exit',
71+
(code: number | null, signalName: NodeJS.Signals | null) => {
72+
if (signalName) {
73+
process.kill(process.pid, signalName)
74+
} else if (typeof code === 'number') {
75+
// eslint-disable-next-line n/no-process-exit
76+
process.exit(code)
77+
}
78+
},
79+
)
7180

72-
if (result.code !== null && result.code !== 0) {
73-
process.exitCode = result.code
74-
} else if (result.code === 0) {
75-
process.exitCode = 0
76-
}
81+
await spawnPromise
7782
}

0 commit comments

Comments
 (0)