@mannyc1/ts-release 0.0.0 → 0.0.2
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/ARCHITECTURE.md +53 -0
- package/README.md +243 -43
- package/SPEC.md +8 -1
- package/dist/cli/command.d.ts +1 -1
- package/dist/cli/command.d.ts.map +1 -1
- package/dist/cli/command.js +116 -33
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/main.js +3 -6
- package/dist/cli/main.js.map +1 -1
- package/dist/domain/evidence.d.ts +49 -3
- package/dist/domain/evidence.d.ts.map +1 -1
- package/dist/domain/evidence.js +43 -2
- package/dist/domain/evidence.js.map +1 -1
- package/dist/domain/operation.d.ts +56 -2
- package/dist/domain/operation.d.ts.map +1 -1
- package/dist/domain/operation.js +78 -2
- package/dist/domain/operation.js.map +1 -1
- package/dist/domain/release.d.ts +4 -4
- package/dist/domain/remote-state.d.ts +90 -0
- package/dist/domain/remote-state.d.ts.map +1 -0
- package/dist/domain/remote-state.js +85 -0
- package/dist/domain/remote-state.js.map +1 -0
- package/dist/domain/status.d.ts +43 -0
- package/dist/domain/status.d.ts.map +1 -0
- package/dist/domain/status.js +50 -0
- package/dist/domain/status.js.map +1 -0
- package/dist/domain/target.d.ts +63 -3
- package/dist/domain/target.d.ts.map +1 -1
- package/dist/domain/target.js +75 -5
- package/dist/domain/target.js.map +1 -1
- package/dist/host/host.d.ts +7 -23
- package/dist/host/host.d.ts.map +1 -1
- package/dist/host/host.js +3 -22
- package/dist/host/host.js.map +1 -1
- package/dist/host/http-live.d.ts +6 -0
- package/dist/host/http-live.d.ts.map +1 -0
- package/dist/host/http-live.js +82 -0
- package/dist/host/http-live.js.map +1 -0
- package/dist/host/http.d.ts +40 -0
- package/dist/host/http.d.ts.map +1 -0
- package/dist/host/http.js +56 -0
- package/dist/host/http.js.map +1 -0
- package/dist/host/platform.d.ts +10 -0
- package/dist/host/platform.d.ts.map +1 -0
- package/dist/host/platform.js +121 -0
- package/dist/host/platform.js.map +1 -0
- package/dist/host/test.d.ts +6 -3
- package/dist/host/test.d.ts.map +1 -1
- package/dist/host/test.js +111 -25
- package/dist/host/test.js.map +1 -1
- package/dist/planner/artifact-inventory.d.ts +9 -0
- package/dist/planner/artifact-inventory.d.ts.map +1 -0
- package/dist/planner/artifact-inventory.js +66 -0
- package/dist/planner/artifact-inventory.js.map +1 -0
- package/dist/planner/create-release-plan.d.ts +1 -1
- package/dist/planner/create-release-plan.d.ts.map +1 -1
- package/dist/planner/errors.d.ts +41 -3
- package/dist/planner/errors.d.ts.map +1 -1
- package/dist/planner/errors.js +35 -3
- package/dist/planner/errors.js.map +1 -1
- package/dist/planner/evidence-recorder.d.ts +16 -8
- package/dist/planner/evidence-recorder.d.ts.map +1 -1
- package/dist/planner/evidence-recorder.js +244 -17
- package/dist/planner/evidence-recorder.js.map +1 -1
- package/dist/planner/executor.d.ts +54 -15
- package/dist/planner/executor.d.ts.map +1 -1
- package/dist/planner/executor.js +117 -38
- package/dist/planner/executor.js.map +1 -1
- package/dist/planner/normalize-release.d.ts +2 -2
- package/dist/planner/normalize-release.d.ts.map +1 -1
- package/dist/planner/normalize-release.js +80 -42
- package/dist/planner/normalize-release.js.map +1 -1
- package/dist/planner/reconcile.d.ts +17 -0
- package/dist/planner/reconcile.d.ts.map +1 -0
- package/dist/planner/reconcile.js +280 -0
- package/dist/planner/reconcile.js.map +1 -0
- package/dist/planner/release-eligibility.d.ts +33 -0
- package/dist/planner/release-eligibility.d.ts.map +1 -0
- package/dist/planner/release-eligibility.js +172 -0
- package/dist/planner/release-eligibility.js.map +1 -0
- package/dist/planner/render-plan.d.ts.map +1 -1
- package/dist/planner/render-plan.js +30 -0
- package/dist/planner/render-plan.js.map +1 -1
- package/dist/planner/status.d.ts +40 -0
- package/dist/planner/status.d.ts.map +1 -0
- package/dist/planner/status.js +336 -0
- package/dist/planner/status.js.map +1 -0
- package/dist/runtime/bun.d.ts +9 -0
- package/dist/runtime/bun.d.ts.map +1 -0
- package/dist/runtime/bun.js +10 -0
- package/dist/runtime/bun.js.map +1 -0
- package/dist/targets/adapter-helpers.d.ts +31 -0
- package/dist/targets/adapter-helpers.d.ts.map +1 -0
- package/dist/targets/adapter-helpers.js +67 -0
- package/dist/targets/adapter-helpers.js.map +1 -0
- package/dist/targets/adapter.d.ts +3 -1
- package/dist/targets/adapter.d.ts.map +1 -1
- package/dist/targets/github.d.ts +2 -2
- package/dist/targets/github.d.ts.map +1 -1
- package/dist/targets/github.js +74 -83
- package/dist/targets/github.js.map +1 -1
- package/dist/targets/homebrew.d.ts +2 -2
- package/dist/targets/homebrew.d.ts.map +1 -1
- package/dist/targets/homebrew.js +45 -75
- package/dist/targets/homebrew.js.map +1 -1
- package/dist/targets/live.d.ts.map +1 -1
- package/dist/targets/live.js +10 -0
- package/dist/targets/live.js.map +1 -1
- package/dist/targets/npm.d.ts +2 -3
- package/dist/targets/npm.d.ts.map +1 -1
- package/dist/targets/npm.js +90 -55
- package/dist/targets/npm.js.map +1 -1
- package/dist/targets/pypi.d.ts +11 -0
- package/dist/targets/pypi.d.ts.map +1 -0
- package/dist/targets/pypi.js +115 -0
- package/dist/targets/pypi.js.map +1 -0
- package/dist/targets/registry.d.ts +3 -3
- package/dist/targets/registry.d.ts.map +1 -1
- package/dist/targets/scoop.d.ts +11 -0
- package/dist/targets/scoop.d.ts.map +1 -0
- package/dist/targets/scoop.js +93 -0
- package/dist/targets/scoop.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +2 -0
- package/dist/version.js.map +1 -0
- package/dist/workflows/config.d.ts +81 -0
- package/dist/workflows/config.d.ts.map +1 -0
- package/dist/workflows/config.js +191 -0
- package/dist/workflows/config.js.map +1 -0
- package/dist/workflows/evidence.d.ts +21 -0
- package/dist/workflows/evidence.d.ts.map +1 -0
- package/dist/workflows/evidence.js +45 -0
- package/dist/workflows/evidence.js.map +1 -0
- package/dist/workflows/live.d.ts +7 -0
- package/dist/workflows/live.d.ts.map +1 -0
- package/dist/workflows/live.js +5 -0
- package/dist/workflows/live.js.map +1 -0
- package/examples/README.md +20 -3
- package/examples/github-release/release.config.json +2 -1
- package/examples/multi-target/artifacts/release-example-multi-target-0.1.0.tgz +1 -0
- package/examples/multi-target/index.js +1 -0
- package/examples/multi-target/package.json +7 -0
- package/examples/multi-target/release.config.json +67 -0
- package/examples/non-strict-skips/release.config.json +1 -0
- package/examples/npm-first-publish/release.config.json +32 -0
- package/examples/npm-only/release.config.json +6 -1
- package/examples/pypi-registry/artifacts/release_example_pypi-0.1.0-py3-none-any.whl +1 -0
- package/examples/pypi-registry/release.config.json +30 -0
- package/examples/scoop-bucket/artifacts/release-example-scoop-0.1.0.zip +1 -0
- package/examples/scoop-bucket/release.config.json +36 -0
- package/package.json +48 -9
- package/dist/cli/programmatic.d.ts +0 -25
- package/dist/cli/programmatic.d.ts.map +0 -1
- package/dist/cli/programmatic.js +0 -48
- package/dist/cli/programmatic.js.map +0 -1
- package/dist/host/bun.d.ts +0 -9
- package/dist/host/bun.d.ts.map +0 -1
- package/dist/host/bun.js +0 -156
- package/dist/host/bun.js.map +0 -1
package/dist/targets/homebrew.js
CHANGED
|
@@ -1,33 +1,22 @@
|
|
|
1
1
|
import * as Effect from "effect/Effect";
|
|
2
|
-
import { CommandSpec, executeGate, irreversibleGate, noApprovalGate, PublishCommandOperation, RenderFileOperation, ValidateCommandOperation
|
|
3
|
-
import { TargetCapabilities, targetAuthRequirement } from "../domain/target.js";
|
|
2
|
+
import { CommandSpec, executeGate, irreversibleGate, noApprovalGate, PublishCommandOperation, RenderFileOperation, ValidateCommandOperation } from "../domain/operation.js";
|
|
4
3
|
import { PlanConstructionError } from "../planner/errors.js";
|
|
5
|
-
|
|
6
|
-
const command = (
|
|
4
|
+
import { findRequiredArtifact, requireSha256FileArtifact, rejectNoDryRunInStrictMode, targetCapabilitiesFor, validationNoteOperation, validationStrategyForDryRun } from "./adapter-helpers.js";
|
|
5
|
+
const command = (executable, args) => CommandSpec.make({
|
|
7
6
|
executable,
|
|
8
7
|
args: [...args],
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
redactedEnv: includeAuth ? envNames(target) : []
|
|
8
|
+
requiredEnv: [],
|
|
9
|
+
redactedEnv: []
|
|
12
10
|
});
|
|
13
|
-
const
|
|
14
|
-
if (target.
|
|
15
|
-
return
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
const rejectUnsupportedTokenEnv = Effect.fn("rejectUnsupportedHomebrewTokenEnv")(function* (target) {
|
|
12
|
+
if (target.tokenEnv !== undefined) {
|
|
13
|
+
return yield* Effect.fail(PlanConstructionError.make({
|
|
14
|
+
targetId: target.id,
|
|
15
|
+
reason: "Homebrew tap targets currently publish with plain git push and require Git credentials to be configured outside the release plan; tokenEnv is not supported yet."
|
|
16
|
+
}));
|
|
19
17
|
}
|
|
20
|
-
return "skipped";
|
|
21
|
-
};
|
|
22
|
-
export const homebrewTargetCapabilities = (target) => TargetCapabilities.make({
|
|
23
|
-
targetId: target.id,
|
|
24
|
-
targetTag: target._tag,
|
|
25
|
-
authRequirement: targetAuthRequirement(target),
|
|
26
|
-
dryRunSupport: target.dryRunSupport,
|
|
27
|
-
mutability: target.mutability,
|
|
28
|
-
recovery: target.recovery,
|
|
29
|
-
validationStrategy: validationStrategy(target)
|
|
30
18
|
});
|
|
19
|
+
export const homebrewTargetCapabilities = (target) => targetCapabilitiesFor(target, validationStrategyForDryRun(target.dryRunSupport));
|
|
31
20
|
const pathBaseName = (path) => {
|
|
32
21
|
const parts = path.replaceAll("\\", "/").split("/");
|
|
33
22
|
return parts[parts.length - 1] ?? path;
|
|
@@ -39,36 +28,23 @@ const formulaClassName = (formulaName) => {
|
|
|
39
28
|
return className.length === 0 ? "GeneratedFormula" : className;
|
|
40
29
|
};
|
|
41
30
|
const renderFormula = (target, model) => Effect.gen(function* () {
|
|
42
|
-
const artifact = model.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
if (artifact.format === "directory") {
|
|
50
|
-
return yield* Effect.fail(PlanConstructionError.make({
|
|
51
|
-
targetId: target.id,
|
|
52
|
-
reason: "Homebrew formula artifacts must be file-like, not directories."
|
|
53
|
-
}));
|
|
54
|
-
}
|
|
55
|
-
if (artifact.checksum === undefined || artifact.checksum.algorithm !== "sha256") {
|
|
56
|
-
return yield* Effect.fail(PlanConstructionError.make({
|
|
57
|
-
targetId: target.id,
|
|
58
|
-
reason: "Homebrew formula rendering requires a sha256 artifact checksum."
|
|
59
|
-
}));
|
|
60
|
-
}
|
|
31
|
+
const artifact = yield* findRequiredArtifact(model, target.id, target.artifactId, `Homebrew target references missing artifact ${target.artifactId}.`);
|
|
32
|
+
const validated = yield* requireSha256FileArtifact(artifact, {
|
|
33
|
+
targetId: target.id,
|
|
34
|
+
directoryReason: "Homebrew formula artifacts must be file-like, not directories.",
|
|
35
|
+
checksumReason: "Homebrew formula rendering requires a sha256 artifact checksum."
|
|
36
|
+
});
|
|
61
37
|
const installLines = target.installPath === undefined
|
|
62
38
|
? [" prefix.install Dir[\"*\"]"]
|
|
63
39
|
: [` bin.install ${rubyString(target.installPath)} => ${rubyString(target.formulaName)}`];
|
|
64
40
|
const homepage = target.homepage ?? `https://github.com/${target.repository}`;
|
|
65
|
-
const url = target.url ?? artifact.path;
|
|
41
|
+
const url = target.url ?? validated.artifact.path;
|
|
66
42
|
return [
|
|
67
43
|
`class ${formulaClassName(target.formulaName)} < Formula`,
|
|
68
44
|
` desc ${rubyString(`${model.identity.name} ${model.identity.version} release artifact`)}`,
|
|
69
45
|
` homepage ${rubyString(homepage)}`,
|
|
70
46
|
` url ${rubyString(url)}`,
|
|
71
|
-
` sha256 ${rubyString(
|
|
47
|
+
` sha256 ${rubyString(validated.checksum.value)}`,
|
|
72
48
|
` version ${rubyString(model.identity.version)}`,
|
|
73
49
|
"",
|
|
74
50
|
" def install",
|
|
@@ -78,36 +54,30 @@ const renderFormula = (target, model) => Effect.gen(function* () {
|
|
|
78
54
|
""
|
|
79
55
|
].join("\n");
|
|
80
56
|
});
|
|
81
|
-
const dryRunOperation = (target) =>
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
risk: "read-only",
|
|
87
|
-
gate: noApprovalGate("brew audit validates the generated formula without publishing."),
|
|
88
|
-
command: command(target, "brew", ["audit", "--strict", "--formula", target.formulaPath], false)
|
|
89
|
-
})
|
|
90
|
-
: ValidationNoteOperation.make({
|
|
91
|
-
id: `${target.id}:brew-audit`,
|
|
92
|
-
targetId: target.id,
|
|
93
|
-
description: target.dryRunSupport === "simulated"
|
|
94
|
-
? "Record simulated Homebrew formula validation."
|
|
95
|
-
: "Record skipped Homebrew formula validation.",
|
|
96
|
-
risk: "read-only",
|
|
97
|
-
gate: noApprovalGate("Validation notes do not modify local or remote state."),
|
|
98
|
-
message: target.dryRunSupport === "simulated"
|
|
99
|
-
? "Homebrew formula validation is simulated by the deterministic release plan."
|
|
100
|
-
: "Homebrew formula validation was skipped because this target declares no dry-run support.",
|
|
101
|
-
skipped: target.dryRunSupport === "none",
|
|
102
|
-
severity: target.dryRunSupport === "none" ? "warning" : "info"
|
|
103
|
-
});
|
|
104
|
-
export const planHomebrewOperations = Effect.fn("planHomebrewOperations")(function* (target, model) {
|
|
105
|
-
if (model.strict && target.dryRunSupport === "none") {
|
|
106
|
-
return yield* Effect.fail(PlanConstructionError.make({
|
|
57
|
+
const dryRunOperation = (target) => {
|
|
58
|
+
const dryRunSupport = target.dryRunSupport;
|
|
59
|
+
return dryRunSupport === "native"
|
|
60
|
+
? ValidateCommandOperation.make({
|
|
61
|
+
id: `${target.id}:brew-audit`,
|
|
107
62
|
targetId: target.id,
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
63
|
+
description: "Validate generated Homebrew formula with brew audit.",
|
|
64
|
+
risk: "read-only",
|
|
65
|
+
gate: noApprovalGate("brew audit validates the generated formula without publishing."),
|
|
66
|
+
command: command("brew", ["audit", "--strict", "--formula", target.formulaPath])
|
|
67
|
+
})
|
|
68
|
+
: validationNoteOperation({
|
|
69
|
+
id: `${target.id}:brew-audit`,
|
|
70
|
+
targetId: target.id,
|
|
71
|
+
dryRunSupport,
|
|
72
|
+
simulatedDescription: "Record simulated Homebrew formula validation.",
|
|
73
|
+
skippedDescription: "Record skipped Homebrew formula validation.",
|
|
74
|
+
simulatedMessage: "Homebrew formula validation is simulated by the deterministic release plan.",
|
|
75
|
+
skippedMessage: "Homebrew formula validation was skipped because this target declares no dry-run support."
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
export const planHomebrewOperations = Effect.fn("planHomebrewOperations")(function* (target, model) {
|
|
79
|
+
yield* rejectUnsupportedTokenEnv(target);
|
|
80
|
+
yield* rejectNoDryRunInStrictMode(target, model, "Homebrew tap target declares no dry-run support in strict mode.");
|
|
111
81
|
const formula = yield* renderFormula(target, model);
|
|
112
82
|
const publishRisk = target.mutability === "immutable" ? "irreversible" : "externally-visible";
|
|
113
83
|
const publishGate = publishRisk === "irreversible"
|
|
@@ -132,7 +102,7 @@ export const planHomebrewOperations = Effect.fn("planHomebrewOperations")(functi
|
|
|
132
102
|
description: "Check Homebrew CLI availability.",
|
|
133
103
|
risk: "read-only",
|
|
134
104
|
gate: noApprovalGate("CLI availability validation is read-only."),
|
|
135
|
-
command: command(
|
|
105
|
+
command: command("brew", ["--version"])
|
|
136
106
|
}));
|
|
137
107
|
}
|
|
138
108
|
operations.push(dryRunOperation(target), PublishCommandOperation.make({
|
|
@@ -141,7 +111,7 @@ export const planHomebrewOperations = Effect.fn("planHomebrewOperations")(functi
|
|
|
141
111
|
description: `Push Homebrew tap update for ${model.identity.name}@${model.identity.version}.`,
|
|
142
112
|
risk: publishRisk,
|
|
143
113
|
gate: publishGate,
|
|
144
|
-
command: command(
|
|
114
|
+
command: command("git", ["-C", tapDirectory, "push"])
|
|
145
115
|
}));
|
|
146
116
|
return operations;
|
|
147
117
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"homebrew.js","sourceRoot":"","sources":["../../src/targets/homebrew.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EACL,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,cAAc,EAEd,uBAAuB,EACvB,mBAAmB,EACnB,wBAAwB,
|
|
1
|
+
{"version":3,"file":"homebrew.js","sourceRoot":"","sources":["../../src/targets/homebrew.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/targets/live.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/targets/live.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAOrC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAG9C,mBAAmB,6BAA6B,CAAA;AAmChD,eAAO,MAAM,uBAAuB,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc,CAG9D,CAAA"}
|
package/dist/targets/live.js
CHANGED
|
@@ -3,7 +3,9 @@ import * as Layer from "effect/Layer";
|
|
|
3
3
|
import { GitHubAdapter } from "./github.js";
|
|
4
4
|
import { HomebrewAdapter } from "./homebrew.js";
|
|
5
5
|
import { NpmAdapter } from "./npm.js";
|
|
6
|
+
import { PyPiAdapter } from "./pypi.js";
|
|
6
7
|
import { TargetRegistry } from "./registry.js";
|
|
8
|
+
import { ScoopAdapter } from "./scoop.js";
|
|
7
9
|
const planLiveTargetOperations = Effect.fn("planLiveTargetOperations")(function* (target, model) {
|
|
8
10
|
switch (target._tag) {
|
|
9
11
|
case "NpmRegistryTarget":
|
|
@@ -12,6 +14,10 @@ const planLiveTargetOperations = Effect.fn("planLiveTargetOperations")(function*
|
|
|
12
14
|
return yield* GitHubAdapter.planOperations(target, model);
|
|
13
15
|
case "HomebrewTapTarget":
|
|
14
16
|
return yield* HomebrewAdapter.planOperations(target, model);
|
|
17
|
+
case "PyPiRegistryTarget":
|
|
18
|
+
return yield* PyPiAdapter.planOperations(target, model);
|
|
19
|
+
case "ScoopBucketTarget":
|
|
20
|
+
return yield* ScoopAdapter.planOperations(target, model);
|
|
15
21
|
}
|
|
16
22
|
});
|
|
17
23
|
const liveTargetCapabilities = (target) => {
|
|
@@ -22,6 +28,10 @@ const liveTargetCapabilities = (target) => {
|
|
|
22
28
|
return GitHubAdapter.capabilities(target);
|
|
23
29
|
case "HomebrewTapTarget":
|
|
24
30
|
return HomebrewAdapter.capabilities(target);
|
|
31
|
+
case "PyPiRegistryTarget":
|
|
32
|
+
return PyPiAdapter.capabilities(target);
|
|
33
|
+
case "ScoopBucketTarget":
|
|
34
|
+
return ScoopAdapter.capabilities(target);
|
|
25
35
|
}
|
|
26
36
|
};
|
|
27
37
|
export const LiveTargetRegistryLayer = Layer.succeed(TargetRegistry)({
|
package/dist/targets/live.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/targets/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAGrC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/targets/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAGrC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAIzC,MAAM,wBAAwB,GAAG,MAAM,CAAC,EAAE,CAAC,0BAA0B,CAAC,CAAC,QAAQ,CAAC,EAC9E,MAAoB,EACpB,KAAmB;IAEnB,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,mBAAmB;YACtB,OAAO,KAAK,CAAC,CAAC,UAAU,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACxD,KAAK,qBAAqB;YACxB,OAAO,KAAK,CAAC,CAAC,aAAa,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QAC3D,KAAK,mBAAmB;YACtB,OAAO,KAAK,CAAC,CAAC,eAAe,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QAC7D,KAAK,oBAAoB;YACvB,OAAO,KAAK,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACzD,KAAK,mBAAmB;YACtB,OAAO,KAAK,CAAC,CAAC,YAAY,CAAC,cAAc,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAC5D,CAAC;AACH,CAAC,CAAC,CAAA;AAEF,MAAM,sBAAsB,GAAG,CAAC,MAAoB,EAAE,EAAE;IACtD,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,mBAAmB;YACtB,OAAO,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;QACxC,KAAK,qBAAqB;YACxB,OAAO,aAAa,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;QAC3C,KAAK,mBAAmB;YACtB,OAAO,eAAe,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;QAC7C,KAAK,oBAAoB;YACvB,OAAO,WAAW,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;QACzC,KAAK,mBAAmB;YACtB,OAAO,YAAY,CAAC,YAAY,CAAC,MAAM,CAAC,CAAA;IAC5C,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAgC,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;IAChG,kBAAkB,EAAE,sBAAsB;IAC1C,oBAAoB,EAAE,wBAAwB;CAC/C,CAAC,CAAA"}
|
package/dist/targets/npm.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import * as Effect from "effect/Effect";
|
|
2
|
-
import { PublishCommandOperation, ValidateCommandOperation,
|
|
2
|
+
import { PublishCommandOperation, ValidateCommandOperation, VerifyRemoteOperation } from "../domain/operation.js";
|
|
3
3
|
import { ReleaseModel } from "../domain/release.js";
|
|
4
4
|
import { NpmRegistryTarget, TargetCapabilities } from "../domain/target.js";
|
|
5
|
-
import { PlanConstructionError } from "../planner/errors.js";
|
|
6
5
|
import { NpmTargetAdapter } from "./adapter.js";
|
|
7
6
|
export type * from "../types/effect-internal.js";
|
|
8
7
|
export declare const npmTargetCapabilities: (target: NpmRegistryTarget) => TargetCapabilities;
|
|
9
|
-
export declare const planNpmOperations: (target: NpmRegistryTarget, model: ReleaseModel) => Effect.Effect<(import("../domain/operation.js").RenderFileOperation | ValidateCommandOperation | ValidationNoteOperation | PublishCommandOperation | import("../domain/operation.js").
|
|
8
|
+
export declare const planNpmOperations: (target: NpmRegistryTarget, model: ReleaseModel) => Effect.Effect<(import("../domain/operation.js").RenderFileOperation | ValidateCommandOperation | import("../domain/operation.js").ValidationNoteOperation | PublishCommandOperation | VerifyRemoteOperation | import("../domain/operation.js").VerifyHttpOperation)[], import("../planner/errors.js").PlanConstructionError, never>;
|
|
10
9
|
export declare const NpmAdapter: NpmTargetAdapter;
|
|
11
10
|
//# sourceMappingURL=npm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"npm.d.ts","sourceRoot":"","sources":["../../src/targets/npm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAKL,uBAAuB,EACvB,wBAAwB,EACxB,
|
|
1
|
+
{"version":3,"file":"npm.d.ts","sourceRoot":"","sources":["../../src/targets/npm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAKL,uBAAuB,EACvB,wBAAwB,EACxB,qBAAqB,EACtB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EACL,iBAAiB,EAEjB,kBAAkB,EAEnB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAQ/C,mBAAmB,6BAA6B,CAAA;AA4ChD,eAAO,MAAM,qBAAqB,GAAI,QAAQ,iBAAiB,KAAG,kBAejE,CAAA;AAmED,eAAO,MAAM,iBAAiB,yXAyC5B,CAAA;AAEF,eAAO,MAAM,UAAU,EAAE,gBAIxB,CAAA"}
|
package/dist/targets/npm.js
CHANGED
|
@@ -1,56 +1,94 @@
|
|
|
1
1
|
import * as Effect from "effect/Effect";
|
|
2
|
-
import { CommandSpec, irreversibleGate, noApprovalGate, PublishCommandOperation, ValidateCommandOperation,
|
|
3
|
-
import { TargetCapabilities,
|
|
4
|
-
import {
|
|
5
|
-
const
|
|
2
|
+
import { CommandSpec, irreversibleGate, noApprovalGate, PublishCommandOperation, ValidateCommandOperation, VerifyRemoteOperation } from "../domain/operation.js";
|
|
3
|
+
import { TargetAuthSetup, TargetCapabilities, TargetRequiredPermission } from "../domain/target.js";
|
|
4
|
+
import { rejectNoDryRunInStrictMode, targetCapabilitiesFor, validationNoteOperation, validationStrategyForDryRun } from "./adapter-helpers.js";
|
|
5
|
+
const isTrustedPublishing = (target) => target.trustedPublishing !== undefined;
|
|
6
|
+
const envNames = (target) => isTrustedPublishing(target) || target.tokenEnv === undefined ? [] : [target.tokenEnv];
|
|
7
|
+
const trustedPublishingRequiredEnvNames = [
|
|
8
|
+
"ACTIONS_ID_TOKEN_REQUEST_URL",
|
|
9
|
+
"ACTIONS_ID_TOKEN_REQUEST_TOKEN"
|
|
10
|
+
];
|
|
11
|
+
const requiredAuthEnvNames = (target) => isTrustedPublishing(target) ? trustedPublishingRequiredEnvNames : envNames(target);
|
|
12
|
+
const redactedAuthEnvNames = (target) => isTrustedPublishing(target) ? trustedPublishingRequiredEnvNames : envNames(target);
|
|
6
13
|
const npmCommand = (target, args, cwd, includeAuth) => CommandSpec.make({
|
|
7
14
|
executable: "npm",
|
|
8
15
|
args: [...args],
|
|
9
16
|
...(cwd === undefined ? {} : { cwd }),
|
|
10
|
-
requiredEnv: includeAuth ?
|
|
11
|
-
redactedEnv: includeAuth ?
|
|
17
|
+
requiredEnv: includeAuth ? requiredAuthEnvNames(target) : [],
|
|
18
|
+
redactedEnv: includeAuth ? redactedAuthEnvNames(target) : []
|
|
12
19
|
});
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
const trustedPublishingAuthSetup = (workflow) => TargetAuthSetup.make({
|
|
21
|
+
runsIn: "ci",
|
|
22
|
+
provider: "github-actions",
|
|
23
|
+
workflow,
|
|
24
|
+
requiredPermissions: [
|
|
25
|
+
TargetRequiredPermission.make({ name: "id-token", value: "write" })
|
|
26
|
+
],
|
|
27
|
+
prerequisites: ["npm-package-exists"]
|
|
28
|
+
});
|
|
29
|
+
export const npmTargetCapabilities = (target) => {
|
|
30
|
+
const trustedPublishing = target.trustedPublishing;
|
|
31
|
+
if (trustedPublishing === undefined) {
|
|
32
|
+
return targetCapabilitiesFor(target, validationStrategyForDryRun(target.dryRunSupport));
|
|
19
33
|
}
|
|
20
|
-
return
|
|
34
|
+
return TargetCapabilities.make({
|
|
35
|
+
targetId: target.id,
|
|
36
|
+
targetTag: target._tag,
|
|
37
|
+
authRequirement: "trusted-publishing",
|
|
38
|
+
dryRunSupport: target.dryRunSupport,
|
|
39
|
+
mutability: target.mutability,
|
|
40
|
+
recovery: target.recovery,
|
|
41
|
+
validationStrategy: validationStrategyForDryRun(target.dryRunSupport),
|
|
42
|
+
authSetup: trustedPublishingAuthSetup(trustedPublishing.workflow)
|
|
43
|
+
});
|
|
21
44
|
};
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
45
|
+
const npmDryRunOperation = (target) => {
|
|
46
|
+
const dryRunSupport = target.dryRunSupport;
|
|
47
|
+
return dryRunSupport === "native"
|
|
48
|
+
? ValidateCommandOperation.make({
|
|
49
|
+
id: `${target.id}:npm-pack-dry-run`,
|
|
50
|
+
targetId: target.id,
|
|
51
|
+
description: "Validate npm package contents with npm pack dry-run.",
|
|
52
|
+
risk: "read-only",
|
|
53
|
+
gate: noApprovalGate("npm pack --dry-run validates package contents without publishing."),
|
|
54
|
+
command: npmCommand(target, ["pack", "--dry-run", "--json", target.packagePath], undefined, false)
|
|
55
|
+
})
|
|
56
|
+
: validationNoteOperation({
|
|
57
|
+
id: `${target.id}:npm-pack-dry-run`,
|
|
58
|
+
targetId: target.id,
|
|
59
|
+
dryRunSupport,
|
|
60
|
+
simulatedDescription: "Record simulated npm dry-run validation.",
|
|
61
|
+
skippedDescription: "Record skipped npm dry-run validation.",
|
|
62
|
+
simulatedMessage: "npm dry-run validation is marked as simulated by target configuration; no npm pack --dry-run command was planned.",
|
|
63
|
+
skippedMessage: "npm dry-run validation was skipped because this target declares no dry-run support."
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
const npmAuthOperation = (target) => target.trustedPublishing !== undefined
|
|
67
|
+
? validationNoteOperation({
|
|
68
|
+
id: `${target.id}:npm-trusted-publishing-auth`,
|
|
34
69
|
targetId: target.id,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
70
|
+
dryRunSupport: "simulated",
|
|
71
|
+
simulatedDescription: "Record npm trusted publishing authentication mode.",
|
|
72
|
+
skippedDescription: "Record skipped npm trusted publishing authentication mode.",
|
|
73
|
+
simulatedMessage: `NPM trusted publishing authenticates during npm publish with CI OIDC; npm whoami does not validate this mode. This target expects provider ${target.trustedPublishing.provider}, workflow ${target.trustedPublishing.workflow}, GitHub Actions permission id-token: write, and package ${target.packageName} to already exist on the registry.`,
|
|
74
|
+
skippedMessage: "NPM trusted publishing authentication validation was skipped."
|
|
39
75
|
})
|
|
40
|
-
:
|
|
41
|
-
id: `${target.id}:npm-
|
|
76
|
+
: ValidateCommandOperation.make({
|
|
77
|
+
id: `${target.id}:npm-whoami`,
|
|
42
78
|
targetId: target.id,
|
|
43
|
-
description:
|
|
44
|
-
? "Record simulated npm dry-run validation."
|
|
45
|
-
: "Record skipped npm dry-run validation.",
|
|
79
|
+
description: "Validate npm CLI authentication.",
|
|
46
80
|
risk: "read-only",
|
|
47
|
-
gate: noApprovalGate("
|
|
48
|
-
|
|
49
|
-
? "npm dry-run validation is marked as simulated by target configuration; no npm pack --dry-run command was planned."
|
|
50
|
-
: "npm dry-run validation was skipped because this target declares no dry-run support.",
|
|
51
|
-
skipped: target.dryRunSupport === "none",
|
|
52
|
-
severity: "warning"
|
|
81
|
+
gate: noApprovalGate("npm whoami checks CLI authentication without publishing."),
|
|
82
|
+
command: npmCommand(target, ["whoami", "--registry", target.registry], undefined, true)
|
|
53
83
|
});
|
|
84
|
+
const npmPackageExistsOperation = (target) => ValidateCommandOperation.make({
|
|
85
|
+
id: `${target.id}:npm-package-exists`,
|
|
86
|
+
targetId: target.id,
|
|
87
|
+
description: "Verify npm package exists before trusted publishing.",
|
|
88
|
+
risk: "read-only",
|
|
89
|
+
gate: noApprovalGate("npm view checks package metadata without publishing."),
|
|
90
|
+
command: npmCommand(target, ["view", target.packageName, "name", "--registry", target.registry], undefined, false)
|
|
91
|
+
});
|
|
54
92
|
const npmPublishArgs = (target) => {
|
|
55
93
|
const args = ["publish", target.packagePath, "--registry", target.registry];
|
|
56
94
|
if (target.access !== undefined) {
|
|
@@ -62,12 +100,7 @@ const npmPublishArgs = (target) => {
|
|
|
62
100
|
return args;
|
|
63
101
|
};
|
|
64
102
|
export const planNpmOperations = Effect.fn("planNpmOperations")(function* (target, model) {
|
|
65
|
-
|
|
66
|
-
return yield* Effect.fail(PlanConstructionError.make({
|
|
67
|
-
targetId: target.id,
|
|
68
|
-
reason: "npm target declares no dry-run support in strict mode."
|
|
69
|
-
}));
|
|
70
|
-
}
|
|
103
|
+
yield* rejectNoDryRunInStrictMode(target, model, "npm target declares no dry-run support in strict mode.");
|
|
71
104
|
const operations = [
|
|
72
105
|
ValidateCommandOperation.make({
|
|
73
106
|
id: `${target.id}:npm-version`,
|
|
@@ -77,22 +110,24 @@ export const planNpmOperations = Effect.fn("planNpmOperations")(function* (targe
|
|
|
77
110
|
gate: noApprovalGate("CLI availability validation is read-only."),
|
|
78
111
|
command: npmCommand(target, ["--version"], undefined, false)
|
|
79
112
|
}),
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
targetId: target.id,
|
|
83
|
-
description: "Validate npm CLI authentication.",
|
|
84
|
-
risk: "read-only",
|
|
85
|
-
gate: noApprovalGate("npm whoami checks CLI authentication without publishing."),
|
|
86
|
-
command: npmCommand(target, ["whoami", "--registry", target.registry], undefined, true)
|
|
87
|
-
}),
|
|
113
|
+
npmAuthOperation(target),
|
|
114
|
+
...(target.trustedPublishing?.verifyPackageExists === true ? [npmPackageExistsOperation(target)] : []),
|
|
88
115
|
npmDryRunOperation(target),
|
|
89
116
|
PublishCommandOperation.make({
|
|
90
117
|
id: `${target.id}:npm-publish`,
|
|
91
118
|
targetId: target.id,
|
|
92
|
-
description: `Publish ${
|
|
119
|
+
description: `Publish ${target.packageName}@${model.identity.version} to npm.`,
|
|
93
120
|
risk: "irreversible",
|
|
94
121
|
gate: irreversibleGate("npm package versions are immutable once published."),
|
|
95
122
|
command: npmCommand(target, npmPublishArgs(target), undefined, true)
|
|
123
|
+
}),
|
|
124
|
+
VerifyRemoteOperation.make({
|
|
125
|
+
id: `${target.id}:npm-version-verify`,
|
|
126
|
+
targetId: target.id,
|
|
127
|
+
description: `Verify ${target.packageName}@${model.identity.version} exists on npm.`,
|
|
128
|
+
risk: "read-only",
|
|
129
|
+
gate: noApprovalGate("npm view verifies published package metadata without publishing."),
|
|
130
|
+
command: npmCommand(target, ["view", `${target.packageName}@${model.identity.version}`, "version", "--registry", target.registry], undefined, false)
|
|
96
131
|
})
|
|
97
132
|
];
|
|
98
133
|
return operations;
|
package/dist/targets/npm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"npm.js","sourceRoot":"","sources":["../../src/targets/npm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,cAAc,EAEd,uBAAuB,EACvB,wBAAwB,EACxB,
|
|
1
|
+
{"version":3,"file":"npm.js","sourceRoot":"","sources":["../../src/targets/npm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import { PublishCommandOperation, ValidateCommandOperation } from "../domain/operation.js";
|
|
3
|
+
import { ReleaseModel } from "../domain/release.js";
|
|
4
|
+
import { PyPiRegistryTarget, TargetCapabilities } from "../domain/target.js";
|
|
5
|
+
import { PlanConstructionError } from "../planner/errors.js";
|
|
6
|
+
import { PyPiTargetAdapter } from "./adapter.js";
|
|
7
|
+
export type * from "../types/effect-internal.js";
|
|
8
|
+
export declare const pypiTargetCapabilities: (target: PyPiRegistryTarget) => TargetCapabilities;
|
|
9
|
+
export declare const planPyPiOperations: (target: PyPiRegistryTarget, model: ReleaseModel) => Effect.Effect<(import("../domain/operation.js").RenderFileOperation | ValidateCommandOperation | import("../domain/operation.js").ValidationNoteOperation | PublishCommandOperation | import("../domain/operation.js").VerifyRemoteOperation | import("../domain/operation.js").VerifyHttpOperation)[], PlanConstructionError, never>;
|
|
10
|
+
export declare const PyPiAdapter: PyPiTargetAdapter;
|
|
11
|
+
//# sourceMappingURL=pypi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pypi.d.ts","sourceRoot":"","sources":["../../src/targets/pypi.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAKL,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAA;AAQhD,mBAAmB,6BAA6B,CAAA;AA2BhD,eAAO,MAAM,sBAAsB,GAAI,QAAQ,kBAAkB,KAAG,kBACc,CAAA;AAiElF,eAAO,MAAM,kBAAkB,4XAsD7B,CAAA;AAEF,eAAO,MAAM,WAAW,EAAE,iBAIzB,CAAA"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import { CommandSpec, irreversibleGate, noApprovalGate, PublishCommandOperation, ValidateCommandOperation } from "../domain/operation.js";
|
|
3
|
+
import { PlanConstructionError } from "../planner/errors.js";
|
|
4
|
+
import { rejectNoDryRunInStrictMode, targetCapabilitiesFor, validationNoteOperation, validationStrategyForDryRun } from "./adapter-helpers.js";
|
|
5
|
+
const twineUsernameEnv = "TWINE_USERNAME";
|
|
6
|
+
const twinePasswordEnv = "TWINE_PASSWORD";
|
|
7
|
+
const envNames = (target) => target.usernameEnv === undefined || target.passwordEnv === undefined ? [] : [target.usernameEnv, target.passwordEnv];
|
|
8
|
+
const pythonCommand = (target, args, includeAuth) => CommandSpec.make({
|
|
9
|
+
executable: "python",
|
|
10
|
+
args: [...args],
|
|
11
|
+
requiredEnv: includeAuth ? envNames(target) : [],
|
|
12
|
+
redactedEnv: includeAuth ? envNames(target) : []
|
|
13
|
+
});
|
|
14
|
+
const twineCommand = (target, args, includeAuth) => pythonCommand(target, ["-m", "twine", ...args], includeAuth);
|
|
15
|
+
export const pypiTargetCapabilities = (target) => targetCapabilitiesFor(target, validationStrategyForDryRun(target.dryRunSupport));
|
|
16
|
+
const targetArtifacts = (target, model) => model.artifacts.filter((artifact) => artifact.consumers.includes(target.id));
|
|
17
|
+
const pypiDryRunOperation = (target, artifactPaths) => {
|
|
18
|
+
const dryRunSupport = target.dryRunSupport;
|
|
19
|
+
return dryRunSupport === "native"
|
|
20
|
+
? ValidateCommandOperation.make({
|
|
21
|
+
id: `${target.id}:twine-check`,
|
|
22
|
+
targetId: target.id,
|
|
23
|
+
description: "Validate Python distribution metadata with twine check.",
|
|
24
|
+
risk: "read-only",
|
|
25
|
+
gate: noApprovalGate("twine check validates built distributions without publishing."),
|
|
26
|
+
command: twineCommand(target, ["check", ...artifactPaths], false)
|
|
27
|
+
})
|
|
28
|
+
: validationNoteOperation({
|
|
29
|
+
id: `${target.id}:twine-check`,
|
|
30
|
+
targetId: target.id,
|
|
31
|
+
dryRunSupport,
|
|
32
|
+
simulatedDescription: "Record simulated PyPI distribution validation.",
|
|
33
|
+
skippedDescription: "Record skipped PyPI distribution validation.",
|
|
34
|
+
simulatedMessage: "PyPI distribution validation is simulated by the deterministic release plan; no twine check command was planned.",
|
|
35
|
+
skippedMessage: "PyPI distribution validation was skipped because this target declares no dry-run support."
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
const pypiPublishArgs = (target, artifactPaths) => [
|
|
39
|
+
"upload",
|
|
40
|
+
"--repository-url",
|
|
41
|
+
target.repositoryUrl,
|
|
42
|
+
...artifactPaths
|
|
43
|
+
];
|
|
44
|
+
const validateAuthConfig = (target) => {
|
|
45
|
+
const hasUsername = target.usernameEnv !== undefined;
|
|
46
|
+
const hasPassword = target.passwordEnv !== undefined;
|
|
47
|
+
if (!hasUsername && !hasPassword) {
|
|
48
|
+
return Effect.void;
|
|
49
|
+
}
|
|
50
|
+
if (hasUsername !== hasPassword) {
|
|
51
|
+
return Effect.fail(PlanConstructionError.make({
|
|
52
|
+
targetId: target.id,
|
|
53
|
+
reason: "PyPI token auth must configure both usernameEnv and passwordEnv, or neither."
|
|
54
|
+
}));
|
|
55
|
+
}
|
|
56
|
+
if (target.usernameEnv === twineUsernameEnv && target.passwordEnv === twinePasswordEnv) {
|
|
57
|
+
return Effect.void;
|
|
58
|
+
}
|
|
59
|
+
return Effect.fail(PlanConstructionError.make({
|
|
60
|
+
targetId: target.id,
|
|
61
|
+
reason: "PyPI token auth only supports usernameEnv TWINE_USERNAME and passwordEnv TWINE_PASSWORD because Twine reads those environment variables directly; this adapter keeps secrets out of argv and does not remap env names."
|
|
62
|
+
}));
|
|
63
|
+
};
|
|
64
|
+
export const planPyPiOperations = Effect.fn("planPyPiOperations")(function* (target, model) {
|
|
65
|
+
yield* validateAuthConfig(target);
|
|
66
|
+
yield* rejectNoDryRunInStrictMode(target, model, "PyPI target declares no dry-run support in strict mode.");
|
|
67
|
+
const artifacts = targetArtifacts(target, model);
|
|
68
|
+
if (artifacts.length === 0) {
|
|
69
|
+
return yield* Effect.fail(PlanConstructionError.make({
|
|
70
|
+
targetId: target.id,
|
|
71
|
+
reason: "PyPI target must have at least one artifact consumer."
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
const directoryArtifact = artifacts.find((artifact) => artifact.format === "directory");
|
|
75
|
+
if (directoryArtifact !== undefined) {
|
|
76
|
+
return yield* Effect.fail(PlanConstructionError.make({
|
|
77
|
+
targetId: target.id,
|
|
78
|
+
reason: `PyPI target artifact ${directoryArtifact.id} must be a built distribution file, not a directory.`
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
const artifactPaths = artifacts.map((artifact) => artifact.path);
|
|
82
|
+
return [
|
|
83
|
+
ValidateCommandOperation.make({
|
|
84
|
+
id: `${target.id}:python-version`,
|
|
85
|
+
targetId: target.id,
|
|
86
|
+
description: "Check Python CLI availability.",
|
|
87
|
+
risk: "read-only",
|
|
88
|
+
gate: noApprovalGate("CLI availability validation is read-only."),
|
|
89
|
+
command: pythonCommand(target, ["--version"], false)
|
|
90
|
+
}),
|
|
91
|
+
ValidateCommandOperation.make({
|
|
92
|
+
id: `${target.id}:twine-version`,
|
|
93
|
+
targetId: target.id,
|
|
94
|
+
description: "Check Twine CLI availability.",
|
|
95
|
+
risk: "read-only",
|
|
96
|
+
gate: noApprovalGate("Twine availability validation is read-only."),
|
|
97
|
+
command: twineCommand(target, ["--version"], false)
|
|
98
|
+
}),
|
|
99
|
+
pypiDryRunOperation(target, artifactPaths),
|
|
100
|
+
PublishCommandOperation.make({
|
|
101
|
+
id: `${target.id}:twine-upload`,
|
|
102
|
+
targetId: target.id,
|
|
103
|
+
description: `Publish ${model.identity.name}@${model.identity.version} to PyPI-compatible registry.`,
|
|
104
|
+
risk: "irreversible",
|
|
105
|
+
gate: irreversibleGate("PyPI package versions are immutable once published."),
|
|
106
|
+
command: twineCommand(target, pypiPublishArgs(target, artifactPaths), true)
|
|
107
|
+
})
|
|
108
|
+
];
|
|
109
|
+
});
|
|
110
|
+
export const PyPiAdapter = {
|
|
111
|
+
targetTag: "PyPiRegistryTarget",
|
|
112
|
+
capabilities: pypiTargetCapabilities,
|
|
113
|
+
planOperations: planPyPiOperations
|
|
114
|
+
};
|
|
115
|
+
//# sourceMappingURL=pypi.js.map
|