styleproof 4.4.19 → 4.4.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/map-store.js +42 -22
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,14 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [4.4.20] - 2026-07-14
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **Map-store network operations can no longer wedge CI indefinitely.** Remote
|
|
15
|
+
lookup, clone, and push commands now have a bounded timeout, and a stalled
|
|
16
|
+
isolated push falls through to the authenticated consumer checkout path.
|
|
17
|
+
|
|
10
18
|
## [4.4.19] - 2026-07-14
|
|
11
19
|
|
|
12
20
|
### Fixed
|
package/dist/map-store.js
CHANGED
|
@@ -52,6 +52,33 @@ function gitProcessEnvironment() {
|
|
|
52
52
|
function runGit(cwd, args, maxBuffer = 1 << 28) {
|
|
53
53
|
return spawnSync('git', args, { cwd, encoding: 'utf8', maxBuffer, env: gitProcessEnvironment() });
|
|
54
54
|
}
|
|
55
|
+
const DEFAULT_MAP_STORE_GIT_TIMEOUT_MILLISECONDS = 30_000;
|
|
56
|
+
function mapStoreGitTimeoutMilliseconds() {
|
|
57
|
+
const configuredTimeout = Number(process.env.STYLEPROOF_MAP_STORE_GIT_TIMEOUT_MS);
|
|
58
|
+
return Number.isFinite(configuredTimeout) && configuredTimeout > 0
|
|
59
|
+
? Math.floor(configuredTimeout)
|
|
60
|
+
: DEFAULT_MAP_STORE_GIT_TIMEOUT_MILLISECONDS;
|
|
61
|
+
}
|
|
62
|
+
function runMapStoreNetworkGit(cwd, args, maxBuffer = 1 << 20) {
|
|
63
|
+
return spawnSync('git', args, {
|
|
64
|
+
cwd,
|
|
65
|
+
encoding: 'utf8',
|
|
66
|
+
maxBuffer,
|
|
67
|
+
timeout: mapStoreGitTimeoutMilliseconds(),
|
|
68
|
+
env: {
|
|
69
|
+
...gitProcessEnvironment(),
|
|
70
|
+
GIT_TERMINAL_PROMPT: '0',
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function gitFailureMessage(result, fallback) {
|
|
75
|
+
const standardError = typeof result.stderr === 'string' ? result.stderr.trim() : '';
|
|
76
|
+
if (standardError)
|
|
77
|
+
return standardError;
|
|
78
|
+
if (result.error)
|
|
79
|
+
return result.error.message;
|
|
80
|
+
return fallback;
|
|
81
|
+
}
|
|
55
82
|
const WORKFLOW_TOKEN_CREDENTIAL_HELPER = '!f() { if [ "$1" = get ]; then printf \'%s\\n\' username=x-access-token "password=$STYLEPROOF_MAP_STORE_TOKEN"; fi; }; f';
|
|
56
83
|
export function workflowTokenCredentialArguments() {
|
|
57
84
|
return ['-c', 'credential.helper=', '-c', `credential.helper=${WORKFLOW_TOKEN_CREDENTIAL_HELPER}`];
|
|
@@ -459,19 +486,20 @@ function checkoutMapStore(cwd, remote, branch, sparseSegment) {
|
|
|
459
486
|
const httpExtraHeaders = effectiveGitHttpExtraHeaders(cwd);
|
|
460
487
|
const authenticationArguments = httpExtraHeaders.flatMap(({ key, value }) => ['-c', `${key}=${value}`]);
|
|
461
488
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'styleproof-map-store-'));
|
|
462
|
-
const
|
|
489
|
+
const branchLookup = runMapStoreNetworkGit(cwd, ['ls-remote', '--exit-code', '--heads', remote, branch], 1 << 20);
|
|
490
|
+
if (branchLookup.status !== 0 && branchLookup.status !== 2) {
|
|
491
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
492
|
+
throw new MapStoreError(gitFailureMessage(branchLookup, 'could not query map store branch'));
|
|
493
|
+
}
|
|
494
|
+
const branchExists = branchLookup.status === 0;
|
|
463
495
|
if (branchExists) {
|
|
464
496
|
const cloneArguments = sparseSegment
|
|
465
497
|
? ['clone', '-q', '--filter=blob:none', '--no-checkout', '--depth', '1', '--single-branch', '--branch', branch]
|
|
466
498
|
: ['clone', '-q', '--depth', '1', '--branch', branch];
|
|
467
|
-
const clone =
|
|
468
|
-
encoding: 'utf8',
|
|
469
|
-
maxBuffer: 1 << 20,
|
|
470
|
-
env: gitProcessEnvironment(),
|
|
471
|
-
});
|
|
499
|
+
const clone = runMapStoreNetworkGit(cwd, [...authenticationArguments, ...cloneArguments, remoteUrl, tmp]);
|
|
472
500
|
if (clone.status !== 0) {
|
|
473
501
|
fs.rmSync(tmp, { recursive: true, force: true });
|
|
474
|
-
throw new MapStoreError(clone
|
|
502
|
+
throw new MapStoreError(gitFailureMessage(clone, 'could not clone map store branch'));
|
|
475
503
|
}
|
|
476
504
|
}
|
|
477
505
|
else {
|
|
@@ -486,15 +514,15 @@ function checkoutMapStore(cwd, remote, branch, sparseSegment) {
|
|
|
486
514
|
}
|
|
487
515
|
function pushMapStoreCommit(cwd, temporaryCheckout, remote, branch, authenticationArguments) {
|
|
488
516
|
const pushFailures = [];
|
|
489
|
-
const isolatedPush =
|
|
517
|
+
const isolatedPush = runMapStoreNetworkGit(temporaryCheckout, [...authenticationArguments, 'push', '-q', 'origin', `HEAD:${branch}`], 1 << 20);
|
|
490
518
|
if (isolatedPush.status === 0)
|
|
491
519
|
return isolatedPush;
|
|
492
|
-
pushFailures.push(`isolated map-store push: ${isolatedPush
|
|
520
|
+
pushFailures.push(`isolated map-store push: ${gitFailureMessage(isolatedPush, `git exited ${isolatedPush.status}`)}`);
|
|
493
521
|
const mapStoreToken = process.env.STYLEPROOF_MAP_STORE_TOKEN;
|
|
494
522
|
if (mapStoreToken) {
|
|
495
523
|
const githubExtraHeaderKey = ['http.https:', '', 'github.com', '.extraheader'].join('/');
|
|
496
524
|
runGit(temporaryCheckout, ['config', '--local', '--unset-all', githubExtraHeaderKey], 1 << 20);
|
|
497
|
-
const credentialPush =
|
|
525
|
+
const credentialPush = runMapStoreNetworkGit(temporaryCheckout, [
|
|
498
526
|
'-c',
|
|
499
527
|
`${githubExtraHeaderKey}=`,
|
|
500
528
|
...workflowTokenCredentialArguments(),
|
|
@@ -502,18 +530,10 @@ function pushMapStoreCommit(cwd, temporaryCheckout, remote, branch, authenticati
|
|
|
502
530
|
'-q',
|
|
503
531
|
'origin',
|
|
504
532
|
`HEAD:${branch}`,
|
|
505
|
-
]
|
|
506
|
-
cwd: temporaryCheckout,
|
|
507
|
-
encoding: 'utf8',
|
|
508
|
-
maxBuffer: 1 << 20,
|
|
509
|
-
env: {
|
|
510
|
-
...gitProcessEnvironment(),
|
|
511
|
-
GIT_TERMINAL_PROMPT: '0',
|
|
512
|
-
},
|
|
513
|
-
});
|
|
533
|
+
]);
|
|
514
534
|
if (credentialPush.status === 0)
|
|
515
535
|
return credentialPush;
|
|
516
|
-
pushFailures.push(`workflow-token credential push: ${credentialPush
|
|
536
|
+
pushFailures.push(`workflow-token credential push: ${gitFailureMessage(credentialPush, `git exited ${credentialPush.status}`)}`);
|
|
517
537
|
}
|
|
518
538
|
const mapStoreCommit = gitOutput(temporaryCheckout, ['rev-parse', 'HEAD']);
|
|
519
539
|
const importCommit = runGit(cwd, ['fetch', '-q', '--no-write-fetch-head', temporaryCheckout, mapStoreCommit], 1 << 20);
|
|
@@ -526,14 +546,14 @@ function pushMapStoreCommit(cwd, temporaryCheckout, remote, branch, authenticati
|
|
|
526
546
|
].join('\n'),
|
|
527
547
|
};
|
|
528
548
|
}
|
|
529
|
-
const consumerCheckoutPush =
|
|
549
|
+
const consumerCheckoutPush = runMapStoreNetworkGit(cwd, ['push', '-q', remote, `${mapStoreCommit}:${branch}`], 1 << 20);
|
|
530
550
|
if (consumerCheckoutPush.status === 0)
|
|
531
551
|
return consumerCheckoutPush;
|
|
532
552
|
return {
|
|
533
553
|
...consumerCheckoutPush,
|
|
534
554
|
stderr: [
|
|
535
555
|
...pushFailures,
|
|
536
|
-
`consumer checkout push: ${consumerCheckoutPush
|
|
556
|
+
`consumer checkout push: ${gitFailureMessage(consumerCheckoutPush, `git exited ${consumerCheckoutPush.status}`)}`,
|
|
537
557
|
].join('\n'),
|
|
538
558
|
};
|
|
539
559
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "styleproof",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.20",
|
|
4
4
|
"description": "Catch every CSS change before it ships — review PRs and certify refactors by the browser's computed styles, not pixels. Works with any styling system.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"playwright",
|