@effected/github-actions 0.16.1 → 0.17.0-next-20260927071821
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/PackageManagerInstaller.js +124 -43
- package/index.d.ts +71 -11
- package/package.json +3 -3
|
@@ -7,7 +7,7 @@ import { PNPM_EXE_PREFIX, detectMusl, isNodeScript, pnpmExeTarget, strongestSri
|
|
|
7
7
|
import { ToolInstaller } from "./ToolInstaller.js";
|
|
8
8
|
import { Context, Effect, FileSystem, Layer, Option, Path, Schema } from "effect";
|
|
9
9
|
import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
|
|
10
|
-
import { DEFAULT_REGISTRY, PackageManagerPinName } from "@effected/npm";
|
|
10
|
+
import { CorepackIntegrityHash, DEFAULT_REGISTRY, PackageManagerPin, PackageManagerPinName } from "@effected/npm";
|
|
11
11
|
|
|
12
12
|
//#region src/PackageManagerInstaller.ts
|
|
13
13
|
/**
|
|
@@ -21,8 +21,16 @@ var PackageManagerInstallerError = class extends Schema.TaggedError()("PackageMa
|
|
|
21
21
|
* {@link ToolInstallerError} that caused them, preserved on `cause`
|
|
22
22
|
* (`cacheFailed` also covers a shim that could not be written into the
|
|
23
23
|
* entry). `integrityMismatch` — the downloaded artifact does not hash to
|
|
24
|
-
* what the pin
|
|
25
|
-
*
|
|
24
|
+
* what the pin or the `integrity` option (or, for pnpm 12's native
|
|
25
|
+
* binary, the registry or the caller's `nativeIntegrity`) declares;
|
|
26
|
+
* nothing was cached. Also raised before anything runs when the
|
|
27
|
+
* `integrity` option is malformed or disagrees with the pin (see
|
|
28
|
+
* {@link PackageManagerInstallOptions.integrity}).
|
|
29
|
+
* `integrityMissing` — neither the pin nor the `integrity` option
|
|
30
|
+
* carries integrity and the caller asked for `requireIntegrity`, or —
|
|
31
|
+
* with `subject` naming the package — the
|
|
32
|
+
* caller supplied `nativeIntegrity` without an entry for the host's
|
|
33
|
+
* `@pnpm/exe.*` package.
|
|
26
34
|
* `unsupportedPlatform` — no build exists for this runner's
|
|
27
35
|
* OS/architecture pair: bun publishes none, or pnpm 12 ships no
|
|
28
36
|
* `@pnpm/exe.*` native binary for it. `layoutUnexpected` — the artifact
|
|
@@ -57,7 +65,7 @@ var PackageManagerInstallerError = class extends Schema.TaggedError()("PackageMa
|
|
|
57
65
|
case "downloadFailed": return `Could not download ${pin}${this.subject === void 0 ? "" : ` from ${this.subject}`}`;
|
|
58
66
|
case "extractFailed": return `Could not extract ${pin}${this.subject === void 0 ? "" : ` (${this.subject})`}`;
|
|
59
67
|
case "integrityMismatch": return this.expected === void 0 || this.actual === void 0 ? `Could not verify the integrity of ${pin}${this.subject === void 0 ? "" : ` (${this.subject})`}` : `Integrity mismatch for ${pin}: expected ${this.expected}, got ${this.actual}`;
|
|
60
|
-
case "integrityMissing": return `
|
|
68
|
+
case "integrityMissing": return this.subject === void 0 ? `Neither the pin for ${pin} nor the integrity option carries an integrity hash, and requireIntegrity is set` : `No integrity was supplied for ${this.subject}, which ${pin} needs on this runner`;
|
|
61
69
|
case "unsupportedPlatform": return `No ${pin} build is published for ${this.subject}`;
|
|
62
70
|
case "layoutUnexpected": return `The ${pin} artifact does not have the expected layout${this.subject === void 0 ? "" : `: ${this.subject}`}`;
|
|
63
71
|
default: return `Could not cache ${pin} into the tool cache${this.subject === void 0 ? "" : `: ${this.subject}`}`;
|
|
@@ -241,25 +249,27 @@ const make = Effect.gen(function* () {
|
|
|
241
249
|
cause
|
|
242
250
|
})));
|
|
243
251
|
/**
|
|
244
|
-
* Verify a downloaded artifact against the pin's integrity,
|
|
252
|
+
* Verify a downloaded artifact against the settled pin's integrity,
|
|
253
|
+
* fail-closed.
|
|
245
254
|
*
|
|
246
|
-
*
|
|
255
|
+
* An integrity-less pin proceeds with a logged warning — in-the-wild
|
|
247
256
|
* `devEngines` pins routinely carry none, and the opt-in strictness lives in
|
|
248
257
|
* `requireIntegrity`, checked before anything is downloaded.
|
|
249
258
|
*/
|
|
250
259
|
const verifyIntegrity = (pin, file) => Effect.gen(function* () {
|
|
251
|
-
|
|
252
|
-
|
|
260
|
+
const integrity = pin.integrity;
|
|
261
|
+
if (integrity === void 0) {
|
|
262
|
+
yield* Effect.logWarning(`The pin ${pin.toString()} carries no integrity hash and none was supplied; the downloaded artifact was not verified.`);
|
|
253
263
|
return;
|
|
254
264
|
}
|
|
255
|
-
const dot =
|
|
256
|
-
const algorithm =
|
|
257
|
-
const expectedHex =
|
|
265
|
+
const dot = integrity.indexOf(".");
|
|
266
|
+
const algorithm = integrity.slice(0, dot);
|
|
267
|
+
const expectedHex = integrity.slice(dot + 1);
|
|
258
268
|
const actualHex = yield* hashFile(pin, file, algorithm);
|
|
259
269
|
if (actualHex !== expectedHex) return yield* Effect.fail(errorFor(pin)({
|
|
260
270
|
reason: "integrityMismatch",
|
|
261
271
|
subject: file,
|
|
262
|
-
expected:
|
|
272
|
+
expected: integrity,
|
|
263
273
|
actual: `${algorithm}.${actualHex}`
|
|
264
274
|
}));
|
|
265
275
|
});
|
|
@@ -422,17 +432,64 @@ const make = Effect.gen(function* () {
|
|
|
422
432
|
}));
|
|
423
433
|
});
|
|
424
434
|
/**
|
|
435
|
+
* The strongest digest an SRI value lists — or, when it is not a string or
|
|
436
|
+
* lists no usable algorithm, the could-not-verify arm of
|
|
437
|
+
* `integrityMismatch` naming `subject`.
|
|
438
|
+
*/
|
|
439
|
+
const expectedFromSri = (pin, sri, subject) => Option.match(typeof sri === "string" ? strongestSri(sri) : Option.none(), {
|
|
440
|
+
onNone: () => Effect.fail(errorFor(pin)({
|
|
441
|
+
reason: "integrityMismatch",
|
|
442
|
+
subject
|
|
443
|
+
})),
|
|
444
|
+
onSome: Effect.succeed
|
|
445
|
+
});
|
|
446
|
+
/**
|
|
447
|
+
* The expected integrity of a native package as its registry packument
|
|
448
|
+
* declares it for the exact version — fail-closed: a packument that cannot
|
|
449
|
+
* be read, parsed, or that lists no usable SRI is the could-not-verify arm
|
|
450
|
+
* of `integrityMismatch`, naming the packument url.
|
|
451
|
+
*/
|
|
452
|
+
const registryIntegrity = (pin, packageName, version, registry) => Effect.gen(function* () {
|
|
453
|
+
const packumentUrl = `${registry}/${packageName}/${version}`;
|
|
454
|
+
const packumentFile = yield* installer.download(packumentUrl).pipe(Effect.mapError(fromInstaller(pin)));
|
|
455
|
+
const unverifiable = (cause) => errorFor(pin)({
|
|
456
|
+
reason: "integrityMismatch",
|
|
457
|
+
subject: packumentUrl,
|
|
458
|
+
cause
|
|
459
|
+
});
|
|
460
|
+
const packument = yield* fs.readFileString(packumentFile).pipe(Effect.mapError(unverifiable), Effect.flatMap((raw) => Effect.try({
|
|
461
|
+
try: () => JSON.parse(raw),
|
|
462
|
+
catch: unverifiable
|
|
463
|
+
})));
|
|
464
|
+
return yield* expectedFromSri(pin, packument.dist?.integrity, packumentUrl);
|
|
465
|
+
});
|
|
466
|
+
/**
|
|
467
|
+
* The expected integrity of a native package as the caller's
|
|
468
|
+
* `nativeIntegrity` map records it — fail-closed: no entry for the host's
|
|
469
|
+
* package is `integrityMissing` (a lockfile records every platform, so a
|
|
470
|
+
* gap means the map is inconsistent), and an entry with no usable SRI is
|
|
471
|
+
* the could-not-verify arm of `integrityMismatch`, both naming the package.
|
|
472
|
+
*/
|
|
473
|
+
const suppliedIntegrity = (pin, packageName, nativeIntegrity) => {
|
|
474
|
+
const supplied = Object.hasOwn(nativeIntegrity, packageName) ? nativeIntegrity[packageName] : void 0;
|
|
475
|
+
return typeof supplied === "string" ? expectedFromSri(pin, supplied, packageName) : Effect.fail(errorFor(pin)({
|
|
476
|
+
reason: "integrityMissing",
|
|
477
|
+
subject: packageName
|
|
478
|
+
}));
|
|
479
|
+
};
|
|
480
|
+
/**
|
|
425
481
|
* pnpm 12's native overlay, done here because the installer never runs the
|
|
426
482
|
* lifecycle script that does it upstream: pick the host's `@pnpm/exe.*`
|
|
427
483
|
* package from the wrapper's optional dependencies, fetch its tarball from
|
|
428
|
-
* the SAME registry the wrapper came from, verify it against the
|
|
429
|
-
*
|
|
430
|
-
*
|
|
484
|
+
* the SAME registry the wrapper came from, verify it against the caller's
|
|
485
|
+
* `nativeIntegrity` entry when one was supplied or else the registry's own
|
|
486
|
+
* `dist.integrity` (fail-closed either way — this is a second artifact the
|
|
487
|
+
* pin never named, so there is no integrity-less posture to honor), and copy
|
|
431
488
|
* the executable over the placeholder in the STAGED wrapper, where `dist/`
|
|
432
489
|
* sits beside it as the binary expects. Answers the bins as they should be
|
|
433
490
|
* shimmed and recorded — retargeted to `.exe` on Windows, as upstream does.
|
|
434
491
|
*/
|
|
435
|
-
const overlayNativeBinary = (pin, packageDir, bins, nativePackages, registry) => Effect.gen(function* () {
|
|
492
|
+
const overlayNativeBinary = (pin, packageDir, { bins, nativePackages }, { registry, nativeIntegrity }) => Effect.gen(function* () {
|
|
436
493
|
const target = Option.getOrUndefined(pnpmExeTarget(runnerOs, arch, musl));
|
|
437
494
|
const packageName = target === void 0 ? void 0 : `${PNPM_EXE_PREFIX}${target}`;
|
|
438
495
|
const nativeVersion = packageName === void 0 ? void 0 : nativePackages[packageName];
|
|
@@ -449,19 +506,7 @@ const make = Effect.gen(function* () {
|
|
|
449
506
|
reason: "layoutUnexpected",
|
|
450
507
|
subject: `package.json names no ${pin.name} bin to overlay`
|
|
451
508
|
}));
|
|
452
|
-
const
|
|
453
|
-
const packumentFile = yield* installer.download(packumentUrl).pipe(Effect.mapError(fromInstaller(pin)));
|
|
454
|
-
const unverifiable = (cause) => errorFor(pin)({
|
|
455
|
-
reason: "integrityMismatch",
|
|
456
|
-
subject: packumentUrl,
|
|
457
|
-
...cause === void 0 ? {} : { cause }
|
|
458
|
-
});
|
|
459
|
-
const declared = (yield* fs.readFileString(packumentFile).pipe(Effect.mapError((cause) => unverifiable(cause)), Effect.flatMap((raw) => Effect.try({
|
|
460
|
-
try: () => JSON.parse(raw),
|
|
461
|
-
catch: (cause) => unverifiable(cause)
|
|
462
|
-
})))).dist?.integrity;
|
|
463
|
-
const expected = typeof declared === "string" ? Option.getOrUndefined(strongestSri(declared)) : void 0;
|
|
464
|
-
if (expected === void 0) return yield* Effect.fail(unverifiable());
|
|
509
|
+
const expected = nativeIntegrity === void 0 ? yield* registryIntegrity(pin, packageName, nativeVersion, registry) : yield* suppliedIntegrity(pin, packageName, nativeIntegrity);
|
|
465
510
|
const tarballUrl = `${registry}/${packageName}/-/exe.${target}-${nativeVersion}.tgz`;
|
|
466
511
|
const archive = yield* installer.download(tarballUrl).pipe(Effect.mapError(fromInstaller(pin)));
|
|
467
512
|
const actualHex = yield* hashFile(pin, archive, expected.algorithm);
|
|
@@ -525,9 +570,10 @@ const make = Effect.gen(function* () {
|
|
|
525
570
|
});
|
|
526
571
|
});
|
|
527
572
|
/** Download a registry tarball, verify, extract, shim, and cache the package dir. */
|
|
528
|
-
const installFromRegistry = (pin,
|
|
573
|
+
const installFromRegistry = (pin, source) => Effect.gen(function* () {
|
|
574
|
+
const { name } = pin;
|
|
529
575
|
const version = pin.version.toString();
|
|
530
|
-
const url = registryTarballUrl(name, version, pin.version.major, registry);
|
|
576
|
+
const url = registryTarballUrl(name, version, pin.version.major, source.registry);
|
|
531
577
|
const archive = yield* installer.download(url).pipe(Effect.mapError(fromInstaller(pin)));
|
|
532
578
|
const berry = name === "yarn" && pin.version.major >= 2;
|
|
533
579
|
if (!berry) yield* verifyIntegrity(pin, archive);
|
|
@@ -538,7 +584,7 @@ const make = Effect.gen(function* () {
|
|
|
538
584
|
subject: "tarball has no package/ root"
|
|
539
585
|
}));
|
|
540
586
|
const manifest = yield* readPackageManifest(pin, packageDir);
|
|
541
|
-
const bins = Object.keys(manifest.nativePackages).length > 0 ? yield* overlayNativeBinary(pin, packageDir, manifest
|
|
587
|
+
const bins = Object.keys(manifest.nativePackages).length > 0 ? yield* overlayNativeBinary(pin, packageDir, manifest, source) : manifest.bins;
|
|
542
588
|
if (berry) {
|
|
543
589
|
const cli = path.join(packageDir, "bin/yarn.js");
|
|
544
590
|
yield* assertFile(pin, cli, "bin/yarn.js is missing from the cli-dist tarball");
|
|
@@ -555,22 +601,54 @@ const make = Effect.gen(function* () {
|
|
|
555
601
|
bins: rootBins(bins, directory)
|
|
556
602
|
});
|
|
557
603
|
});
|
|
604
|
+
/**
|
|
605
|
+
* Fold the `integrity` option into the pin, answering the one pin every
|
|
606
|
+
* later step reads. The option's FORM is checked here, once — the type
|
|
607
|
+
* admits every `IntegrityHash` form, but only a corepack `<algo>.<hex>` can
|
|
608
|
+
* be compared with a pin's tail or split into an algorithm and a digest —
|
|
609
|
+
* and a pin integrity that disagrees with the option is refused rather than
|
|
610
|
+
* resolved by preferring either.
|
|
611
|
+
*
|
|
612
|
+
* A malformed option is `integrityMismatch` on its could-not-verify arm (no
|
|
613
|
+
* `expected`, no `actual`): the caller DID supply an integrity, so
|
|
614
|
+
* `integrityMissing` would misreport it, and a value that cannot be
|
|
615
|
+
* compared is exactly what that arm means.
|
|
616
|
+
*/
|
|
617
|
+
const settlePin = (pin, integrity) => Effect.gen(function* () {
|
|
618
|
+
if (integrity === void 0) return pin;
|
|
619
|
+
const option = yield* Schema.decodeUnknownEffect(CorepackIntegrityHash)(integrity).pipe(Effect.mapError((cause) => errorFor(pin)({
|
|
620
|
+
reason: "integrityMismatch",
|
|
621
|
+
subject: `the integrity option ${integrity} is not a corepack <algo>.<hex> hash`,
|
|
622
|
+
cause
|
|
623
|
+
})));
|
|
624
|
+
if (pin.integrity !== void 0 && pin.integrity !== option) return yield* Effect.fail(errorFor(pin)({
|
|
625
|
+
reason: "integrityMismatch",
|
|
626
|
+
subject: `the pin declares ${pin.integrity}, which disagrees with the integrity option`,
|
|
627
|
+
expected: option
|
|
628
|
+
}));
|
|
629
|
+
return PackageManagerPin.make({
|
|
630
|
+
name: pin.name,
|
|
631
|
+
version: pin.version,
|
|
632
|
+
integrity: option
|
|
633
|
+
});
|
|
634
|
+
});
|
|
558
635
|
return { install: Effect.fn("PackageManagerInstaller.install")(function* (pin, options) {
|
|
559
636
|
const version = pin.version.toString();
|
|
560
637
|
yield* Effect.annotateCurrentSpan({
|
|
561
638
|
name: pin.name,
|
|
562
639
|
version
|
|
563
640
|
});
|
|
564
|
-
|
|
565
|
-
|
|
641
|
+
const effective = yield* settlePin(pin, options?.integrity);
|
|
642
|
+
if (options?.requireIntegrity === true && effective.integrity === void 0) return yield* Effect.fail(errorFor(pin)({ reason: "integrityMissing" }));
|
|
643
|
+
const cached = yield* installer.find(effective.name, version);
|
|
566
644
|
if (Option.isSome(cached)) {
|
|
567
|
-
const record = yield* cachedRecord(
|
|
645
|
+
const record = yield* cachedRecord(effective, cached.value);
|
|
568
646
|
if (Option.isSome(record)) return record.value;
|
|
569
647
|
}
|
|
570
|
-
if (
|
|
648
|
+
if (effective.name === "npm" && options?.allowAmbient !== false) {
|
|
571
649
|
const probed = yield* ambientNpmVersion;
|
|
572
650
|
if (Option.isSome(probed) && probed.value === version) return AmbientPackageManager.make({
|
|
573
|
-
name:
|
|
651
|
+
name: effective.name,
|
|
574
652
|
version,
|
|
575
653
|
bins: {
|
|
576
654
|
npm: "npm",
|
|
@@ -578,9 +656,11 @@ const make = Effect.gen(function* () {
|
|
|
578
656
|
}
|
|
579
657
|
});
|
|
580
658
|
}
|
|
581
|
-
if (
|
|
582
|
-
|
|
583
|
-
|
|
659
|
+
if (effective.name === "bun") return yield* installBun(effective);
|
|
660
|
+
return yield* installFromRegistry(effective, {
|
|
661
|
+
registry: (options?.registry ?? DEFAULT_REGISTRY).replace(/\/+$/, ""),
|
|
662
|
+
nativeIntegrity: options?.nativeIntegrity
|
|
663
|
+
});
|
|
584
664
|
}) };
|
|
585
665
|
});
|
|
586
666
|
const dies = unstubbed("PackageManagerInstaller.makeTest");
|
|
@@ -593,9 +673,10 @@ const dies = unstubbed("PackageManagerInstaller.makeTest");
|
|
|
593
673
|
* ambient `npm --version` probe (every Node toolchain ships npm), and only
|
|
594
674
|
* then the manager's own dist: npm, pnpm and yarn 1.x from their registry
|
|
595
675
|
* tarballs, yarn 2+ (Berry) from `@yarnpkg/cli-dist`, bun from its
|
|
596
|
-
* per-platform GitHub-release zip.
|
|
597
|
-
*
|
|
598
|
-
*
|
|
676
|
+
* per-platform GitHub-release zip. An install with an expected integrity —
|
|
677
|
+
* the pin's `+<integrity>` tail or the `integrity` option — is verified
|
|
678
|
+
* fail-closed against what corepack itself hashes; one without proceeds with
|
|
679
|
+
* a logged warning unless `requireIntegrity` says otherwise.
|
|
599
680
|
*
|
|
600
681
|
* Every tool-cache answer carries a `binDir` a consumer can hand straight to
|
|
601
682
|
* `ActionOutputs.addPath`: the npm-registry managers get a `.bin` directory
|
package/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { HttpClient } from "effect/unstable/http";
|
|
|
4
4
|
import { ChildProcessSpawner } from "effect/unstable/process";
|
|
5
5
|
import { IdentityToken, SlsaProvenance } from "@effected/sbom";
|
|
6
6
|
import { BotIdentity, GitHubApp, GitHubClient, InstallationToken, PermissionLevel, RetryPolicy } from "@effected/github";
|
|
7
|
-
import { PackageManagerPin } from "@effected/npm";
|
|
7
|
+
import { IntegrityHashBrand, PackageManagerPin } from "@effected/npm";
|
|
8
8
|
//#region src/ActionEnvironment.d.ts
|
|
9
9
|
declare const ActionEnvironmentError_base: Schema.Class<ActionEnvironmentError, Schema.TaggedStruct<"ActionEnvironmentError", {
|
|
10
10
|
readonly reason: Schema.Literals<readonly ["missing", "malformed"]>;
|
|
@@ -4597,8 +4597,16 @@ declare const PackageManagerInstallerError_base: Schema.Class<PackageManagerInst
|
|
|
4597
4597
|
* {@link ToolInstallerError} that caused them, preserved on `cause`
|
|
4598
4598
|
* (`cacheFailed` also covers a shim that could not be written into the
|
|
4599
4599
|
* entry). `integrityMismatch` — the downloaded artifact does not hash to
|
|
4600
|
-
* what the pin
|
|
4601
|
-
*
|
|
4600
|
+
* what the pin or the `integrity` option (or, for pnpm 12's native
|
|
4601
|
+
* binary, the registry or the caller's `nativeIntegrity`) declares;
|
|
4602
|
+
* nothing was cached. Also raised before anything runs when the
|
|
4603
|
+
* `integrity` option is malformed or disagrees with the pin (see
|
|
4604
|
+
* {@link PackageManagerInstallOptions.integrity}).
|
|
4605
|
+
* `integrityMissing` — neither the pin nor the `integrity` option
|
|
4606
|
+
* carries integrity and the caller asked for `requireIntegrity`, or —
|
|
4607
|
+
* with `subject` naming the package — the
|
|
4608
|
+
* caller supplied `nativeIntegrity` without an entry for the host's
|
|
4609
|
+
* `@pnpm/exe.*` package.
|
|
4602
4610
|
* `unsupportedPlatform` — no build exists for this runner's
|
|
4603
4611
|
* OS/architecture pair: bun publishes none, or pnpm 12 ships no
|
|
4604
4612
|
* `@pnpm/exe.*` native binary for it. `layoutUnexpected` — the artifact
|
|
@@ -4634,11 +4642,40 @@ export declare class PackageManagerInstallerError extends PackageManagerInstalle
|
|
|
4634
4642
|
*/
|
|
4635
4643
|
interface PackageManagerInstallOptions {
|
|
4636
4644
|
/**
|
|
4637
|
-
* Fail with `integrityMissing` when the pin
|
|
4638
|
-
* instead of proceeding with a logged
|
|
4639
|
-
* in-the-wild `devEngines` pins routinely
|
|
4645
|
+
* Fail with `integrityMissing` when neither the pin nor the `integrity`
|
|
4646
|
+
* option carries an integrity hash, instead of proceeding with a logged
|
|
4647
|
+
* warning. Off by default, because in-the-wild `devEngines` pins routinely
|
|
4648
|
+
* carry no integrity.
|
|
4640
4649
|
*/
|
|
4641
4650
|
readonly requireIntegrity?: boolean | undefined;
|
|
4651
|
+
/**
|
|
4652
|
+
* The expected integrity of the manager's own artifact, supplied beside
|
|
4653
|
+
* the pin rather than through its `+<integrity>` tail — for a caller whose
|
|
4654
|
+
* digest comes from somewhere other than the pin (a lockfile, or the
|
|
4655
|
+
* registry's `dist.integrity`) and that should not have to rewrite the pin
|
|
4656
|
+
* to carry it.
|
|
4657
|
+
*
|
|
4658
|
+
* @remarks
|
|
4659
|
+
* Corepack form only (`<algo>.<hex>`), the same brand the pin's own
|
|
4660
|
+
* `integrity` carries; convert a registry or lockfile SRI string with
|
|
4661
|
+
* `CorepackIntegrityHash.fromSri` from `@effected/npm`. It verifies
|
|
4662
|
+
* exactly what a pin integrity verifies — the registry tarball for npm,
|
|
4663
|
+
* pnpm and yarn 1.x, the standalone `yarn.js` for yarn 2+, the platform zip
|
|
4664
|
+
* for bun — and stands in for the pin's in every rule: it silences the
|
|
4665
|
+
* "carries no integrity hash" warning, satisfies `requireIntegrity`, and a
|
|
4666
|
+
* tool-cache hit is answered without re-verifying, exactly as it is for an
|
|
4667
|
+
* integrity-carrying pin.
|
|
4668
|
+
*
|
|
4669
|
+
* Fail-closed, before any cache lookup or download: a value not in corepack
|
|
4670
|
+
* form (an SRI or yarn hash) fails with `integrityMismatch` on its
|
|
4671
|
+
* could-not-verify arm (no `expected`, no `actual`, `subject` naming the
|
|
4672
|
+
* option); and when the pin also carries an integrity and the two differ,
|
|
4673
|
+
* the install fails with `integrityMismatch` (`expected` is this option,
|
|
4674
|
+
* `subject` names the pin's value) — neither is chosen silently. Equal
|
|
4675
|
+
* values verify once. It governs the wrapper only; pnpm 12's native
|
|
4676
|
+
* binary is `nativeIntegrity`'s business.
|
|
4677
|
+
*/
|
|
4678
|
+
readonly integrity?: IntegrityHashBrand | undefined;
|
|
4642
4679
|
/**
|
|
4643
4680
|
* The npm registry host the npm, pnpm and yarn tarballs download from.
|
|
4644
4681
|
* Defaults to `https://registry.npmjs.org`. A corporate mirror qualifies
|
|
@@ -4647,10 +4684,32 @@ interface PackageManagerInstallOptions {
|
|
|
4647
4684
|
* artifact verified against the registry's own integrity — the
|
|
4648
4685
|
* `/<name>/<version>` packument route as JSON carrying `dist.integrity`.
|
|
4649
4686
|
* A tarball-only proxy fails a pnpm 12 pin with `downloadFailed` naming
|
|
4650
|
-
* that packument url
|
|
4651
|
-
*
|
|
4687
|
+
* that packument url — unless `nativeIntegrity` vouches for the host's
|
|
4688
|
+
* native package, which skips the packument. bun does not ship through a
|
|
4689
|
+
* registry — its per-platform zip always comes from GitHub releases.
|
|
4652
4690
|
*/
|
|
4653
4691
|
readonly registry?: string | undefined;
|
|
4692
|
+
/**
|
|
4693
|
+
* The expected Subresource Integrity of each pnpm native-binary package,
|
|
4694
|
+
* keyed by bare package name with no version (`"@pnpm/exe.linux-x64"`) —
|
|
4695
|
+
* usually read straight from the lockfile, which records every platform's
|
|
4696
|
+
* entry.
|
|
4697
|
+
*
|
|
4698
|
+
* @remarks
|
|
4699
|
+
* Consulted only for a pin whose wrapper overlays a native binary (pnpm 12
|
|
4700
|
+
* and later); every other pin ignores it. When supplied, the installer
|
|
4701
|
+
* verifies the host's `@pnpm/exe.<target>` tarball against this map's entry
|
|
4702
|
+
* (its strongest listed algorithm) INSTEAD of the registry's packument, so
|
|
4703
|
+
* the packument route is never requested and a tarball-only mirror
|
|
4704
|
+
* suffices. Fail-closed throughout: a map with no entry for the host's
|
|
4705
|
+
* package fails with `integrityMissing` naming that package, an entry
|
|
4706
|
+
* carrying no parseable SRI fails with `integrityMismatch` (the
|
|
4707
|
+
* could-not-verify arm), and a tarball that hashes to anything else fails
|
|
4708
|
+
* with `integrityMismatch` naming the tarball url. Absent, the registry's
|
|
4709
|
+
* own `dist.integrity` is the authority, as before. A tool-cache hit is
|
|
4710
|
+
* answered without re-verifying, exactly as the pin's own integrity is.
|
|
4711
|
+
*/
|
|
4712
|
+
readonly nativeIntegrity?: Readonly<Record<string, string>> | undefined;
|
|
4654
4713
|
/**
|
|
4655
4714
|
* Whether an npm pin may be answered by the runner's own ambient npm.
|
|
4656
4715
|
* Defaults to `true`.
|
|
@@ -4775,9 +4834,10 @@ declare const PackageManagerInstaller_base: Context.ServiceClass<PackageManagerI
|
|
|
4775
4834
|
* ambient `npm --version` probe (every Node toolchain ships npm), and only
|
|
4776
4835
|
* then the manager's own dist: npm, pnpm and yarn 1.x from their registry
|
|
4777
4836
|
* tarballs, yarn 2+ (Berry) from `@yarnpkg/cli-dist`, bun from its
|
|
4778
|
-
* per-platform GitHub-release zip.
|
|
4779
|
-
*
|
|
4780
|
-
*
|
|
4837
|
+
* per-platform GitHub-release zip. An install with an expected integrity —
|
|
4838
|
+
* the pin's `+<integrity>` tail or the `integrity` option — is verified
|
|
4839
|
+
* fail-closed against what corepack itself hashes; one without proceeds with
|
|
4840
|
+
* a logged warning unless `requireIntegrity` says otherwise.
|
|
4781
4841
|
*
|
|
4782
4842
|
* Every tool-cache answer carries a `binDir` a consumer can hand straight to
|
|
4783
4843
|
* `ActionOutputs.addPath`: the npm-registry managers get a `.bin` directory
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effected/github-actions",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0-next-20260927071821",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The GitHub Actions runtime: env, inputs, outputs, state, logging, cache, artifacts, blob storage, OIDC and the token bridge.",
|
|
6
6
|
"keywords": [
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"@effected/github": "^0.13.0",
|
|
43
43
|
"@effected/glob": "^0.8.0",
|
|
44
44
|
"@effected/markdown": "^0.12.1",
|
|
45
|
-
"@effected/npm": "^0.
|
|
46
|
-
"@effected/sbom": "^0.8.
|
|
45
|
+
"@effected/npm": "^0.17.0-next-20260927071821",
|
|
46
|
+
"@effected/sbom": "^0.8.1-next-20260927071821",
|
|
47
47
|
"@effected/semver": "^0.9.0",
|
|
48
48
|
"@effected/templates": "^0.8.0",
|
|
49
49
|
"@effected/walker": "^0.12.0"
|