Skip to content

Commit c655793

Browse files
committed
Merge remote-tracking branch 'origin/jdalton/enable-curly-rule' into chore/sync-template
2 parents 5ce65f4 + 236273c commit c655793

File tree

8 files changed

+78
-34
lines changed

8 files changed

+78
-34
lines changed

.git-hooks/pre-push

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,10 +168,10 @@ while read local_ref local_sha remote_ref remote_sha; do
168168
ERRORS=$((ERRORS + 1))
169169
fi
170170

171-
# AWS keys.
172-
if echo "$file_text" | grep -iqE '(aws_access_key|aws_secret|AKIA[0-9A-Z]{16})'; then
171+
# AWS keys (word-boundary match to avoid false positives in base64 data).
172+
if echo "$file_text" | grep -iqE '(aws_access_key|aws_secret|\bAKIA[0-9A-Z]{16}\b)'; then
173173
printf "${RED}✗ BLOCKED: Potential AWS credentials found in: %s${NC}\n" "$file"
174-
echo "$file_text" | grep -niE '(aws_access_key|aws_secret|AKIA[0-9A-Z]{16})' | head -3
174+
echo "$file_text" | grep -niE '(aws_access_key|aws_secret|\bAKIA[0-9A-Z]{16}\b)' | head -3
175175
ERRORS=$((ERRORS + 1))
176176
fi
177177

.oxlintrc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"suspicious": "error"
77
},
88
"rules": {
9-
"eslint/curly": "off",
9+
"eslint/curly": ["error", "all"],
1010
"eslint/no-await-in-loop": "off",
1111
"eslint/no-console": "off",
1212
"eslint/no-control-regex": "off",

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
"pretest": "pnpm run build:cli"
5353
},
5454
"devDependencies": {
55+
"@typescript/native-preview": "7.0.0-dev.20260415.1",
5556
"@anthropic-ai/claude-code": "catalog:",
5657
"@babel/core": "catalog:",
5758
"@babel/parser": "catalog:",

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ import { pRetry } from '@socketsecurity/lib/promises'
1212

1313
const logger = getDefaultLogger()
1414

15-
// Cache GitHub API responses for 1 hour to avoid rate limiting.
15+
// Cache GitHub API responses for 4 hours to reduce API calls and avoid rate limiting.
1616
const cache = createTtlCache({
1717
memoize: true,
1818
prefix: 'github-releases',
19-
ttl: 60 * 60 * 1000, // 1 hour.
19+
ttl: 4 * 60 * 60 * 1000, // 4 hours.
2020
})
2121

2222
/**
@@ -155,8 +155,8 @@ export async function getLatestRelease(
155155
return null
156156
},
157157
{
158-
backoffFactor: 1,
159-
baseDelayMs: 5_000,
158+
backoffFactor: 2,
159+
baseDelayMs: 3_000,
160160
onRetry: (attempt, error) => {
161161
if (!quiet) {
162162
logger.info(
@@ -231,8 +231,8 @@ export async function getReleaseAssetUrl(
231231
return asset.browser_download_url
232232
},
233233
{
234-
backoffFactor: 1,
235-
baseDelayMs: 5_000,
234+
backoffFactor: 2,
235+
baseDelayMs: 3_000,
236236
onRetry: (attempt, error) => {
237237
if (!quiet) {
238238
logger.info(` Retry attempt ${attempt + 1}/3 for asset URL...`)

packages/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@socketsecurity/cli",
3-
"version": "0.0.0-copied-from-packages-socket",
3+
"version": "0.0.0",
44
"description": "CLI for Socket.dev",
55
"private": true,
66
"license": "MIT",

packages/cli/scripts/download-assets.mjs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,14 @@ async function downloadAssets(assetNames, parallel = true) {
231231
* Main entry point.
232232
*/
233233
async function main() {
234+
// Skip downloads entirely when SKIP_ASSET_DOWNLOAD is set.
235+
// Useful for repeated local builds where assets are already cached,
236+
// or when GitHub API rate limits are exhausted.
237+
if (process.env.SKIP_ASSET_DOWNLOAD) {
238+
logger.info('Skipping asset downloads (SKIP_ASSET_DOWNLOAD is set)')
239+
return
240+
}
241+
234242
const args = process.argv.slice(2)
235243
const parallel = !args.includes('--no-parallel')
236244
const assetArgs = args.filter(arg => !arg.startsWith('--'))

packages/cli/scripts/sync-checksums.mjs

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@
1717
*/
1818

1919
import { createHash } from 'node:crypto'
20-
import { createReadStream, existsSync, readFileSync, promises as fs } from 'node:fs'
20+
import {
21+
createReadStream,
22+
existsSync,
23+
readFileSync,
24+
promises as fs,
25+
} from 'node:fs'
2126
import os from 'node:os'
2227
import path from 'node:path'
2328
import { fileURLToPath } from 'node:url'
@@ -48,7 +53,9 @@ function parseChecksums(content) {
4853
const checksums = {}
4954
for (const line of content.split('\n')) {
5055
const trimmed = line.trim()
51-
if (!trimmed) continue
56+
if (!trimmed) {
57+
continue
58+
}
5259
// Format: hash filename (two spaces or whitespace between)
5360
const match = trimmed.match(/^([a-f0-9]{64})\s+(.+)$/)
5461
if (match) {
@@ -64,7 +71,7 @@ function parseChecksums(content) {
6471
async function downloadFile(url, destPath) {
6572
const response = await fetch(url, {
6673
headers: {
67-
'Accept': 'application/octet-stream',
74+
Accept: 'application/octet-stream',
6875
'User-Agent': 'socket-cli-sync-checksums',
6976
},
7077
redirect: 'follow',
@@ -87,21 +94,27 @@ async function downloadFile(url, destPath) {
8794
* Fetch checksums for a GitHub release.
8895
* First tries checksums.txt, then falls back to downloading assets.
8996
*/
90-
async function fetchGitHubReleaseChecksums(repo, releaseTag, existingChecksums = {}) {
97+
async function fetchGitHubReleaseChecksums(
98+
repo,
99+
releaseTag,
100+
existingChecksums = {},
101+
) {
91102
const [owner, repoName] = repo.split('/')
92103
const apiUrl = `https://api.github.com/repos/${owner}/${repoName}/releases/tags/${releaseTag}`
93104

94105
console.log(` Fetching release info from ${apiUrl}...`)
95106

96107
const response = await fetch(apiUrl, {
97108
headers: {
98-
'Accept': 'application/vnd.github.v3+json',
109+
Accept: 'application/vnd.github.v3+json',
99110
'User-Agent': 'socket-cli-sync-checksums',
100111
},
101112
})
102113

103114
if (!response.ok) {
104-
throw new Error(`GitHub API error: ${response.status} ${response.statusText}`)
115+
throw new Error(
116+
`GitHub API error: ${response.status} ${response.statusText}`,
117+
)
105118
}
106119

107120
const release = await response.json()
@@ -111,7 +124,9 @@ async function fetchGitHubReleaseChecksums(repo, releaseTag, existingChecksums =
111124
const checksumsAsset = assets.find(a => a.name === 'checksums.txt')
112125
if (checksumsAsset) {
113126
console.log(` Found checksums.txt, downloading...`)
114-
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'socket-checksums-'))
127+
const tempDir = await fs.mkdtemp(
128+
path.join(os.tmpdir(), 'socket-checksums-'),
129+
)
115130
const checksumPath = path.join(tempDir, 'checksums.txt')
116131

117132
try {
@@ -122,7 +137,9 @@ async function fetchGitHubReleaseChecksums(repo, releaseTag, existingChecksums =
122137
// Clean up.
123138
await fs.rm(tempDir, { recursive: true })
124139

125-
console.log(` Parsed ${Object.keys(checksums).length} checksums from checksums.txt`)
140+
console.log(
141+
` Parsed ${Object.keys(checksums).length} checksums from checksums.txt`,
142+
)
126143
return checksums
127144
} catch (error) {
128145
console.log(` Failed to download checksums.txt: ${error.message}`)
@@ -139,7 +156,9 @@ async function fetchGitHubReleaseChecksums(repo, releaseTag, existingChecksums =
139156
return {}
140157
}
141158

142-
console.log(` No checksums.txt found, downloading ${assetNames.length} assets to compute checksums...`)
159+
console.log(
160+
` No checksums.txt found, downloading ${assetNames.length} assets to compute checksums...`,
161+
)
143162

144163
const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'socket-checksums-'))
145164
const checksums = {}
@@ -192,24 +211,32 @@ async function main() {
192211
// Find all GitHub-released tools.
193212
const githubTools = Object.entries(externalTools)
194213
.filter(([key, value]) => {
195-
if (key.startsWith('$')) return false // Skip schema keys
214+
if (key.startsWith('$')) {
215+
return false
216+
} // Skip schema keys
196217
return value.release === 'asset'
197218
})
198219
.map(([key, value]) => ({ key, ...value }))
199220

200221
if (toolFilter) {
201222
const filtered = githubTools.filter(t => t.key === toolFilter)
202223
if (filtered.length === 0) {
203-
console.error(`Error: Tool '${toolFilter}' not found or is not a GitHub release tool`)
204-
console.log(`Available GitHub release tools: ${githubTools.map(t => t.key).join(', ')}`)
224+
console.error(
225+
`Error: Tool '${toolFilter}' not found or is not a GitHub release tool`,
226+
)
227+
console.log(
228+
`Available GitHub release tools: ${githubTools.map(t => t.key).join(', ')}`,
229+
)
205230
process.exitCode = 1
206231
return
207232
}
208233
githubTools.length = 0
209234
githubTools.push(...filtered)
210235
}
211236

212-
console.log(`Syncing checksums for ${githubTools.length} GitHub release tool(s)...\n`)
237+
console.log(
238+
`Syncing checksums for ${githubTools.length} GitHub release tool(s)...\n`,
239+
)
213240

214241
let updated = 0
215242
let unchanged = 0
@@ -235,10 +262,13 @@ async function main() {
235262

236263
// Check if update is needed.
237264
const oldChecksums = tool.checksums || {}
238-
const checksumChanged = JSON.stringify(newChecksums) !== JSON.stringify(oldChecksums)
265+
const checksumChanged =
266+
JSON.stringify(newChecksums) !== JSON.stringify(oldChecksums)
239267

240268
if (!force && !checksumChanged) {
241-
console.log(` Unchanged: ${Object.keys(newChecksums).length} checksums\n`)
269+
console.log(
270+
` Unchanged: ${Object.keys(newChecksums).length} checksums\n`,
271+
)
242272
unchanged++
243273
continue
244274
}
@@ -269,7 +299,9 @@ async function main() {
269299
}
270300

271301
// Summary.
272-
console.log(`\nSummary: ${updated} updated, ${unchanged} unchanged, ${failed} failed`)
302+
console.log(
303+
`\nSummary: ${updated} updated, ${unchanged} unchanged, ${failed} failed`,
304+
)
273305

274306
if (failed > 0) {
275307
process.exitCode = 1

scripts/validate-checksums.mjs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url))
2626
const rootPath = path.join(__dirname, '..')
2727

2828
// Load external tools configuration.
29-
const externalToolsPath = path.join(
30-
rootPath,
31-
'packages/cli/bundle-tools.json',
32-
)
29+
const externalToolsPath = path.join(rootPath, 'packages/cli/bundle-tools.json')
3330
const externalTools = JSON.parse(readFileSync(externalToolsPath, 'utf8'))
3431

3532
/**
@@ -47,10 +44,14 @@ function validateChecksums() {
4744

4845
// Collect all assets needed across all platforms.
4946
for (const [platform, tools] of Object.entries(PLATFORM_MAP_TOOLS)) {
50-
if (!tools) continue
47+
if (!tools) {
48+
continue
49+
}
5150

5251
for (const [toolName, assetName] of Object.entries(tools)) {
53-
if (!assetName) continue
52+
if (!assetName) {
53+
continue
54+
}
5455

5556
if (!requiredAssets.has(toolName)) {
5657
requiredAssets.set(toolName, new Set())
@@ -130,7 +131,9 @@ function validateChecksums() {
130131
logger.error(
131132
'All external tool assets MUST have SHA-256 checksums defined in bundle-tools.json.',
132133
)
133-
logger.error('This is a security requirement to prevent supply chain attacks.')
134+
logger.error(
135+
'This is a security requirement to prevent supply chain attacks.',
136+
)
134137
return false
135138
}
136139

0 commit comments

Comments
 (0)