@@ -262,6 +262,66 @@ async function main(): Promise<void> {
262262 }
263263 }
264264
265+ // CI gate: `<binary> --smoke-login-primitives` checks the local pieces that
266+ // must work before browser OAuth can complete. This is intentionally not a
267+ // full OAuth flow: CI should not depend on a real GitHub account/browser
268+ // round trip just to validate the compiled Windows executable.
269+ if ( process . argv . includes ( '--smoke-login-primitives' ) ) {
270+ try {
271+ const [ { withTimeout } , fingerprint , { getWindowsOpenUrlCommand } ] =
272+ await Promise . all ( [
273+ import ( '@codebuff/common/util/promise' ) ,
274+ import ( './utils/fingerprint' ) ,
275+ import ( './utils/open-url' ) ,
276+ ] )
277+
278+ let timeoutRejected = false
279+ try {
280+ await withTimeout (
281+ new Promise < never > ( ( ) => { } ) ,
282+ 50 ,
283+ 'login smoke expected timeout' ,
284+ )
285+ } catch ( err ) {
286+ timeoutRejected =
287+ err instanceof Error &&
288+ err . message . includes ( 'login smoke expected timeout' )
289+ }
290+ if ( ! timeoutRejected ) {
291+ throw new Error ( 'withTimeout did not reject a hanging promise' )
292+ }
293+
294+ const fingerprintId = await withTimeout (
295+ fingerprint . calculateFingerprint ( ) ,
296+ 5_000 ,
297+ 'calculateFingerprint exceeded login smoke timeout' ,
298+ )
299+ const fingerprintType = fingerprint . getFingerprintType ( fingerprintId )
300+ if ( fingerprintType === 'unknown' ) {
301+ throw new Error ( `Unexpected fingerprint type for ${ fingerprintId } ` )
302+ }
303+
304+ if ( process . platform === 'win32' ) {
305+ const opener = getWindowsOpenUrlCommand ( 'https://example.com' )
306+ if (
307+ opener . command !== 'rundll32.exe' ||
308+ opener . args [ 0 ] !== 'url.dll,FileProtocolHandler' ||
309+ opener . args [ 1 ] !== 'https://example.com'
310+ ) {
311+ throw new Error (
312+ `Unexpected Windows URL opener: ${ opener . command } ${ opener . args . join ( ' ' ) } ` ,
313+ )
314+ }
315+ }
316+
317+ console . log ( `login primitives smoke ok (${ fingerprintType } )` )
318+ process . exit ( 0 )
319+ } catch ( err ) {
320+ console . error ( 'login primitives smoke FAIL:' , err )
321+ process . exit ( 1 )
322+ }
323+ }
324+
265325 // Run OSC theme detection BEFORE anything else.
266326 // This MUST happen before OpenTUI starts because OSC responses come through stdin,
267327 // and OpenTUI also listens to stdin. Running detection here ensures stdin is clean.
0 commit comments