styleproof 4.4.7 → 4.4.9
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 +24 -0
- package/dist/map-store.js +30 -15
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,8 +7,27 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [4.4.8] - 2026-07-13
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **Map-store restore now retrieves only the requested commit bundle.** Restore
|
|
15
|
+
clones branch metadata without a checkout, sparsely selects the requested SHA,
|
|
16
|
+
and, on partial-clone-capable remotes such as GitHub, downloads only that
|
|
17
|
+
bundle's blobs. Large long-lived map stores therefore no longer make every
|
|
18
|
+
cache lookup clone all historical bundles on supported remotes. Publishing
|
|
19
|
+
uses the same sparse checkout and stages only the requested bundle plus the
|
|
20
|
+
store README; Git's sparse index preserves unseen bundles without downloading
|
|
21
|
+
their blobs, so cache misses no longer materialise the complete store either.
|
|
22
|
+
|
|
23
|
+
## [4.4.7] - 2026-07-13
|
|
24
|
+
|
|
10
25
|
### Fixed
|
|
11
26
|
|
|
27
|
+
- **Explicit map-store credentials take precedence over checkout state.** When
|
|
28
|
+
`STYLEPROOF_MAP_STORE_TOKEN` is set, StyleProof now uses it before inspecting
|
|
29
|
+
persisted Git headers, so stale `actions/checkout` credentials cannot break a
|
|
30
|
+
cold-cache map upload.
|
|
12
31
|
- **Generated CI authenticates map publication explicitly.** `styleproof-init`
|
|
13
32
|
passes the workflow's least-privilege `github.token` as
|
|
14
33
|
`STYLEPROOF_MAP_STORE_TOKEN`, so cold-cache uploads do not depend on private
|
|
@@ -19,6 +38,11 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|
|
19
38
|
directly in `.git/config`; StyleProof now explicitly enables Git config includes
|
|
20
39
|
and falls back to its locally registered checkout config before carrying that
|
|
21
40
|
header into the isolated clone and push.
|
|
41
|
+
- **Map-store uploads now reuse credentials from `actions/checkout@v7`.**
|
|
42
|
+
Checkout v7 keeps its HTTP header in an included temporary config rather than
|
|
43
|
+
directly in `.git/config`; StyleProof now explicitly enables Git config includes
|
|
44
|
+
and falls back to its locally registered checkout config before carrying that
|
|
45
|
+
header into the isolated clone and push.
|
|
22
46
|
- **Map-store uploads now reuse the HTTP authentication persisted by
|
|
23
47
|
`actions/checkout`.** The isolated `styleproof-maps` clone carries the
|
|
24
48
|
checkout's URL-scoped extra header through clone and push, so cache-miss
|
package/dist/map-store.js
CHANGED
|
@@ -64,6 +64,15 @@ function parseGitHttpExtraHeaders(configuredHeaders) {
|
|
|
64
64
|
});
|
|
65
65
|
}
|
|
66
66
|
function effectiveGitHttpExtraHeaders(cwd) {
|
|
67
|
+
const mapStoreToken = process.env.STYLEPROOF_MAP_STORE_TOKEN;
|
|
68
|
+
if (mapStoreToken) {
|
|
69
|
+
return [
|
|
70
|
+
{
|
|
71
|
+
key: ['http.https:', '', 'github.com', '.extraheader'].join('/'),
|
|
72
|
+
value: `AUTHORIZATION: basic ${Buffer.from(`x-access-token:${mapStoreToken}`).toString('base64')}`,
|
|
73
|
+
},
|
|
74
|
+
];
|
|
75
|
+
}
|
|
67
76
|
const configuredHeaders = runGit(cwd, ['config', '--includes', '--get-regexp', '^http\\..*\\.extraheader$'], 1 << 20);
|
|
68
77
|
const effectiveHeaders = parseGitHttpExtraHeaders(configuredHeaders.stdout);
|
|
69
78
|
if (effectiveHeaders.length > 0)
|
|
@@ -82,15 +91,7 @@ function effectiveGitHttpExtraHeaders(cwd) {
|
|
|
82
91
|
});
|
|
83
92
|
if (includedHeaders.length > 0)
|
|
84
93
|
return includedHeaders;
|
|
85
|
-
|
|
86
|
-
if (!mapStoreToken)
|
|
87
|
-
return [];
|
|
88
|
-
return [
|
|
89
|
-
{
|
|
90
|
-
key: ['http.https:', '', 'github.com', '.extraheader'].join('/'),
|
|
91
|
-
value: `AUTHORIZATION: basic ${Buffer.from(`x-access-token:${mapStoreToken}`).toString('base64')}`,
|
|
92
|
-
},
|
|
93
|
-
];
|
|
94
|
+
return [];
|
|
94
95
|
}
|
|
95
96
|
function gitOutput(cwd, args) {
|
|
96
97
|
const r = runGit(cwd, args);
|
|
@@ -435,15 +436,27 @@ function copyDir(src, dest, includeHar) {
|
|
|
435
436
|
filter: (source) => includeHar || !source.endsWith('.har'),
|
|
436
437
|
});
|
|
437
438
|
}
|
|
438
|
-
function
|
|
439
|
+
function checkoutSparseSegment(tmp, branch, segment) {
|
|
440
|
+
const sparseCheckout = runGit(tmp, ['sparse-checkout', 'set', segment], 1 << 20);
|
|
441
|
+
const checkout = sparseCheckout.status === 0 ? runGit(tmp, ['checkout', '-q', branch], 1 << 20) : sparseCheckout;
|
|
442
|
+
if (checkout.status !== 0) {
|
|
443
|
+
fs.rmSync(tmp, { recursive: true, force: true });
|
|
444
|
+
throw new MapStoreError(checkout.stderr.trim() || `could not check out ${segment} from map store`);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function checkoutMapStore(cwd, remote, branch, sparseSegment) {
|
|
439
448
|
if (!remoteExists(remote, cwd))
|
|
440
449
|
throw new MapStoreError(`git remote ${remote} was not found`);
|
|
441
450
|
const remoteUrl = gitOutput(cwd, ['remote', 'get-url', remote]);
|
|
442
451
|
const httpExtraHeaders = effectiveGitHttpExtraHeaders(cwd);
|
|
443
452
|
const authenticationArguments = httpExtraHeaders.flatMap(({ key, value }) => ['-c', `${key}=${value}`]);
|
|
444
453
|
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'styleproof-map-store-'));
|
|
445
|
-
|
|
446
|
-
|
|
454
|
+
const branchExists = runGit(cwd, ['ls-remote', '--exit-code', '--heads', remote, branch], 1 << 20).status === 0;
|
|
455
|
+
if (branchExists) {
|
|
456
|
+
const cloneArguments = sparseSegment
|
|
457
|
+
? ['clone', '-q', '--filter=blob:none', '--no-checkout', '--depth', '1', '--single-branch', '--branch', branch]
|
|
458
|
+
: ['clone', '-q', '--depth', '1', '--branch', branch];
|
|
459
|
+
const clone = spawnSync('git', [...authenticationArguments, ...cloneArguments, remoteUrl, tmp], {
|
|
447
460
|
encoding: 'utf8',
|
|
448
461
|
maxBuffer: 1 << 20,
|
|
449
462
|
env: gitProcessEnvironment(),
|
|
@@ -459,6 +472,8 @@ function checkoutMapStore(cwd, remote, branch) {
|
|
|
459
472
|
}
|
|
460
473
|
for (const { key, value } of httpExtraHeaders)
|
|
461
474
|
runGit(tmp, ['config', '--local', key, value]);
|
|
475
|
+
if (sparseSegment && branchExists)
|
|
476
|
+
checkoutSparseSegment(tmp, branch, sparseSegment);
|
|
462
477
|
return tmp;
|
|
463
478
|
}
|
|
464
479
|
export function publishMapBundle(options) {
|
|
@@ -479,7 +494,7 @@ export function publishMapBundle(options) {
|
|
|
479
494
|
let ok = false;
|
|
480
495
|
let lastError = '';
|
|
481
496
|
for (let attempt = 1; attempt <= 5; attempt++) {
|
|
482
|
-
const tmp = checkoutMapStore(cwd, remote, branch);
|
|
497
|
+
const tmp = checkoutMapStore(cwd, remote, branch, sha);
|
|
483
498
|
try {
|
|
484
499
|
runGit(tmp, ['config', 'user.name', 'github-actions[bot]']);
|
|
485
500
|
runGit(tmp, ['config', 'user.email', '41898282+github-actions[bot]@users.noreply.github.com']);
|
|
@@ -489,7 +504,7 @@ export function publishMapBundle(options) {
|
|
|
489
504
|
if (!options.includeHar) {
|
|
490
505
|
fs.writeFileSync(path.join(tmp, target, MAP_MANIFEST), JSON.stringify({ ...manifest, har: false }, null, 2));
|
|
491
506
|
}
|
|
492
|
-
runGit(tmp, ['add', '-A']);
|
|
507
|
+
runGit(tmp, ['add', '-A', '--sparse', '--', 'README.md', target]);
|
|
493
508
|
runGit(tmp, ['commit', '-q', '-m', `StyleProof map ${sha.slice(0, 12)} ${compatibilityKey}`], 1 << 20);
|
|
494
509
|
const push = runGit(tmp, ['push', '-q', 'origin', `HEAD:${branch}`], 1 << 20);
|
|
495
510
|
if (push.status === 0) {
|
|
@@ -520,7 +535,7 @@ export function restoreMapBundle(options) {
|
|
|
520
535
|
if (runGit(cwd, ['ls-remote', '--exit-code', '--heads', remote, branch], 1 << 20).status !== 0) {
|
|
521
536
|
throw new MapStoreError(`map store branch ${branch} does not exist`);
|
|
522
537
|
}
|
|
523
|
-
const tmp = checkoutMapStore(cwd, remote, branch);
|
|
538
|
+
const tmp = checkoutMapStore(cwd, remote, branch, sha);
|
|
524
539
|
try {
|
|
525
540
|
const shaDir = path.join(tmp, sha);
|
|
526
541
|
if (!fs.existsSync(shaDir))
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "styleproof",
|
|
3
|
-
"version": "4.4.
|
|
3
|
+
"version": "4.4.9",
|
|
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",
|