Skip to content

Commit 139a778

Browse files
committed
chore(wheelhouse): cascade template@7067995498
Auto-applied by socket-wheelhouse commit-cascade into sdk-415-release-rKpmnZ. 42 file(s) touched: - .config/fleet/oxlintrc.json - .git-hooks/_shared/canonical/source.mts - .git-hooks/_shared/run-step.sh - .git-hooks/_shared/scan-core.mts - .github/actions/fleet/_shared/codeql-languages.d.mts - .github/actions/fleet/_shared/codeql-languages.mjs - .github/actions/fleet/_shared/install-tool.mjs - .github/actions/fleet/_shared/platform-key.mjs - .github/actions/fleet/_shared/platform.mjs - .github/actions/fleet/_shared/resolve-external-tool-asset.d.mts - .github/actions/fleet/_shared/resolve-external-tool-asset.mjs - .github/actions/fleet/checkout/action.yml - .github/actions/fleet/github-ci-fix-app-token/mint-app-installation-token.mjs - .github/actions/fleet/github-payload-app-token/mint-app-installation-token.mjs - .github/actions/fleet/github-pr-branch-app-token/mint-app-installation-token.mjs - .github/actions/fleet/setup-and-install/action.yml - .github/actions/fleet/setup/action.yml - .github/actions/fleet/setup/fleet-env.json - .github/workflows/ci-fix.yml - .github/workflows/cron-weekly-fuzz.yml ... and 22 more
1 parent 2a9d8c4 commit 139a778

44 files changed

Lines changed: 32771 additions & 4492 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.config/fleet/oxlintrc.json‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.git-hooks/_shared/canonical/source.mts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
} from './git.mts'
1515
import type { CanonicalGitRead } from './git.mts'
1616

17-
function canonicalMemberSlug(root: string): string | undefined {
17+
export function canonicalMemberSlug(root: string): string | undefined {
1818
const remote = canonicalGitText(root, ['remote', 'get-url', 'origin'])?.trim()
1919
// Accept the three GitHub transports, retaining the organization segment.
2020
const match =

‎.git-hooks/_shared/run-step.sh‎

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ run_pkg_step_bounded() {
132132
# seconds, and the budget is the hang ceiling that keeps a deadlock (e.g. the
133133
# Socket Firewall sfw proxy + a worker blocking on each other) from ever hanging
134134
# the commit past PRECOMMIT_STEP_BUDGET_S. A real lint/test FAILURE (clean
135-
# non-zero before the budget) still BLOCKS the commit — only a budget-exceeding
136-
# HANG is skipped, and the pre-push `--all` gate + CI run the full suite. The
135+
# non-zero, including during timeout cleanup) still BLOCKS the commit — only a
136+
# budget-exceeding HANG is skipped. The pre-push `--all` gate + CI run the full suite. The
137137
# ceiling is enforced by scripts/fleet/check/precommit-steps-are-bounded.mts,
138138
# which fails if a heavy step is invoked un-bounded or the budget drifts above
139139
# its cap.
@@ -156,7 +156,7 @@ run_step_bounded() {
156156
return 1
157157
fi
158158
set -m
159-
{ "$@" >"$step_log" 2>&1; } &
159+
{ exec "$@" >"$step_log" 2>&1; } &
160160
job=$!
161161
set +m
162162
fi
@@ -168,11 +168,29 @@ run_step_bounded() {
168168
while kill -0 "$job" 2>/dev/null; do
169169
if [ "$elapsed" -ge "$PRECOMMIT_STEP_BUDGET_S" ]; then
170170
# Budget blown — a deadlock or an over-broad related-set. Take out the
171-
# whole group (sfw wrapper + workers), TERM then KILL, and fail open.
171+
# whole group (sfw wrapper + workers), TERM then KILL.
172172
# The kills run in an stderr-discarded subshell so the shell's
173173
# "Terminated" job-control notice doesn't leak into the commit output.
174-
{ kill -- -"$job"; sleep 1; kill -9 -- -"$job"; } 2>/dev/null
175-
wait "$job" 2>/dev/null
174+
timeout_signalled=false
175+
{
176+
if kill -- -"$job"; then timeout_signalled=true; fi
177+
sleep 1
178+
kill -9 -- -"$job"
179+
} 2>/dev/null
180+
if wait "$job" 2>/dev/null; then
181+
status=0
182+
else
183+
status=$?
184+
fi
185+
case "$status:$timeout_signalled" in
186+
0:*|137:true|143:true) ;;
187+
*)
188+
show_step_output
189+
printf '\n========== pre-commit: %s FAILED (exit %s) ==========\n' "$step_name" "$status"
190+
printf '\n========== full log: %s ==========\n' "$step_log"
191+
return "$status"
192+
;;
193+
esac
176194
cat "$step_log" 2>/dev/null
177195
rm -f "$step_log"
178196
printf '\n========== pre-commit: %s SKIPPED (budget %ss exceeded) ==========\n' \

‎.git-hooks/_shared/scan-core.mts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020

2121
export const stripTemplateLayer = (p: string): string =>
2222
p
23+
.replace(/^template\/base\/(?:conditional|universal)\//, 'template/')
2324
.replace(/^template\/(?:base|mono|solo)\//, 'template/')
2425
.replace(/^template\/overrides\/[^/]+\//, 'template/')
2526

‎.github/actions/fleet/_shared/codeql-languages.d.mts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export declare const CODEQL_LANGUAGE_GLOBS: Readonly<Record<string, readonly str
66
export interface CodeqlMatrixEntry {
77
language: string
88
'build-mode': 'autobuild' | 'none'
9-
runner: 'macos-latest' | 'ubuntu-latest'
9+
runner: string
1010
}
1111

1212
export declare function presentCodeqlLanguages(gitPaths: readonly string[]): string[]

‎.github/actions/fleet/_shared/codeql-languages.mjs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import path from 'node:path'
2+
import runnerImages from './runner-images.json' with { type: 'json' }
23

34
export const CANONICAL_JS_IDENTIFIER = 'javascript-typescript'
45
export const ALWAYS_EXPECTED_LANGUAGES = Object.freeze(['actions'])
@@ -95,7 +96,9 @@ export function planCodeqlMatrix(gitPaths) {
9596
(language === 'java-kotlin' && kotlin)
9697
? 'autobuild'
9798
: 'none',
98-
runner: language === 'swift' ? 'macos-latest' : 'ubuntu-latest',
99+
runner:
100+
runnerImages.roles[language === 'swift' ? 'macos-arm64' : 'linux-x64']
101+
.label,
99102
})),
100103
}
101104
}

‎.github/actions/fleet/_shared/install-tool.mjs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ async function run() {
236236
}
237237
// Positionals: <url> <integrity> <dest-dir> [<bin-name>]. Optional flags
238238
// --src <url> and --date <iso> carry the object-form integrity provenance
239-
// (forwarded by the composite actions from resolve-external-tool-asset.mjs's
239+
// (forwarded by the composite actions from resolve-external-tool-asset.generated.mjs's
240240
// JSON output) so the live src / staleness checks run after the SRI check.
241241
const flags = { src: '', date: '', cache: false }
242242
const positionals = []

‎.github/actions/fleet/_shared/platform-key.mjs‎

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
11
/**
22
* @file Prints the external-tools.json `platforms` KEY for this runner:
33
* linux-x64, linux-arm64, linux-x64-musl, linux-arm64-musl, darwin-x64,
4-
* darwin-arm64, win32-x64, win32-arm64.
5-
* This is the companion to platform.mjs, which prints the legacy shell-side
6-
* shape (`win-x64`, `win-arm64`) for human-facing messages. The two agree
7-
* everywhere except Windows, and that one difference silently broke every
8-
* real Windows runner: a lookup keyed `win-x64` misses the schema's
9-
* `win32-x64` entry, jq.mjs exits non-zero printing NOTHING, and `set -e`
10-
* kills the step with an empty log. It read as "pnpm has no Windows build"
11-
* when the entry was there all along, and it false-negatived the zizmor
12-
* audit into a permanent skip.
13-
* So: use THIS for any `platforms <key>` lookup, and platform.mjs only for
14-
* prose. The mapping itself is not duplicated here — it is
15-
* `canonicalPlatformKey` from resolve-external-tool-asset.mjs, which already
16-
* owned it for the Go/Rust/odai resolvers.
17-
* Usage: node .github/actions/fleet/_shared/platform-key.mjs
18-
* Exits non-zero on an unsupported platform/arch.
4+
* darwin-arm64, win32-x64, win32-arm64. This is the companion to
5+
* platform.mjs, which prints the legacy shell-side shape (`win-x64`,
6+
* `win-arm64`) for human-facing messages. The two agree everywhere except
7+
* Windows, and that one difference silently broke every real Windows runner:
8+
* a lookup keyed `win-x64` misses the schema's `win32-x64` entry, jq.mjs
9+
* exits non-zero printing NOTHING, and `set -e` kills the step with an empty
10+
* log. It read as "pnpm has no Windows build" when the entry was there all
11+
* along, and it false-negatived the zizmor audit into a permanent skip. So:
12+
* use THIS for any `platforms <key>` lookup, and platform.mjs only for prose.
13+
* The mapping itself is not duplicated here — it is `canonicalPlatformKey`
14+
* from resolve-external-tool-asset.generated.mjs, which already owned it for
15+
* the Go/Rust/odai resolvers. Usage: node
16+
* .github/actions/fleet/_shared/platform-key.mjs Exits non-zero on an
17+
* unsupported platform/arch.
1918
*/
2019

2120
import process from 'node:process'
2221
import { realpathSync } from 'node:fs'
2322
import { pathToFileURL } from 'node:url'
2423

25-
import { canonicalPlatformKey } from './resolve-external-tool-asset.mjs'
24+
import { canonicalPlatformKey } from './resolve-external-tool-asset.generated.mjs'
2625

2726
// Re-exported so a caller can reach the key function from the module whose name
2827
// says "key", and so this file satisfies the exported-helper contract that

‎.github/actions/fleet/_shared/platform.mjs‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66
* `process.report` exposes libc (glibcVersionRuntime is the string "musl" on
77
* musl Node, otherwise a glibc version number). No shelling out. Usage: node
88
* .github/actions/fleet/_shared/platform.mjs Exits non-zero on unsupported
9-
* platform/arch.
10-
* NOTE: this script outputs `win-x64` / `win-arm64` (the legacy fleet
11-
* shell-side shape), NOT `win32-x64` (the external-tools.json `platforms`
12-
* keys). The resolver helper (resolve-external-tool-asset.mjs) computes its
13-
* own `win32-*` key for schema lookup; do NOT consume this script's output as
14-
* a platforms-map key.
15-
* Testability: the pure `canonicalPlatform` helper is EXPORTED and the
9+
* platform/arch. NOTE: this script outputs `win-x64` / `win-arm64` (the
10+
* legacy fleet shell-side shape), NOT `win32-x64` (the external-tools.json
11+
* `platforms` keys). The resolver helper
12+
* (resolve-external-tool-asset.generated.mjs) computes its own `win32-*` key
13+
* for schema lookup; do NOT consume this script's output as a platforms-map
14+
* key. Testability: the pure `canonicalPlatform` helper is EXPORTED and the
1615
* side-effectful stdout print is guarded by isMainModule(), so unit tests can
1716
* import it without triggering a process.exit. Every composite-action _shared
1817
* helper follows this pattern (see check-fleet-shared-scripts-are-testable).
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
const GITHUB_ORIGIN = 'https://github.com'
2+
3+
export function integrityValue(integrity: unknown): string {
4+
if (typeof integrity === 'object' && integrity !== null) {
5+
const value = (integrity as { readonly value?: unknown | undefined }).value
6+
return typeof value === 'string' ? value : ''
7+
}
8+
return typeof integrity === 'string' ? integrity : ''
9+
}
10+
11+
export function integrityProvenance(integrity: unknown): {
12+
readonly src: string
13+
readonly date: string
14+
} {
15+
if (typeof integrity === 'object' && integrity !== null) {
16+
const record = integrity as {
17+
readonly src?: unknown | undefined
18+
readonly date?: unknown | undefined
19+
}
20+
return {
21+
__proto__: null,
22+
src: typeof record.src === 'string' ? record.src : '',
23+
date: typeof record.date === 'string' ? record.date : '',
24+
} as { readonly src: string; readonly date: string }
25+
}
26+
return { __proto__: null, src: '', date: '' } as {
27+
readonly src: string
28+
readonly date: string
29+
}
30+
}
31+
32+
function safeReleaseSegment(value: unknown, label: string): string {
33+
if (
34+
typeof value !== 'string' ||
35+
value.length === 0 ||
36+
value === '.' ||
37+
value === '..' ||
38+
/[/\\?#\u0000-\u0020]/u.test(value)
39+
) {
40+
throw new Error(
41+
`external-tools.json ${label} is not a safe GitHub release path segment`,
42+
)
43+
}
44+
return value
45+
}
46+
47+
function githubRepositorySlug(repository: unknown): string {
48+
if (typeof repository !== 'string' || !repository.startsWith('github:')) {
49+
throw new Error(
50+
'external-tools.json repository is not a github:owner/repo reference',
51+
)
52+
}
53+
const slug = repository.slice('github:'.length)
54+
const parts = slug.split('/')
55+
if (
56+
parts.length !== 2 ||
57+
!parts[0] ||
58+
!parts[1] ||
59+
parts.some(part => !/^[A-Za-z0-9_.-]+$/u.test(part))
60+
) {
61+
throw new Error(
62+
'external-tools.json repository is not a github:owner/repo reference',
63+
)
64+
}
65+
return slug
66+
}
67+
68+
export interface ReleaseAssetTool {
69+
readonly origin?: unknown | undefined
70+
readonly repository?: unknown | undefined
71+
readonly tag?: unknown | undefined
72+
readonly version?: unknown | undefined
73+
}
74+
75+
export interface ReleaseAssetEntry {
76+
readonly asset?: unknown | undefined
77+
readonly integrity?: unknown | undefined
78+
}
79+
80+
export interface ResolvedCatalogAsset {
81+
readonly asset: string
82+
readonly assetName?: string | undefined
83+
readonly integrity: string
84+
readonly repository?: string | undefined
85+
readonly src: string
86+
readonly date: string
87+
readonly tag?: string | undefined
88+
readonly version: string
89+
}
90+
91+
/**
92+
* Resolve a pinned GitHub release asset and verify its URL binding.
93+
*/
94+
export function resolveGithubReleaseAsset(
95+
tool: ReleaseAssetTool,
96+
entry: ReleaseAssetEntry,
97+
canonicalKey: string,
98+
): ResolvedCatalogAsset {
99+
const slug = githubRepositorySlug(tool.repository)
100+
const tag = safeReleaseSegment(tool.tag, 'tag')
101+
const assetName = safeReleaseSegment(entry.asset, 'platform asset')
102+
const pathname = `/${slug}/releases/download/${encodeURIComponent(tag)}/${encodeURIComponent(assetName)}`
103+
const asset = new URL(pathname, GITHUB_ORIGIN)
104+
if (
105+
asset.origin !== GITHUB_ORIGIN ||
106+
asset.pathname !== pathname ||
107+
asset.username ||
108+
asset.password ||
109+
asset.search ||
110+
asset.hash
111+
) {
112+
throw new Error(
113+
`external-tools.json ${canonicalKey} release asset URL failed GitHub binding validation`,
114+
)
115+
}
116+
const integrity = integrityValue(entry.integrity)
117+
if (!integrity) {
118+
throw new Error(
119+
`external-tools.json ${canonicalKey} entry is missing integrity`,
120+
)
121+
}
122+
const { src, date } = integrityProvenance(entry.integrity)
123+
return {
124+
__proto__: null,
125+
asset: asset.href,
126+
assetName,
127+
integrity,
128+
repository: slug,
129+
src,
130+
date,
131+
tag,
132+
version: String(tool.version ?? ''),
133+
} as ResolvedCatalogAsset
134+
}
135+
136+
/**
137+
* Resolve a catalog asset while preserving its exact integrity metadata.
138+
*/
139+
export function resolveCatalogAsset(
140+
tool: ReleaseAssetTool,
141+
entry: ReleaseAssetEntry,
142+
canonicalKey: string,
143+
): ResolvedCatalogAsset {
144+
const isGithub =
145+
tool.origin === 'gh-asset' ||
146+
(typeof tool.repository === 'string' &&
147+
tool.repository.startsWith('github:'))
148+
if (isGithub) {
149+
return resolveGithubReleaseAsset(tool, entry, canonicalKey)
150+
}
151+
const asset = entry.asset
152+
const integrity = integrityValue(entry.integrity)
153+
if (typeof asset !== 'string' || !asset.startsWith('https://')) {
154+
throw new Error(
155+
`external-tools.json ${canonicalKey} entry is missing an HTTPS asset URL`,
156+
)
157+
}
158+
if (!integrity) {
159+
throw new Error(
160+
`external-tools.json ${canonicalKey} entry is missing integrity`,
161+
)
162+
}
163+
const { src, date } = integrityProvenance(entry.integrity)
164+
return {
165+
__proto__: null,
166+
asset,
167+
integrity,
168+
src,
169+
date,
170+
version: String(tool.version ?? ''),
171+
} as ResolvedCatalogAsset
172+
}

0 commit comments

Comments
 (0)