styleproof 4.4.19 → 4.4.21
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 +16 -0
- package/dist/map-store.js +56 -25
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [4.4.21] - 2026-07-14
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **GitHub Actions map publication no longer sends duplicate authorization headers.**
|
|
15
|
+
StyleProof now resets inherited checkout headers before applying the single
|
|
16
|
+
effective credential to isolated map-store clone and push operations.
|
|
17
|
+
|
|
18
|
+
## [4.4.20] - 2026-07-14
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **Map-store network operations can no longer wedge CI indefinitely.** Remote
|
|
23
|
+
lookup, clone, and push commands now have a bounded timeout, and a stalled
|
|
24
|
+
isolated push falls through to the authenticated consumer checkout path.
|
|
25
|
+
|
|
10
26
|
## [4.4.19] - 2026-07-14
|
|
11
27
|
|
|
12
28
|
### 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}`];
|
|
@@ -67,6 +94,17 @@ function parseGitHttpExtraHeaders(configuredHeaders) {
|
|
|
67
94
|
return [{ key: configuredHeader.slice(0, separatorIndex), value: configuredHeader.slice(separatorIndex + 1) }];
|
|
68
95
|
});
|
|
69
96
|
}
|
|
97
|
+
function resetInheritedGitHttpExtraHeaders(configuredHeaders) {
|
|
98
|
+
const resetHeaderKeys = new Set();
|
|
99
|
+
return configuredHeaders.flatMap((configuredHeader) => {
|
|
100
|
+
if (resetHeaderKeys.has(configuredHeader.key))
|
|
101
|
+
return [configuredHeader];
|
|
102
|
+
resetHeaderKeys.add(configuredHeader.key);
|
|
103
|
+
return configuredHeader.value === ''
|
|
104
|
+
? [configuredHeader]
|
|
105
|
+
: [{ key: configuredHeader.key, value: '' }, configuredHeader];
|
|
106
|
+
});
|
|
107
|
+
}
|
|
70
108
|
function effectiveGitHttpExtraHeaders(cwd) {
|
|
71
109
|
const mapStoreToken = process.env.STYLEPROOF_MAP_STORE_TOKEN;
|
|
72
110
|
if (mapStoreToken) {
|
|
@@ -84,7 +122,7 @@ function effectiveGitHttpExtraHeaders(cwd) {
|
|
|
84
122
|
const configuredHeaders = runGit(cwd, ['config', '--includes', '--get-regexp', '^http\\..*\\.extraheader$'], 1 << 20);
|
|
85
123
|
const effectiveHeaders = parseGitHttpExtraHeaders(configuredHeaders.stdout);
|
|
86
124
|
if (effectiveHeaders.length > 0)
|
|
87
|
-
return effectiveHeaders;
|
|
125
|
+
return resetInheritedGitHttpExtraHeaders(effectiveHeaders);
|
|
88
126
|
const registeredIncludes = runGit(cwd, ['config', '--local', '--get-regexp', '^includeIf\\..*\\.path$'], 1 << 20);
|
|
89
127
|
const includedHeaders = registeredIncludes.stdout
|
|
90
128
|
.split('\n')
|
|
@@ -98,7 +136,7 @@ function effectiveGitHttpExtraHeaders(cwd) {
|
|
|
98
136
|
return parseGitHttpExtraHeaders(includedHeaders.stdout);
|
|
99
137
|
});
|
|
100
138
|
if (includedHeaders.length > 0)
|
|
101
|
-
return includedHeaders;
|
|
139
|
+
return resetInheritedGitHttpExtraHeaders(includedHeaders);
|
|
102
140
|
return [];
|
|
103
141
|
}
|
|
104
142
|
function gitOutput(cwd, args) {
|
|
@@ -459,19 +497,20 @@ function checkoutMapStore(cwd, remote, branch, sparseSegment) {
|
|
|
459
497
|
const httpExtraHeaders = effectiveGitHttpExtraHeaders(cwd);
|
|
460
498
|
const authenticationArguments = httpExtraHeaders.flatMap(({ key, value }) => ['-c', `${key}=${value}`]);
|
|
461
499
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'styleproof-map-store-'));
|
|
462
|
-
const
|
|
500
|
+
const branchLookup = runMapStoreNetworkGit(cwd, ['ls-remote', '--exit-code', '--heads', remote, branch], 1 << 20);
|
|
501
|
+
if (branchLookup.status !== 0 && branchLookup.status !== 2) {
|
|
502
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
503
|
+
throw new MapStoreError(gitFailureMessage(branchLookup, 'could not query map store branch'));
|
|
504
|
+
}
|
|
505
|
+
const branchExists = branchLookup.status === 0;
|
|
463
506
|
if (branchExists) {
|
|
464
507
|
const cloneArguments = sparseSegment
|
|
465
508
|
? ['clone', '-q', '--filter=blob:none', '--no-checkout', '--depth', '1', '--single-branch', '--branch', branch]
|
|
466
509
|
: ['clone', '-q', '--depth', '1', '--branch', branch];
|
|
467
|
-
const clone =
|
|
468
|
-
encoding: 'utf8',
|
|
469
|
-
maxBuffer: 1 << 20,
|
|
470
|
-
env: gitProcessEnvironment(),
|
|
471
|
-
});
|
|
510
|
+
const clone = runMapStoreNetworkGit(cwd, [...authenticationArguments, ...cloneArguments, remoteUrl, tmp]);
|
|
472
511
|
if (clone.status !== 0) {
|
|
473
512
|
fs.rmSync(tmp, { recursive: true, force: true });
|
|
474
|
-
throw new MapStoreError(clone
|
|
513
|
+
throw new MapStoreError(gitFailureMessage(clone, 'could not clone map store branch'));
|
|
475
514
|
}
|
|
476
515
|
}
|
|
477
516
|
else {
|
|
@@ -479,22 +518,22 @@ function checkoutMapStore(cwd, remote, branch, sparseSegment) {
|
|
|
479
518
|
runGit(tmp, ['remote', 'add', 'origin', remoteUrl]);
|
|
480
519
|
}
|
|
481
520
|
for (const { key, value } of httpExtraHeaders)
|
|
482
|
-
runGit(tmp, ['config', '--local', key, value]);
|
|
521
|
+
runGit(tmp, ['config', '--local', '--add', key, value]);
|
|
483
522
|
if (sparseSegment && branchExists)
|
|
484
523
|
checkoutSparseSegment(tmp, branch, sparseSegment);
|
|
485
524
|
return tmp;
|
|
486
525
|
}
|
|
487
526
|
function pushMapStoreCommit(cwd, temporaryCheckout, remote, branch, authenticationArguments) {
|
|
488
527
|
const pushFailures = [];
|
|
489
|
-
const isolatedPush =
|
|
528
|
+
const isolatedPush = runMapStoreNetworkGit(temporaryCheckout, [...authenticationArguments, 'push', '-q', 'origin', `HEAD:${branch}`], 1 << 20);
|
|
490
529
|
if (isolatedPush.status === 0)
|
|
491
530
|
return isolatedPush;
|
|
492
|
-
pushFailures.push(`isolated map-store push: ${isolatedPush
|
|
531
|
+
pushFailures.push(`isolated map-store push: ${gitFailureMessage(isolatedPush, `git exited ${isolatedPush.status}`)}`);
|
|
493
532
|
const mapStoreToken = process.env.STYLEPROOF_MAP_STORE_TOKEN;
|
|
494
533
|
if (mapStoreToken) {
|
|
495
534
|
const githubExtraHeaderKey = ['http.https:', '', 'github.com', '.extraheader'].join('/');
|
|
496
535
|
runGit(temporaryCheckout, ['config', '--local', '--unset-all', githubExtraHeaderKey], 1 << 20);
|
|
497
|
-
const credentialPush =
|
|
536
|
+
const credentialPush = runMapStoreNetworkGit(temporaryCheckout, [
|
|
498
537
|
'-c',
|
|
499
538
|
`${githubExtraHeaderKey}=`,
|
|
500
539
|
...workflowTokenCredentialArguments(),
|
|
@@ -502,18 +541,10 @@ function pushMapStoreCommit(cwd, temporaryCheckout, remote, branch, authenticati
|
|
|
502
541
|
'-q',
|
|
503
542
|
'origin',
|
|
504
543
|
`HEAD:${branch}`,
|
|
505
|
-
]
|
|
506
|
-
cwd: temporaryCheckout,
|
|
507
|
-
encoding: 'utf8',
|
|
508
|
-
maxBuffer: 1 << 20,
|
|
509
|
-
env: {
|
|
510
|
-
...gitProcessEnvironment(),
|
|
511
|
-
GIT_TERMINAL_PROMPT: '0',
|
|
512
|
-
},
|
|
513
|
-
});
|
|
544
|
+
]);
|
|
514
545
|
if (credentialPush.status === 0)
|
|
515
546
|
return credentialPush;
|
|
516
|
-
pushFailures.push(`workflow-token credential push: ${credentialPush
|
|
547
|
+
pushFailures.push(`workflow-token credential push: ${gitFailureMessage(credentialPush, `git exited ${credentialPush.status}`)}`);
|
|
517
548
|
}
|
|
518
549
|
const mapStoreCommit = gitOutput(temporaryCheckout, ['rev-parse', 'HEAD']);
|
|
519
550
|
const importCommit = runGit(cwd, ['fetch', '-q', '--no-write-fetch-head', temporaryCheckout, mapStoreCommit], 1 << 20);
|
|
@@ -526,14 +557,14 @@ function pushMapStoreCommit(cwd, temporaryCheckout, remote, branch, authenticati
|
|
|
526
557
|
].join('\n'),
|
|
527
558
|
};
|
|
528
559
|
}
|
|
529
|
-
const consumerCheckoutPush =
|
|
560
|
+
const consumerCheckoutPush = runMapStoreNetworkGit(cwd, ['push', '-q', remote, `${mapStoreCommit}:${branch}`], 1 << 20);
|
|
530
561
|
if (consumerCheckoutPush.status === 0)
|
|
531
562
|
return consumerCheckoutPush;
|
|
532
563
|
return {
|
|
533
564
|
...consumerCheckoutPush,
|
|
534
565
|
stderr: [
|
|
535
566
|
...pushFailures,
|
|
536
|
-
`consumer checkout push: ${consumerCheckoutPush
|
|
567
|
+
`consumer checkout push: ${gitFailureMessage(consumerCheckoutPush, `git exited ${consumerCheckoutPush.status}`)}`,
|
|
537
568
|
].join('\n'),
|
|
538
569
|
};
|
|
539
570
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "styleproof",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.21",
|
|
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",
|