putitoutthere 0.1.43 → 0.1.45

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.
Files changed (82) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/MIGRATIONS.md +632 -0
  3. package/README.md +342 -94
  4. package/action.yml +5 -5
  5. package/dist/action.js +2 -2
  6. package/dist/action.js.map +1 -1
  7. package/dist/cascade.d.ts +1 -1
  8. package/dist/cascade.js +2 -2
  9. package/dist/cli.d.ts +9 -6
  10. package/dist/cli.d.ts.map +1 -1
  11. package/dist/cli.js +12 -426
  12. package/dist/cli.js.map +1 -1
  13. package/dist/config.d.ts +13 -61
  14. package/dist/config.d.ts.map +1 -1
  15. package/dist/config.js +31 -45
  16. package/dist/config.js.map +1 -1
  17. package/dist/git.js +1 -1
  18. package/dist/git.js.map +1 -1
  19. package/dist/handlers/npm-platform.d.ts.map +1 -1
  20. package/dist/handlers/npm-platform.js +5 -1
  21. package/dist/handlers/npm-platform.js.map +1 -1
  22. package/dist/handlers/pypi.d.ts.map +1 -1
  23. package/dist/handlers/pypi.js +29 -6
  24. package/dist/handlers/pypi.js.map +1 -1
  25. package/dist/plan.d.ts +0 -1
  26. package/dist/plan.d.ts.map +1 -1
  27. package/dist/plan.js +19 -18
  28. package/dist/plan.js.map +1 -1
  29. package/dist/preflight.js +1 -1
  30. package/dist/preflight.js.map +1 -1
  31. package/dist/publish.d.ts +0 -10
  32. package/dist/publish.d.ts.map +1 -1
  33. package/dist/publish.js +6 -52
  34. package/dist/publish.js.map +1 -1
  35. package/dist/types.d.ts +1 -21
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/types.js.map +1 -1
  38. package/package.json +5 -3
  39. package/dist/auth.d.ts +0 -68
  40. package/dist/auth.d.ts.map +0 -1
  41. package/dist/auth.js +0 -285
  42. package/dist/auth.js.map +0 -1
  43. package/dist/doctor.d.ts +0 -115
  44. package/dist/doctor.d.ts.map +0 -1
  45. package/dist/doctor.js +0 -292
  46. package/dist/doctor.js.map +0 -1
  47. package/dist/init.d.ts +0 -59
  48. package/dist/init.d.ts.map +0 -1
  49. package/dist/init.js +0 -181
  50. package/dist/init.js.map +0 -1
  51. package/dist/keyring.d.ts +0 -35
  52. package/dist/keyring.d.ts.map +0 -1
  53. package/dist/keyring.js +0 -88
  54. package/dist/keyring.js.map +0 -1
  55. package/dist/oidc-policy.d.ts +0 -145
  56. package/dist/oidc-policy.d.ts.map +0 -1
  57. package/dist/oidc-policy.js +0 -383
  58. package/dist/oidc-policy.js.map +0 -1
  59. package/dist/preflight-run.d.ts +0 -47
  60. package/dist/preflight-run.d.ts.map +0 -1
  61. package/dist/preflight-run.js +0 -197
  62. package/dist/preflight-run.js.map +0 -1
  63. package/dist/registries/crates-trust.d.ts +0 -69
  64. package/dist/registries/crates-trust.d.ts.map +0 -1
  65. package/dist/registries/crates-trust.js +0 -95
  66. package/dist/registries/crates-trust.js.map +0 -1
  67. package/dist/release.d.ts +0 -36
  68. package/dist/release.d.ts.map +0 -1
  69. package/dist/release.js +0 -102
  70. package/dist/release.js.map +0 -1
  71. package/dist/templates.d.ts +0 -43
  72. package/dist/templates.d.ts.map +0 -1
  73. package/dist/templates.js +0 -310
  74. package/dist/templates.js.map +0 -1
  75. package/dist/token-scope.d.ts +0 -65
  76. package/dist/token-scope.d.ts.map +0 -1
  77. package/dist/token-scope.js +0 -163
  78. package/dist/token-scope.js.map +0 -1
  79. package/dist/token.d.ts +0 -211
  80. package/dist/token.d.ts.map +0 -1
  81. package/dist/token.js +0 -719
  82. package/dist/token.js.map +0 -1
@@ -1,47 +0,0 @@
1
- /**
2
- * `putitoutthere preflight` — run every pre-publish check against every
3
- * package, without side effects.
4
- *
5
- * Lives alongside (not inside) `preflight.ts` because that module is
6
- * scoped to auth-only checks that handlers delegate to. This one is
7
- * the cross-cutting orchestrator that `doctor` and `publish` each use
8
- * pieces of.
9
- *
10
- * Issue #93. Plan: §16.4.7.
11
- *
12
- * Check catalogue:
13
- * - path: pkg.path exists on disk (resolved against opts.cwd).
14
- * - manifest: the per-kind manifest file exists under pkg.path.
15
- * - auth: OIDC or the per-kind token env var is set.
16
- * - repository: package.json has `repository` (npm --provenance requirement).
17
- * - artifact: when the package is in the cascaded plan, its artifact
18
- * dir exists.
19
- *
20
- * Default scope is "packages cascaded by the plan". `--all` widens to
21
- * every configured package (useful pre-commit or when plan can't run
22
- * in a scratch checkout).
23
- */
24
- import type { Kind } from './types.js';
25
- export interface PreflightOptions {
26
- cwd: string;
27
- configPath?: string;
28
- /** When true, widen scope from cascaded-only to every configured package. */
29
- all?: boolean;
30
- }
31
- export type CheckStatus = 'ok' | 'fail' | 'skip';
32
- export type CheckName = 'path' | 'manifest' | 'auth' | 'repository' | 'artifact';
33
- export interface PreflightCheck {
34
- package: string;
35
- kind: Kind;
36
- check: CheckName;
37
- status: CheckStatus;
38
- detail?: string;
39
- }
40
- export interface PreflightReport {
41
- ok: boolean;
42
- checks: PreflightCheck[];
43
- /** Top-level issues not scoped to a package (e.g. config parse failure). */
44
- issues: string[];
45
- }
46
- export declare function runPreflight(opts: PreflightOptions): Promise<PreflightReport>;
47
- //# sourceMappingURL=preflight-run.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"preflight-run.d.ts","sourceRoot":"","sources":["../src/preflight-run.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AASH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC;AACjD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,YAAY,GAAG,UAAU,CAAC;AAEjF,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,EAAE,SAAS,CAAC;IACjB,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,4EAA4E;IAC5E,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAgEnF"}
@@ -1,197 +0,0 @@
1
- /**
2
- * `putitoutthere preflight` — run every pre-publish check against every
3
- * package, without side effects.
4
- *
5
- * Lives alongside (not inside) `preflight.ts` because that module is
6
- * scoped to auth-only checks that handlers delegate to. This one is
7
- * the cross-cutting orchestrator that `doctor` and `publish` each use
8
- * pieces of.
9
- *
10
- * Issue #93. Plan: §16.4.7.
11
- *
12
- * Check catalogue:
13
- * - path: pkg.path exists on disk (resolved against opts.cwd).
14
- * - manifest: the per-kind manifest file exists under pkg.path.
15
- * - auth: OIDC or the per-kind token env var is set.
16
- * - repository: package.json has `repository` (npm --provenance requirement).
17
- * - artifact: when the package is in the cascaded plan, its artifact
18
- * dir exists.
19
- *
20
- * Default scope is "packages cascaded by the plan". `--all` widens to
21
- * every configured package (useful pre-commit or when plan can't run
22
- * in a scratch checkout).
23
- */
24
- import { existsSync, readFileSync } from 'node:fs';
25
- import { isAbsolute, join, resolve } from 'node:path';
26
- import { expectedLayout } from './completeness.js';
27
- import { loadConfig } from './config.js';
28
- import { plan } from './plan.js';
29
- import { checkAuth } from './preflight.js';
30
- export async function runPreflight(opts) {
31
- const issues = [];
32
- const checks = [];
33
- /* v8 ignore next -- tests always pass an explicit configPath or cwd */
34
- const cfgPath = opts.configPath ?? `${opts.cwd.replace(/\/+$/, '')}/putitoutthere.toml`;
35
- let config;
36
- try {
37
- config = loadConfig(cfgPath);
38
- /* v8 ignore start -- non-Error catch fallback path */
39
- }
40
- catch (err) {
41
- const message = err instanceof Error ? err.message : String(err);
42
- issues.push(`config: ${message}`);
43
- return { ok: false, checks, issues };
44
- }
45
- /* v8 ignore stop */
46
- // Anchor pkg.path to opts.cwd so every downstream fs op points at the
47
- // right tree (mirror src/publish.ts).
48
- for (const p of config.packages) {
49
- if (!isAbsolute(p.path))
50
- p.path = resolve(opts.cwd, p.path);
51
- }
52
- let matrix = [];
53
- try {
54
- matrix = (await plan({ cwd: opts.cwd, configPath: cfgPath }));
55
- }
56
- catch (err) {
57
- /* v8 ignore next -- non-Error catch fallback path */
58
- const message = err instanceof Error ? err.message : String(err);
59
- issues.push(`plan: cannot compute matrix (${message})`);
60
- }
61
- const cascaded = new Set(matrix.map((r) => r.name));
62
- const scope = opts.all
63
- ? config.packages
64
- : config.packages.filter((p) => cascaded.has(p.name));
65
- const auth = checkAuth(scope);
66
- for (const pkg of scope) {
67
- checks.push(pathCheck(pkg));
68
- checks.push(manifestCheck(pkg));
69
- checks.push(authCheckFor(pkg, auth));
70
- if (pkg.kind === 'npm') {
71
- checks.push(repositoryCheck(pkg));
72
- }
73
- }
74
- // Artifact check runs only against matrix rows — non-cascaded packages
75
- // have no rows, and adding a per-row check against them is misleading.
76
- const artifactsRoot = join(opts.cwd, 'artifacts');
77
- for (const row of matrix) {
78
- // Vanilla npm publishes from source; no artifact dir exists.
79
- if (row.kind === 'npm' && row.target === 'noarch')
80
- continue;
81
- // If the cascaded row's package isn't in scope (unusual but possible
82
- // with external filters), still report — artifact issues block
83
- // publish regardless of `--all`.
84
- checks.push(artifactCheck(row, artifactsRoot));
85
- }
86
- const ok = issues.length === 0 && checks.every((c) => c.status !== 'fail');
87
- return { ok, checks, issues };
88
- }
89
- /* ----------------------------- internals ----------------------------- */
90
- function pathCheck(pkg) {
91
- if (existsSync(pkg.path)) {
92
- return { package: pkg.name, kind: pkg.kind, check: 'path', status: 'ok', detail: pkg.path };
93
- }
94
- return {
95
- package: pkg.name,
96
- kind: pkg.kind,
97
- check: 'path',
98
- status: 'fail',
99
- detail: `pkg.path does not exist: ${pkg.path}`,
100
- };
101
- }
102
- function manifestFor(kind) {
103
- switch (kind) {
104
- case 'crates': return 'Cargo.toml';
105
- case 'pypi': return 'pyproject.toml';
106
- case 'npm': return 'package.json';
107
- }
108
- }
109
- function manifestCheck(pkg) {
110
- const manifest = manifestFor(pkg.kind);
111
- const full = join(pkg.path, manifest);
112
- if (existsSync(full)) {
113
- return { package: pkg.name, kind: pkg.kind, check: 'manifest', status: 'ok', detail: manifest };
114
- }
115
- return {
116
- package: pkg.name,
117
- kind: pkg.kind,
118
- check: 'manifest',
119
- status: 'fail',
120
- detail: `missing ${manifest} at ${full}`,
121
- };
122
- }
123
- function authCheckFor(pkg, auth) {
124
- const row = auth.results.find((r) => r.package === pkg.name);
125
- /* v8 ignore start -- every scoped package gets a row in checkAuth */
126
- if (row === undefined) {
127
- return { package: pkg.name, kind: pkg.kind, check: 'auth', status: 'skip', detail: 'no auth row' };
128
- }
129
- /* v8 ignore stop */
130
- if (row.via === 'missing') {
131
- return {
132
- package: pkg.name,
133
- kind: pkg.kind,
134
- check: 'auth',
135
- status: 'fail',
136
- detail: `needs ${row.acceptedEnvVars.join(' or ')} or OIDC`,
137
- };
138
- }
139
- return { package: pkg.name, kind: pkg.kind, check: 'auth', status: 'ok', detail: row.via };
140
- }
141
- function repositoryCheck(pkg) {
142
- const pkgJsonPath = join(pkg.path, 'package.json');
143
- if (!existsSync(pkgJsonPath)) {
144
- return {
145
- package: pkg.name,
146
- kind: pkg.kind,
147
- check: 'repository',
148
- status: 'skip',
149
- detail: 'no package.json',
150
- };
151
- }
152
- let parsed;
153
- try {
154
- parsed = JSON.parse(readFileSync(pkgJsonPath, 'utf8'));
155
- }
156
- catch (err) {
157
- /* v8 ignore next -- non-Error catch fallback */
158
- const message = err instanceof Error ? err.message : String(err);
159
- return {
160
- package: pkg.name,
161
- kind: pkg.kind,
162
- check: 'repository',
163
- status: 'fail',
164
- detail: `package.json parse error: ${message}`,
165
- };
166
- }
167
- if (!parsed.repository) {
168
- return {
169
- package: pkg.name,
170
- kind: pkg.kind,
171
- check: 'repository',
172
- status: 'fail',
173
- detail: '`repository` field required for `npm publish --provenance`',
174
- };
175
- }
176
- return { package: pkg.name, kind: pkg.kind, check: 'repository', status: 'ok' };
177
- }
178
- function artifactCheck(row, artifactsRoot) {
179
- const dir = join(artifactsRoot, row.artifact_name);
180
- if (existsSync(dir)) {
181
- return {
182
- package: row.name,
183
- kind: row.kind,
184
- check: 'artifact',
185
- status: 'ok',
186
- detail: row.artifact_name,
187
- };
188
- }
189
- return {
190
- package: row.name,
191
- kind: row.kind,
192
- check: 'artifact',
193
- status: 'fail',
194
- detail: `missing ${row.artifact_name}/; expected ${expectedLayout(row)}`,
195
- };
196
- }
197
- //# sourceMappingURL=preflight-run.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"preflight-run.js","sourceRoot":"","sources":["../src/preflight-run.ts"],"names":[],"mappings":"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"}
@@ -1,69 +0,0 @@
1
- /**
2
- * crates.io trusted-publishing read API.
3
- *
4
- * Issue #189. crates.io exposes `GET /api/v1/trusted_publishing/github_configs?crate=<name>`
5
- * that returns each registered GitHub trust-policy config — enough to
6
- * diff against a local `[package.trust_policy]` declaration and catch
7
- * the `release.yml → patch-release.yml` rename landmine before it
8
- * breaks a live publish.
9
- *
10
- * PyPI and npm do NOT have a usable read API from CI: PyPI has no
11
- * current-policy endpoint (only past provenance via PEP 740), and
12
- * npm's equivalent requires 2FA/OTP on every call and rejects
13
- * bypass-2FA tokens. See `docs/guide/auth.md` for the full matrix.
14
- */
15
- /** One `GitHubConfig` entry from crates.io's trust-policy API. */
16
- export interface CratesGithubConfig {
17
- id: number;
18
- repository_owner: string;
19
- repository_name: string;
20
- workflow_filename: string;
21
- environment: string | null;
22
- }
23
- export type CratesTrustFetchResult = {
24
- kind: 'ok';
25
- configs: CratesGithubConfig[];
26
- }
27
- /** Transient failure — timeout, network error, or 5xx. Neutral-skip in doctor. */
28
- | {
29
- kind: 'skip-transient';
30
- reason: string;
31
- }
32
- /** Token rejected (401). Fails the phase; user must fix the token. */
33
- | {
34
- kind: 'auth-failed';
35
- reason: string;
36
- };
37
- export interface FetchOptions {
38
- /** Override for tests; defaults to `API_BASE`. */
39
- apiBase?: string;
40
- /** Override for tests; defaults to `AbortSignal.timeout(5000)`. */
41
- signal?: AbortSignal;
42
- }
43
- /**
44
- * Fetches the crates.io trust-policy configs for a crate. Wraps the
45
- * network call in a 5s timeout; transient failures (timeout, 5xx,
46
- * network error) return `skip-transient` so `doctor` doesn't turn red
47
- * because crates.io is having a bad minute. A 401 returns
48
- * `auth-failed` — the token is the user's responsibility to fix.
49
- */
50
- export declare function fetchCratesTrustPolicy(crate: string, token: string, opts?: FetchOptions): Promise<CratesTrustFetchResult>;
51
- /** Issue emitted when a declared trust policy disagrees with crates.io. */
52
- export interface CratesTrustMismatch {
53
- crate: string;
54
- field: 'workflow_filename' | 'environment' | 'repository';
55
- declared: string;
56
- registered: string | null;
57
- }
58
- /**
59
- * Compare a `[package.trust_policy]` declaration against each registered
60
- * crates.io config for the same crate. Returns one mismatch per field
61
- * per config; empty when every field agrees across every registered
62
- * config.
63
- */
64
- export declare function diffCratesTrust(crate: string, declared: {
65
- workflow: string;
66
- environment?: string | undefined;
67
- repository?: string | undefined;
68
- }, configs: readonly CratesGithubConfig[]): CratesTrustMismatch[];
69
- //# sourceMappingURL=crates-trust.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"crates-trust.d.ts","sourceRoot":"","sources":["../../src/registries/crates-trust.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,MAAM,sBAAsB,GAC9B;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,kBAAkB,EAAE,CAAA;CAAE;AAC/C,kFAAkF;GAChF;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AAC5C,sEAAsE;GACpE;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5C,MAAM,WAAW,YAAY;IAC3B,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,YAAiB,GACtB,OAAO,CAAC,sBAAsB,CAAC,CA8BjC;AAED,2EAA2E;AAC3E,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,mBAAmB,GAAG,aAAa,GAAG,YAAY,CAAC;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,EACjG,OAAO,EAAE,SAAS,kBAAkB,EAAE,GACrC,mBAAmB,EAAE,CAgCvB"}
@@ -1,95 +0,0 @@
1
- /**
2
- * crates.io trusted-publishing read API.
3
- *
4
- * Issue #189. crates.io exposes `GET /api/v1/trusted_publishing/github_configs?crate=<name>`
5
- * that returns each registered GitHub trust-policy config — enough to
6
- * diff against a local `[package.trust_policy]` declaration and catch
7
- * the `release.yml → patch-release.yml` rename landmine before it
8
- * breaks a live publish.
9
- *
10
- * PyPI and npm do NOT have a usable read API from CI: PyPI has no
11
- * current-policy endpoint (only past provenance via PEP 740), and
12
- * npm's equivalent requires 2FA/OTP on every call and rejects
13
- * bypass-2FA tokens. See `docs/guide/auth.md` for the full matrix.
14
- */
15
- import { USER_AGENT } from '../version.js';
16
- const API_BASE = 'https://crates.io';
17
- /**
18
- * Fetches the crates.io trust-policy configs for a crate. Wraps the
19
- * network call in a 5s timeout; transient failures (timeout, 5xx,
20
- * network error) return `skip-transient` so `doctor` doesn't turn red
21
- * because crates.io is having a bad minute. A 401 returns
22
- * `auth-failed` — the token is the user's responsibility to fix.
23
- */
24
- export async function fetchCratesTrustPolicy(crate, token, opts = {}) {
25
- const base = opts.apiBase ?? API_BASE;
26
- const url = `${base}/api/v1/trusted_publishing/github_configs?crate=${encodeURIComponent(crate)}`;
27
- const signal = opts.signal ?? AbortSignal.timeout(5000);
28
- let res;
29
- try {
30
- res = await fetch(url, {
31
- method: 'GET',
32
- headers: {
33
- 'user-agent': USER_AGENT,
34
- authorization: `Bearer ${token}`,
35
- },
36
- signal,
37
- });
38
- }
39
- catch (err) {
40
- /* v8 ignore next -- fetch always throws an Error; the String(err) fallback is defensive */
41
- const message = err instanceof Error ? err.message : String(err);
42
- return { kind: 'skip-transient', reason: message };
43
- }
44
- if (res.status === 401) {
45
- return { kind: 'auth-failed', reason: 'crates.io rejected CRATES_IO_DOCTOR_TOKEN (401)' };
46
- }
47
- if (res.status >= 500) {
48
- return { kind: 'skip-transient', reason: `crates.io returned HTTP ${res.status}` };
49
- }
50
- if (res.status !== 200) {
51
- return { kind: 'skip-transient', reason: `crates.io returned unexpected HTTP ${res.status}` };
52
- }
53
- const body = (await res.json());
54
- return { kind: 'ok', configs: body.github_configs ?? [] };
55
- }
56
- /**
57
- * Compare a `[package.trust_policy]` declaration against each registered
58
- * crates.io config for the same crate. Returns one mismatch per field
59
- * per config; empty when every field agrees across every registered
60
- * config.
61
- */
62
- export function diffCratesTrust(crate, declared, configs) {
63
- const out = [];
64
- for (const cfg of configs) {
65
- if (cfg.workflow_filename !== declared.workflow) {
66
- out.push({
67
- crate,
68
- field: 'workflow_filename',
69
- declared: declared.workflow,
70
- registered: cfg.workflow_filename,
71
- });
72
- }
73
- if (declared.environment !== undefined && cfg.environment !== declared.environment) {
74
- out.push({
75
- crate,
76
- field: 'environment',
77
- declared: declared.environment,
78
- registered: cfg.environment,
79
- });
80
- }
81
- if (declared.repository !== undefined) {
82
- const registeredRepo = `${cfg.repository_owner}/${cfg.repository_name}`;
83
- if (registeredRepo !== declared.repository) {
84
- out.push({
85
- crate,
86
- field: 'repository',
87
- declared: declared.repository,
88
- registered: registeredRepo,
89
- });
90
- }
91
- }
92
- }
93
- return out;
94
- }
95
- //# sourceMappingURL=crates-trust.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"crates-trust.js","sourceRoot":"","sources":["../../src/registries/crates-trust.ts"],"names":[],"mappings":"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"}
package/dist/release.d.ts DELETED
@@ -1,36 +0,0 @@
1
- /**
2
- * GitHub Release creation.
3
- *
4
- * After a successful tag push (§13.6), create a Release on GitHub so
5
- * the new version shows up in the repo's Releases UI with body notes
6
- * generated from the commit history since the previous tag.
7
- *
8
- * No external action dependency -- uses the GitHub REST API via
9
- * fetch with the caller-supplied GITHUB_TOKEN (or the default
10
- * GITHUB_TOKEN available to every Actions run).
11
- *
12
- * Issue #26. Plan: §15.
13
- */
14
- export interface CreateReleaseOptions {
15
- tag: string;
16
- title: string;
17
- body: string;
18
- /** Override for tests. Defaults to global fetch. */
19
- fetchFn?: typeof fetch;
20
- }
21
- export interface ReleaseResult {
22
- url: string;
23
- }
24
- /**
25
- * Generate release notes from `git log <prev_tag>..<this_tag>` subject
26
- * lines. If no prior tag exists for this package, falls back to the
27
- * full history (first release).
28
- *
29
- * The filter is subject-only -- commit bodies add noise and are
30
- * already available on the tag itself.
31
- */
32
- export declare function generateReleaseNotes(packageName: string, tagName: string, opts: {
33
- cwd: string;
34
- }): string;
35
- export declare function createGitHubRelease(opts: CreateReleaseOptions): Promise<ReleaseResult | null>;
36
- //# sourceMappingURL=release.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"release.d.ts","sourceRoot":"","sources":["../src/release.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GACpB,MAAM,CAKR;AAED,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAiC/B"}
package/dist/release.js DELETED
@@ -1,102 +0,0 @@
1
- /**
2
- * GitHub Release creation.
3
- *
4
- * After a successful tag push (§13.6), create a Release on GitHub so
5
- * the new version shows up in the repo's Releases UI with body notes
6
- * generated from the commit history since the previous tag.
7
- *
8
- * No external action dependency -- uses the GitHub REST API via
9
- * fetch with the caller-supplied GITHUB_TOKEN (or the default
10
- * GITHUB_TOKEN available to every Actions run).
11
- *
12
- * Issue #26. Plan: §15.
13
- */
14
- import { execFileSync } from 'node:child_process';
15
- /**
16
- * Generate release notes from `git log <prev_tag>..<this_tag>` subject
17
- * lines. If no prior tag exists for this package, falls back to the
18
- * full history (first release).
19
- *
20
- * The filter is subject-only -- commit bodies add noise and are
21
- * already available on the tag itself.
22
- */
23
- export function generateReleaseNotes(packageName, tagName, opts) {
24
- const prev = findPreviousTag(packageName, tagName, opts.cwd);
25
- const range = prev ? `${prev}..${tagName}` : tagName;
26
- const out = runGit(['log', range, '--format=- %s', '--no-merges'], opts.cwd);
27
- return out.trim();
28
- }
29
- export async function createGitHubRelease(opts) {
30
- const token = process.env.GITHUB_TOKEN;
31
- const repository = process.env.GITHUB_REPOSITORY;
32
- if (!token || !repository) {
33
- // Local runs (putitoutthere doctor, operator on laptop) don't have
34
- // these. Silent-skip so we don't confuse operators with a failure
35
- // that doesn't matter outside Actions.
36
- return null;
37
- }
38
- const fetchFn = opts.fetchFn ?? fetch;
39
- const url = `https://api.github.com/repos/${repository}/releases`;
40
- const res = await fetchFn(url, {
41
- method: 'POST',
42
- headers: {
43
- authorization: `Bearer ${token}`,
44
- 'content-type': 'application/json',
45
- accept: 'application/vnd.github+json',
46
- 'user-agent': 'putitoutthere',
47
- },
48
- body: JSON.stringify({
49
- tag_name: opts.tag,
50
- name: opts.title,
51
- body: opts.body,
52
- draft: false,
53
- prerelease: isPrerelease(opts.tag),
54
- }),
55
- });
56
- if (!res.ok) {
57
- const msg = await res.text().catch(() => '');
58
- throw new Error(`GitHub release API ${res.status}: ${msg}`);
59
- }
60
- const data = (await res.json());
61
- return { url: data.html_url ?? '' };
62
- }
63
- /* ------------------------------ internals ------------------------------ */
64
- function isPrerelease(tag) {
65
- return /-(rc|beta|alpha)(\.|$)/.test(tag);
66
- }
67
- function runGit(args, cwd) {
68
- try {
69
- return execFileSync('git', args, { cwd, encoding: 'utf8' });
70
- /* v8 ignore start -- defensive wrap */
71
- }
72
- catch (err) {
73
- const stderr = err.stderr?.toString('utf8') ?? '';
74
- throw new Error(`git ${args.join(' ')} failed: ${stderr.trim()}`, { cause: err });
75
- }
76
- /* v8 ignore stop */
77
- }
78
- function findPreviousTag(packageName, currentTag, cwd) {
79
- const prefix = `${packageName}-v`;
80
- const tags = runGit(['tag', '-l', `${prefix}*.*.*`], cwd)
81
- .split('\n')
82
- .filter((t) => t && t !== currentTag)
83
- .sort(compareSemverTags(prefix));
84
- return tags.length > 0 ? tags[tags.length - 1] : null;
85
- }
86
- function compareSemverTags(prefix) {
87
- return (a, b) => {
88
- const [am, an, ap] = parseVer(a.slice(prefix.length));
89
- const [bm, bn, bp] = parseVer(b.slice(prefix.length));
90
- if (am !== bm)
91
- return am - bm;
92
- if (an !== bn)
93
- return an - bn;
94
- return ap - bp;
95
- };
96
- }
97
- function parseVer(v) {
98
- const parts = v.split('.').map((n) => parseInt(n, 10));
99
- /* v8 ignore next -- tag-glob filter already enforces x.y.z shape */
100
- return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
101
- }
102
- //# sourceMappingURL=release.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"release.js","sourceRoot":"","sources":["../src/release.ts"],"names":[],"mappings":"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"}
@@ -1,43 +0,0 @@
1
- /**
2
- * Workflow templates emitted by `putitoutthere init`.
3
- *
4
- * Per plan.md §9.2 (immediate), §9.4 (scheduled), §9.5 (PR check).
5
- *
6
- * The `release.yml` templates follow the three-job shape
7
- * (plan → build → publish) so users can drop their build tooling into
8
- * the middle job without forking the orchestrator. Build steps are
9
- * keyed on `matrix.kind` (crates | pypi | npm) and `matrix.build`
10
- * (vanilla | maturin | napi | bundled-cli) so the right builder runs
11
- * per row.
12
- *
13
- * Issue #25. Plan: §9.
14
- */
15
- export type Cadence = 'immediate' | 'scheduled';
16
- /**
17
- * Seed values `tomlSkeleton` can bake into the emitted skeleton.
18
- * Today, the only one is a suggested `tag_format` for repos whose
19
- * existing tag history is `v*` — see `src/init.ts#detectTagFormatSuggestion`.
20
- */
21
- export interface SkeletonSeeds {
22
- tag_format?: string;
23
- /** Human-readable phrase explaining why the suggestion was made. */
24
- tag_format_reason?: string;
25
- }
26
- /**
27
- * Emit the `putitoutthere.toml` skeleton. When `seeds.tag_format` is
28
- * set, prepend a short comment explaining why plus a commented
29
- * `# tag_format = "..."` hint inside the crates example block.
30
- *
31
- * Kept as a function (not a constant) so init can bake in
32
- * per-repo detection results (#204). Callers without seeds get the
33
- * plain skeleton.
34
- */
35
- export declare function tomlSkeleton(seeds?: SkeletonSeeds | null): string;
36
- /** @deprecated use {@link tomlSkeleton}; kept for external consumers of the constant. */
37
- export declare const TOML_SKELETON = "# Put It Out There \u2014 release orchestration config.\n# Docs: https://github.com/thekevinscott/put-it-out-there\n\n[putitoutthere]\nversion = 1\n\n# Declare one [[package]] block per releasable artifact. Examples:\n#\n# [[package]]\n# name = \"my-crate\"\n# kind = \"crates\"\n# path = \"crates/my-crate\" # dir containing Cargo.toml\n# paths = [\"crates/my-crate/**\", \"**/Cargo.toml\", \"**/Cargo.lock\"]\n# first_version = \"0.1.0\"\n# # tag_format defaults to \"{name}-v{version}\". Single-package repos\n# # often want \"v{version}\" to keep the existing v0.1.0-style timeline.\n# # tag_format = \"v{version}\"\n#\n# [[package]]\n# name = \"my-py\"\n# kind = \"pypi\"\n# path = \"py/my-py\" # dir containing pyproject.toml\n# paths = [\"py/my-py/**\"]\n# first_version = \"0.1.0\"\n#\n# [[package]]\n# name = \"my-pkg\"\n# kind = \"npm\"\n# path = \"packages/my-pkg\" # dir containing package.json\n# paths = [\"packages/my-pkg/**\"]\n# first_version = \"0.1.0\"\n";
38
- export declare const AGENTS_MD = "# Release signaling for Put It Out There\n\nWhen you finish a unit of work and are preparing a PR or commit, add a git\ntrailer to the commit message body to signal a release:\n\n release: <patch|minor|major|skip>\n\nRules:\n- Omit the trailer for docs-only, CI-only, or internal-only changes.\n- `patch` for bug fixes or internal refactors that don't change public API.\n- `minor` for new features that are backwards-compatible.\n- `major` for breaking changes.\n- `skip` to suppress release when path filters would otherwise cascade.\n\nThe trailer on the merge commit determines the release. If merging via\n\"Squash and merge,\" include the trailer in the PR description so it ends up\nin the squashed commit body.\n\n## Scoping a release to specific packages\n\nTo release a subset of packages in a polyglot repo, append a bracketed list:\n\n release: minor [my-crate, my-py]\n\nPackages named in the list are bumped with the specified version. Other\npackages cascaded by path filters still get a `patch`. Packages in the\nlist that *aren't* cascaded are force-included.\n";
39
- export declare const RELEASE_YML_IMMEDIATE: string;
40
- export declare const RELEASE_YML_SCHEDULED: string;
41
- export declare const CHECK_YML = "name: Putitoutthere check\n\non:\n pull_request:\n branches: [main]\n\npermissions:\n contents: read\n pull-requests: read\n\njobs:\n dry-run:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n with:\n fetch-depth: 0\n - uses: thekevinscott/put-it-out-there@v0\n with:\n command: plan\n dry_run: true\n fail_on_error: true\n";
42
- export declare function releaseYml(cadence: Cadence): string;
43
- //# sourceMappingURL=templates.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../src/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,OAAO,GAAG,WAAW,GAAG,WAAW,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oEAAoE;IACpE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAmCD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,KAAK,GAAE,aAAa,GAAG,IAAW,GAAG,MAAM,CAWvE;AAED,yFAAyF;AACzF,eAAO,MAAM,aAAa,ygCAAqB,CAAC;AAEhD,eAAO,MAAM,SAAS,ikCA2BrB,CAAC;AA+LF,eAAO,MAAM,qBAAqB,QAAsE,CAAC;AACzG,eAAO,MAAM,qBAAqB,QAAsE,CAAC;AAEzG,eAAO,MAAM,SAAS,iaAsBrB,CAAC;AAEF,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAGnD"}