@fuzdev/fuz_gitops 0.77.0 → 0.78.1
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/README.md +25 -5
- package/dist/ModulesDetail.svelte +14 -12
- package/dist/ModulesDetail.svelte.d.ts.map +1 -1
- package/dist/ModulesNav.svelte +6 -6
- package/dist/ModulesNav.svelte.d.ts.map +1 -1
- package/dist/ModulesPage.svelte +2 -2
- package/dist/ModulesPage.svelte.d.ts.map +1 -1
- package/dist/PageFooter.svelte +2 -2
- package/dist/PageHeader.svelte +5 -5
- package/dist/PageHeader.svelte.d.ts +1 -1
- package/dist/PageHeader.svelte.d.ts.map +1 -1
- package/dist/PullRequestsDetail.svelte +25 -17
- package/dist/PullRequestsDetail.svelte.d.ts.map +1 -1
- package/dist/PullRequestsPage.svelte +3 -3
- package/dist/PullRequestsPage.svelte.d.ts.map +1 -1
- package/dist/ReposTable.svelte +24 -15
- package/dist/ReposTable.svelte.d.ts.map +1 -1
- package/dist/ReposTree.svelte +8 -6
- package/dist/ReposTree.svelte.d.ts.map +1 -1
- package/dist/ReposTreeNav.svelte +10 -11
- package/dist/ReposTreeNav.svelte.d.ts.map +1 -1
- package/dist/TablePage.svelte +2 -2
- package/dist/TablePage.svelte.d.ts.map +1 -1
- package/dist/TreeItemPage.svelte +2 -2
- package/dist/TreeItemPage.svelte.d.ts.map +1 -1
- package/dist/TreePage.svelte +2 -2
- package/dist/TreePage.svelte.d.ts.map +1 -1
- package/dist/cargo_toml.d.ts +33 -0
- package/dist/cargo_toml.d.ts.map +1 -0
- package/dist/cargo_toml.js +74 -0
- package/dist/changeset_generator.d.ts +1 -1
- package/dist/changeset_generator.d.ts.map +1 -1
- package/dist/changeset_generator.js +2 -2
- package/dist/changeset_reader.d.ts +1 -1
- package/dist/changeset_reader.d.ts.map +1 -1
- package/dist/changeset_reader.js +3 -3
- package/dist/config_reconcile.d.ts.map +1 -1
- package/dist/config_reconcile.js +6 -2
- package/dist/dependency_graph.d.ts +2 -2
- package/dist/dependency_graph.d.ts.map +1 -1
- package/dist/dependency_graph.js +9 -9
- package/dist/dependency_updater.d.ts +1 -1
- package/dist/dependency_updater.d.ts.map +1 -1
- package/dist/dependency_updater.js +8 -8
- package/dist/fetch_repo_data.d.ts +2 -2
- package/dist/fetch_repo_data.d.ts.map +1 -1
- package/dist/fetch_repo_data.js +4 -4
- package/dist/fs_fetch_value_cache.d.ts +1 -1
- package/dist/fs_fetch_value_cache.d.ts.map +1 -1
- package/dist/fs_fetch_value_cache.js +5 -5
- package/dist/git_operations.d.ts +1 -1
- package/dist/git_operations.d.ts.map +1 -1
- package/dist/git_operations.js +2 -2
- package/dist/github.d.ts +2 -2
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +7 -7
- package/dist/github_helpers.d.ts.map +1 -1
- package/dist/github_helpers.js +1 -1
- package/dist/gitops_analyze.task.d.ts.map +1 -1
- package/dist/gitops_analyze.task.js +21 -14
- package/dist/gitops_config.d.ts +2 -2
- package/dist/gitops_config.d.ts.map +1 -1
- package/dist/gitops_config.js +5 -5
- package/dist/gitops_plan.task.d.ts.map +1 -1
- package/dist/gitops_plan.task.js +8 -8
- package/dist/gitops_publish.task.d.ts.map +1 -1
- package/dist/gitops_publish.task.js +15 -12
- package/dist/gitops_run.task.d.ts.map +1 -1
- package/dist/gitops_run.task.js +10 -10
- package/dist/gitops_sync.task.d.ts.map +1 -1
- package/dist/gitops_sync.task.js +15 -13
- package/dist/gitops_task_helpers.d.ts +1 -1
- package/dist/gitops_task_helpers.d.ts.map +1 -1
- package/dist/gitops_task_helpers.js +4 -4
- package/dist/gitops_validate.task.d.ts.map +1 -1
- package/dist/gitops_validate.task.js +14 -14
- package/dist/graph_validation.d.ts +2 -2
- package/dist/graph_validation.d.ts.map +1 -1
- package/dist/graph_validation.js +5 -3
- package/dist/local_repo.d.ts +21 -7
- package/dist/local_repo.d.ts.map +1 -1
- package/dist/local_repo.js +64 -16
- package/dist/log_helpers.d.ts +1 -1
- package/dist/log_helpers.d.ts.map +1 -1
- package/dist/multi_repo_publisher.d.ts +3 -3
- package/dist/multi_repo_publisher.d.ts.map +1 -1
- package/dist/multi_repo_publisher.js +24 -20
- package/dist/npm_registry.d.ts +1 -1
- package/dist/npm_registry.d.ts.map +1 -1
- package/dist/npm_registry.js +4 -4
- package/dist/operations.d.ts +4 -4
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations_defaults.d.ts.map +1 -1
- package/dist/operations_defaults.js +16 -16
- package/dist/output_helpers.d.ts +1 -1
- package/dist/output_helpers.d.ts.map +1 -1
- package/dist/preflight_checks.d.ts +2 -2
- package/dist/preflight_checks.d.ts.map +1 -1
- package/dist/preflight_checks.js +5 -5
- package/dist/publish_gate.d.ts.map +1 -1
- package/dist/publish_steps.d.ts.map +1 -1
- package/dist/publish_steps.js +4 -4
- package/dist/publishing_event.d.ts.map +1 -1
- package/dist/publishing_event.js +16 -14
- package/dist/publishing_event_handler.d.ts.map +1 -1
- package/dist/publishing_event_handler.js +6 -6
- package/dist/publishing_plan.d.ts +3 -3
- package/dist/publishing_plan.d.ts.map +1 -1
- package/dist/publishing_plan.js +25 -15
- package/dist/publishing_plan_helpers.d.ts.map +1 -1
- package/dist/publishing_plan_helpers.js +3 -3
- package/dist/publishing_plan_logging.d.ts +1 -1
- package/dist/publishing_plan_logging.d.ts.map +1 -1
- package/dist/publishing_plan_logging.js +2 -2
- package/dist/repo.svelte.d.ts +5 -5
- package/dist/repo.svelte.d.ts.map +1 -1
- package/dist/repo.svelte.js +2 -2
- package/dist/repo_ops.js +2 -2
- package/dist/resolved_gitops_config.d.ts.map +1 -1
- package/dist/resolved_gitops_config.js +1 -1
- package/dist/version_utils.js +1 -1
- package/package.json +16 -15
- package/src/lib/cargo_toml.ts +82 -0
- package/src/lib/changeset_generator.ts +20 -20
- package/src/lib/changeset_reader.ts +18 -18
- package/src/lib/ci_reconcile.ts +5 -5
- package/src/lib/config_reconcile.ts +8 -4
- package/src/lib/dependency_graph.ts +28 -28
- package/src/lib/dependency_updater.ts +30 -30
- package/src/lib/fetch_repo_data.ts +11 -11
- package/src/lib/fs_fetch_value_cache.ts +14 -10
- package/src/lib/git_operations.ts +31 -31
- package/src/lib/github.ts +19 -19
- package/src/lib/github_helpers.ts +6 -6
- package/src/lib/gitops_analyze.task.ts +56 -48
- package/src/lib/gitops_config.ts +14 -14
- package/src/lib/gitops_plan.task.ts +32 -32
- package/src/lib/gitops_publish.task.ts +52 -49
- package/src/lib/gitops_run.task.ts +29 -29
- package/src/lib/gitops_sync.task.ts +39 -30
- package/src/lib/gitops_task_helpers.ts +21 -21
- package/src/lib/gitops_validate.task.ts +38 -38
- package/src/lib/graph_validation.ts +14 -13
- package/src/lib/local_repo.ts +130 -64
- package/src/lib/log_helpers.ts +15 -15
- package/src/lib/multi_repo_publisher.ts +75 -74
- package/src/lib/npm_registry.ts +13 -13
- package/src/lib/operations.ts +50 -39
- package/src/lib/operations_defaults.ts +108 -106
- package/src/lib/output_helpers.ts +4 -4
- package/src/lib/preflight_checks.ts +28 -28
- package/src/lib/publish_gate.ts +7 -9
- package/src/lib/publish_steps.ts +15 -15
- package/src/lib/publishing_event.ts +22 -20
- package/src/lib/publishing_event_handler.ts +8 -8
- package/src/lib/publishing_plan.ts +69 -57
- package/src/lib/publishing_plan_helpers.ts +16 -12
- package/src/lib/publishing_plan_logging.ts +23 -23
- package/src/lib/repo.svelte.ts +8 -8
- package/src/lib/repo_ops.ts +12 -12
- package/src/lib/resolved_gitops_config.ts +5 -5
- package/src/lib/version_utils.ts +3 -3
package/src/lib/publish_steps.ts
CHANGED
|
@@ -8,17 +8,17 @@
|
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import type {BumpType} from './version_utils.
|
|
12
|
-
import type {PublishingPlan, VersionChange} from './publishing_plan.
|
|
13
|
-
import {UnreachableError} from '@fuzdev/fuz_util/error.
|
|
11
|
+
import type { BumpType } from './version_utils.ts';
|
|
12
|
+
import type { PublishingPlan, VersionChange } from './publishing_plan.ts';
|
|
13
|
+
import { UnreachableError } from '@fuzdev/fuz_util/error.ts';
|
|
14
14
|
|
|
15
15
|
/** How a package's version bump arises in the plan. */
|
|
16
16
|
export type PublishStepVia = 'changeset' | 'auto_changeset' | 'escalation';
|
|
17
17
|
|
|
18
18
|
/** One ordered side-effect a wetrun would perform. */
|
|
19
19
|
export type PublishStep =
|
|
20
|
-
| {kind: 'publish'; repo: string; from: string; to: string; bump: BumpType; via: PublishStepVia}
|
|
21
|
-
| {kind: 'npm_wait'; repo: string; version: string}
|
|
20
|
+
| { kind: 'publish'; repo: string; from: string; to: string; bump: BumpType; via: PublishStepVia }
|
|
21
|
+
| { kind: 'npm_wait'; repo: string; version: string }
|
|
22
22
|
| {
|
|
23
23
|
kind: 'dependency_update';
|
|
24
24
|
dependent: string;
|
|
@@ -27,8 +27,8 @@ export type PublishStep =
|
|
|
27
27
|
dep_type: 'prod' | 'peer';
|
|
28
28
|
creates_changeset: boolean;
|
|
29
29
|
}
|
|
30
|
-
| {kind: 'dev_dep_update'; repo: string; dependency: string; to: string}
|
|
31
|
-
| {kind: 'deploy'; repo: string; builds: boolean};
|
|
30
|
+
| { kind: 'dev_dep_update'; repo: string; dependency: string; to: string }
|
|
31
|
+
| { kind: 'deploy'; repo: string; builds: boolean };
|
|
32
32
|
|
|
33
33
|
export interface DerivePublishStepsOptions {
|
|
34
34
|
/** Include the deploy phase (the publisher only deploys with `--deploy`). */
|
|
@@ -51,11 +51,11 @@ const step_via = (change: VersionChange): PublishStepVia =>
|
|
|
51
51
|
*/
|
|
52
52
|
export const derive_publish_steps = (
|
|
53
53
|
plan: PublishingPlan,
|
|
54
|
-
options: DerivePublishStepsOptions = {}
|
|
54
|
+
options: DerivePublishStepsOptions = {}
|
|
55
55
|
): Array<PublishStep> => {
|
|
56
|
-
const {deploy = false} = options;
|
|
56
|
+
const { deploy = false } = options;
|
|
57
57
|
const changes: Map<string, VersionChange> = new Map(
|
|
58
|
-
plan.version_changes.map((vc) => [vc.package_name, vc])
|
|
58
|
+
plan.version_changes.map((vc) => [vc.package_name, vc])
|
|
59
59
|
);
|
|
60
60
|
|
|
61
61
|
const steps: Array<PublishStep> = [];
|
|
@@ -72,9 +72,9 @@ export const derive_publish_steps = (
|
|
|
72
72
|
from: change.from,
|
|
73
73
|
to: change.to,
|
|
74
74
|
bump: change.bump_type,
|
|
75
|
-
via: step_via(change)
|
|
75
|
+
via: step_via(change)
|
|
76
76
|
});
|
|
77
|
-
steps.push({kind: 'npm_wait', repo, version: change.to});
|
|
77
|
+
steps.push({ kind: 'npm_wait', repo, version: change.to });
|
|
78
78
|
changed.add(repo);
|
|
79
79
|
|
|
80
80
|
// Prod/peer dependents are rewritten right after this publishes. A dependent that
|
|
@@ -92,7 +92,7 @@ export const derive_publish_steps = (
|
|
|
92
92
|
dependency: repo,
|
|
93
93
|
to: change.to,
|
|
94
94
|
dep_type: update.type === 'peerDependencies' ? 'peer' : 'prod',
|
|
95
|
-
creates_changeset: republishes
|
|
95
|
+
creates_changeset: republishes
|
|
96
96
|
});
|
|
97
97
|
changed.add(update.dependent_package);
|
|
98
98
|
}
|
|
@@ -109,7 +109,7 @@ export const derive_publish_steps = (
|
|
|
109
109
|
kind: 'dev_dep_update',
|
|
110
110
|
repo: update.dependent_package,
|
|
111
111
|
dependency: update.updated_dependency,
|
|
112
|
-
to: dep_change.to
|
|
112
|
+
to: dep_change.to
|
|
113
113
|
});
|
|
114
114
|
changed.add(update.dependent_package);
|
|
115
115
|
}
|
|
@@ -117,7 +117,7 @@ export const derive_publish_steps = (
|
|
|
117
117
|
// Phase 3: deploy every changed repo (only with --deploy). Each builds fresh.
|
|
118
118
|
if (deploy) {
|
|
119
119
|
for (const repo of changed) {
|
|
120
|
-
steps.push({kind: 'deploy', repo, builds: true});
|
|
120
|
+
steps.push({ kind: 'deploy', repo, builds: true });
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* @module
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {z} from 'zod';
|
|
17
|
+
import { z } from 'zod';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Coarse triage classification for a failed package. Lets consumers branch on
|
|
@@ -30,17 +30,17 @@ export const PublishingErrorCode = z.enum([
|
|
|
30
30
|
// invariant violation, distinct from an ordinary publish failure (see fail-loud
|
|
31
31
|
// drift detection in `multi_repo_publisher.ts`)
|
|
32
32
|
'drift',
|
|
33
|
-
'other'
|
|
33
|
+
'other'
|
|
34
34
|
]);
|
|
35
35
|
export type PublishingErrorCode = z.infer<typeof PublishingErrorCode>;
|
|
36
36
|
|
|
37
37
|
/** Tallied outcome of a publishing run, derived from its events via `summarize_events`. */
|
|
38
38
|
export const PublishingRunSummary = z.strictObject({
|
|
39
|
-
total: z.number().meta({description: 'packages in the publishing order (the candidate set)'}),
|
|
40
|
-
published: z.number().meta({description: 'packages published (or, in a dry run, predicted)'}),
|
|
39
|
+
total: z.number().meta({ description: 'packages in the publishing order (the candidate set)' }),
|
|
40
|
+
published: z.number().meta({ description: 'packages published (or, in a dry run, predicted)' }),
|
|
41
41
|
failed: z.number(),
|
|
42
42
|
skipped: z.number(),
|
|
43
|
-
duration: z.number().meta({description: 'wall-clock duration in milliseconds'})
|
|
43
|
+
duration: z.number().meta({ description: 'wall-clock duration in milliseconds' })
|
|
44
44
|
});
|
|
45
45
|
export type PublishingRunSummary = z.infer<typeof PublishingRunSummary>;
|
|
46
46
|
|
|
@@ -51,13 +51,15 @@ export type PublishingRunSummary = z.infer<typeof PublishingRunSummary>;
|
|
|
51
51
|
export const PublishingEvent = z.discriminatedUnion('event', [
|
|
52
52
|
z.strictObject({
|
|
53
53
|
event: z.literal('run_started'),
|
|
54
|
-
wetrun: z
|
|
55
|
-
|
|
54
|
+
wetrun: z
|
|
55
|
+
.boolean()
|
|
56
|
+
.meta({ description: 'false means every package_completed is a prediction' }),
|
|
57
|
+
total: z.number()
|
|
56
58
|
}),
|
|
57
59
|
z.strictObject({
|
|
58
60
|
event: z.literal('package_skipped'),
|
|
59
61
|
name: z.string(),
|
|
60
|
-
reason: z.string()
|
|
62
|
+
reason: z.string()
|
|
61
63
|
}),
|
|
62
64
|
z.strictObject({
|
|
63
65
|
event: z.literal('package_completed'),
|
|
@@ -67,19 +69,19 @@ export const PublishingEvent = z.discriminatedUnion('event', [
|
|
|
67
69
|
// mirrors `BumpType` from `version_utils.ts`; inline so the event schema is self-contained
|
|
68
70
|
bump_type: z.enum(['major', 'minor', 'patch']),
|
|
69
71
|
breaking: z.boolean(),
|
|
70
|
-
commit: z.string().meta({description: "'simulated' in a dry run, otherwise the commit hash"}),
|
|
71
|
-
tag: z.string()
|
|
72
|
+
commit: z.string().meta({ description: "'simulated' in a dry run, otherwise the commit hash" }),
|
|
73
|
+
tag: z.string()
|
|
72
74
|
}),
|
|
73
75
|
z.strictObject({
|
|
74
76
|
event: z.literal('npm_waited'),
|
|
75
77
|
name: z.string(),
|
|
76
|
-
version: z.string().meta({description: 'the version waited on after publishing'})
|
|
78
|
+
version: z.string().meta({ description: 'the version waited on after publishing' })
|
|
77
79
|
}),
|
|
78
80
|
z.strictObject({
|
|
79
81
|
event: z.literal('package_failed'),
|
|
80
82
|
name: z.string(),
|
|
81
83
|
error: z.string(),
|
|
82
|
-
code: PublishingErrorCode
|
|
84
|
+
code: PublishingErrorCode
|
|
83
85
|
}),
|
|
84
86
|
z.strictObject({
|
|
85
87
|
event: z.literal('dependency_updated'),
|
|
@@ -91,25 +93,25 @@ export const PublishingEvent = z.discriminatedUnion('event', [
|
|
|
91
93
|
dep_type: z.enum(['prod', 'peer', 'dev']),
|
|
92
94
|
// true when the update creates an auto-changeset (a publishable dependent republishes);
|
|
93
95
|
// false for dev-dep updates and update-only leaves (private dependents never publish).
|
|
94
|
-
creates_changeset: z.boolean()
|
|
96
|
+
creates_changeset: z.boolean()
|
|
95
97
|
}),
|
|
96
98
|
z.strictObject({
|
|
97
99
|
event: z.literal('deploy_started'),
|
|
98
|
-
name: z.string()
|
|
100
|
+
name: z.string()
|
|
99
101
|
}),
|
|
100
102
|
z.strictObject({
|
|
101
103
|
event: z.literal('deploy_completed'),
|
|
102
|
-
name: z.string()
|
|
104
|
+
name: z.string()
|
|
103
105
|
}),
|
|
104
106
|
z.strictObject({
|
|
105
107
|
event: z.literal('deploy_failed'),
|
|
106
108
|
name: z.string(),
|
|
107
|
-
error: z.string()
|
|
109
|
+
error: z.string()
|
|
108
110
|
}),
|
|
109
111
|
z.strictObject({
|
|
110
112
|
event: z.literal('run_finished'),
|
|
111
|
-
summary: PublishingRunSummary
|
|
112
|
-
})
|
|
113
|
+
summary: PublishingRunSummary
|
|
114
|
+
})
|
|
113
115
|
]);
|
|
114
116
|
export type PublishingEvent = z.infer<typeof PublishingEvent>;
|
|
115
117
|
|
|
@@ -123,7 +125,7 @@ export type PublishingEvent = z.infer<typeof PublishingEvent>;
|
|
|
123
125
|
*/
|
|
124
126
|
export const summarize_events = (
|
|
125
127
|
events: Array<PublishingEvent>,
|
|
126
|
-
duration: number
|
|
128
|
+
duration: number
|
|
127
129
|
): PublishingRunSummary => {
|
|
128
130
|
let total = 0;
|
|
129
131
|
let published = 0;
|
|
@@ -147,5 +149,5 @@ export const summarize_events = (
|
|
|
147
149
|
break;
|
|
148
150
|
}
|
|
149
151
|
}
|
|
150
|
-
return {total, published, failed, skipped, duration};
|
|
152
|
+
return { total, published, failed, skipped, duration };
|
|
151
153
|
};
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import type {PublishingEvent} from './publishing_event.
|
|
12
|
+
import type { PublishingEvent } from './publishing_event.ts';
|
|
13
13
|
|
|
14
14
|
/** A sink for publishing events. */
|
|
15
15
|
export interface PublishingEventHandler {
|
|
@@ -23,7 +23,7 @@ export interface CapturingEventHandler extends PublishingEventHandler {
|
|
|
23
23
|
|
|
24
24
|
/** Drops every event. The default when no handler is supplied. */
|
|
25
25
|
export const null_handler = (): PublishingEventHandler => ({
|
|
26
|
-
emit: () => {}
|
|
26
|
+
emit: () => {}
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
/** Collects events in memory. Used to build the run report and in tests. */
|
|
@@ -33,7 +33,7 @@ export const capture_handler = (): CapturingEventHandler => {
|
|
|
33
33
|
events,
|
|
34
34
|
emit: (event) => {
|
|
35
35
|
events.push(event);
|
|
36
|
-
}
|
|
36
|
+
}
|
|
37
37
|
};
|
|
38
38
|
};
|
|
39
39
|
|
|
@@ -48,7 +48,7 @@ export const stdout_handler = (): PublishingEventHandler => ({
|
|
|
48
48
|
} catch {
|
|
49
49
|
// best-effort: a logging sink must never fail a run
|
|
50
50
|
}
|
|
51
|
-
}
|
|
51
|
+
}
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
/** Fans an event out to every handler in order. */
|
|
@@ -57,7 +57,7 @@ export const multi_handler = (handlers: Array<PublishingEventHandler>): Publishi
|
|
|
57
57
|
for (const handler of handlers) {
|
|
58
58
|
handler.emit(event);
|
|
59
59
|
}
|
|
60
|
-
}
|
|
60
|
+
}
|
|
61
61
|
});
|
|
62
62
|
|
|
63
63
|
/**
|
|
@@ -68,11 +68,11 @@ export const multi_handler = (handlers: Array<PublishingEventHandler>): Publishi
|
|
|
68
68
|
*/
|
|
69
69
|
export const masking_handler = (
|
|
70
70
|
inner: PublishingEventHandler,
|
|
71
|
-
mask: (event: PublishingEvent) => PublishingEvent = mask_secrets
|
|
71
|
+
mask: (event: PublishingEvent) => PublishingEvent = mask_secrets
|
|
72
72
|
): PublishingEventHandler => ({
|
|
73
73
|
emit: (event) => {
|
|
74
74
|
inner.emit(mask(event));
|
|
75
|
-
}
|
|
75
|
+
}
|
|
76
76
|
});
|
|
77
77
|
|
|
78
78
|
// Minimal redaction rules: npm auth tokens (bare or registry-scoped), `SECRET_*`
|
|
@@ -81,7 +81,7 @@ export const masking_handler = (
|
|
|
81
81
|
const SECRET_RULES: Array<readonly [RegExp, string]> = [
|
|
82
82
|
[/((?:\/\/[^\s:]+:)?_authToken\s*=\s*)\S+/gi, '$1[redacted]'],
|
|
83
83
|
[/(SECRET_[A-Z0-9_]+\s*[=:]\s*)\S+/g, '$1[redacted]'],
|
|
84
|
-
[/(npm_[A-Za-z0-9]{4})[A-Za-z0-9]{12,}/g, '$1[redacted]']
|
|
84
|
+
[/(npm_[A-Za-z0-9]{4})[A-Za-z0-9]{12,}/g, '$1[redacted]']
|
|
85
85
|
];
|
|
86
86
|
|
|
87
87
|
/** Redacts known secret shapes from a string. */
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import type {Logger} from '@fuzdev/fuz_util/log.
|
|
2
|
-
import {styleText as st} from 'node:util';
|
|
1
|
+
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
2
|
+
import { styleText as st } from 'node:util';
|
|
3
3
|
|
|
4
|
-
import type
|
|
5
|
-
import {validate_dependency_graph} from './graph_validation.
|
|
4
|
+
import { repo_is_npm, type LocalRepo } from './local_repo.ts';
|
|
5
|
+
import { validate_dependency_graph } from './graph_validation.ts';
|
|
6
6
|
import {
|
|
7
7
|
type BumpType,
|
|
8
8
|
is_breaking_change,
|
|
9
9
|
compare_bump_types,
|
|
10
|
-
calculate_next_version
|
|
11
|
-
} from './version_utils.
|
|
12
|
-
import type {ChangesetOperations} from './operations.
|
|
13
|
-
import {default_changeset_operations} from './operations_defaults.
|
|
14
|
-
import {GITOPS_MAX_ITERATIONS_DEFAULT} from './gitops_constants.
|
|
15
|
-
import type {DependencyGraph} from './dependency_graph.ts';
|
|
10
|
+
calculate_next_version
|
|
11
|
+
} from './version_utils.ts';
|
|
12
|
+
import type { ChangesetOperations } from './operations.ts';
|
|
13
|
+
import { default_changeset_operations } from './operations_defaults.ts';
|
|
14
|
+
import { GITOPS_MAX_ITERATIONS_DEFAULT } from './gitops_constants.ts';
|
|
15
|
+
import type { DependencyGraph } from './dependency_graph.ts';
|
|
16
16
|
import {
|
|
17
17
|
calculate_dependency_updates,
|
|
18
|
-
get_required_bump_for_dependencies
|
|
19
|
-
} from './publishing_plan_helpers.
|
|
18
|
+
get_required_bump_for_dependencies
|
|
19
|
+
} from './publishing_plan_helpers.ts';
|
|
20
20
|
|
|
21
21
|
// Re-export logging functions
|
|
22
|
-
export {log_publishing_plan, type LogPlanOptions} from './publishing_plan_logging.
|
|
22
|
+
export { log_publishing_plan, type LogPlanOptions } from './publishing_plan_logging.ts';
|
|
23
23
|
|
|
24
24
|
export interface VersionChange {
|
|
25
25
|
package_name: string;
|
|
@@ -45,7 +45,7 @@ export interface DependencyUpdate {
|
|
|
45
45
|
// Verbose data types for diagnostic output
|
|
46
46
|
export interface VerboseChangesetDetail {
|
|
47
47
|
package_name: string;
|
|
48
|
-
files: Array<{filename: string; bump_type: BumpType; summary: string}>;
|
|
48
|
+
files: Array<{ filename: string; bump_type: BumpType; summary: string }>;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
export interface VerboseIterationPackage {
|
|
@@ -67,14 +67,14 @@ export interface VerboseIteration {
|
|
|
67
67
|
|
|
68
68
|
export interface VerbosePropagationChain {
|
|
69
69
|
source: string;
|
|
70
|
-
chain: Array<{pkg: string; dep_type: 'prod' | 'peer'; action: string}>;
|
|
70
|
+
chain: Array<{ pkg: string; dep_type: 'prod' | 'peer'; action: string }>;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
export interface VerboseGraphSummary {
|
|
74
74
|
package_count: number;
|
|
75
75
|
internal_dep_count: number;
|
|
76
|
-
prod_peer_edges: Array<{from: string; to: string; type: 'prod' | 'peer'}>;
|
|
77
|
-
dev_edges: Array<{from: string; to: string}>;
|
|
76
|
+
prod_peer_edges: Array<{ from: string; to: string; type: 'prod' | 'peer' }>;
|
|
77
|
+
dev_edges: Array<{ from: string; to: string }>;
|
|
78
78
|
prod_cycle_count: number;
|
|
79
79
|
dev_cycle_count: number;
|
|
80
80
|
}
|
|
@@ -110,16 +110,28 @@ export interface GeneratePlanOptions {
|
|
|
110
110
|
* Uses fixed-point iteration to resolve transitive cascades.
|
|
111
111
|
*/
|
|
112
112
|
export const generate_publishing_plan = async (
|
|
113
|
-
|
|
114
|
-
options: GeneratePlanOptions = {}
|
|
113
|
+
all_repos: Array<LocalRepo>,
|
|
114
|
+
options: GeneratePlanOptions = {}
|
|
115
115
|
): Promise<PublishingPlan> => {
|
|
116
|
-
const {log, ops = default_changeset_operations, verbose} = options;
|
|
116
|
+
const { log, ops = default_changeset_operations, verbose } = options;
|
|
117
117
|
log?.info(st('cyan', 'Generating publishing plan...'));
|
|
118
118
|
|
|
119
119
|
const warnings: Array<string> = [];
|
|
120
120
|
const info: Array<string> = []; // Informational status (not warnings)
|
|
121
121
|
const errors: Array<string> = [];
|
|
122
122
|
|
|
123
|
+
// Publishing concerns only npm packages. Non-npm repos (e.g. Rust cargo repos) are
|
|
124
|
+
// loaded for the dashboard but have no npm identity in the changeset cascade — drop them
|
|
125
|
+
// before building the graph so they never appear in the plan or publishing order.
|
|
126
|
+
const non_npm_repos = all_repos.filter((r) => !repo_is_npm(r));
|
|
127
|
+
if (non_npm_repos.length > 0) {
|
|
128
|
+
info.push(
|
|
129
|
+
`Excluded ${non_npm_repos.length} non-npm repo(s) from publishing: ` +
|
|
130
|
+
non_npm_repos.map((r) => r.library.name).join(', ')
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
const repos = all_repos.filter(repo_is_npm);
|
|
134
|
+
|
|
123
135
|
// Verbose data collection
|
|
124
136
|
const verbose_changeset_details: Array<VerboseChangesetDetail> = [];
|
|
125
137
|
const verbose_iterations: Array<VerboseIteration> = [];
|
|
@@ -134,7 +146,7 @@ export const generate_publishing_plan = async (
|
|
|
134
146
|
const validation = validate_dependency_graph(repos, {
|
|
135
147
|
throw_on_prod_cycles: false, // Collect errors instead of throwing
|
|
136
148
|
log_cycles: false, // We'll handle our own error collection
|
|
137
|
-
log_order: false
|
|
149
|
+
log_order: false // Plan generation doesn't need to log order
|
|
138
150
|
});
|
|
139
151
|
publishing_order = validation.publishing_order;
|
|
140
152
|
production_cycles = validation.production_cycles;
|
|
@@ -154,7 +166,7 @@ export const generate_publishing_plan = async (
|
|
|
154
166
|
breaking_cascades: new Map(),
|
|
155
167
|
warnings,
|
|
156
168
|
info,
|
|
157
|
-
errors
|
|
169
|
+
errors
|
|
158
170
|
};
|
|
159
171
|
}
|
|
160
172
|
|
|
@@ -168,7 +180,7 @@ export const generate_publishing_plan = async (
|
|
|
168
180
|
// Dev cycles are shown in gitops_analyze, not repeated here
|
|
169
181
|
if (dev_cycles.length > 0) {
|
|
170
182
|
info.push(
|
|
171
|
-
`${dev_cycles.length} dev dependency cycle(s) detected (normal, shown in gitops_analyze)
|
|
183
|
+
`${dev_cycles.length} dev dependency cycle(s) detected (normal, shown in gitops_analyze)`
|
|
172
184
|
);
|
|
173
185
|
}
|
|
174
186
|
|
|
@@ -186,7 +198,7 @@ export const generate_publishing_plan = async (
|
|
|
186
198
|
// the topological order. Flag a private package that carries a changeset, since that
|
|
187
199
|
// changeset can't be published.
|
|
188
200
|
if (repo.package_json.private) {
|
|
189
|
-
const private_has_changesets = await ops.has_changesets({repo});
|
|
201
|
+
const private_has_changesets = await ops.has_changesets({ repo });
|
|
190
202
|
if (private_has_changesets.ok && private_has_changesets.value) {
|
|
191
203
|
warnings.push(`${pkg_name} is private — its changeset(s) will not be published`);
|
|
192
204
|
}
|
|
@@ -194,7 +206,7 @@ export const generate_publishing_plan = async (
|
|
|
194
206
|
}
|
|
195
207
|
|
|
196
208
|
// Check for changesets
|
|
197
|
-
const has_result = await ops.has_changesets({repo});
|
|
209
|
+
const has_result = await ops.has_changesets({ repo });
|
|
198
210
|
|
|
199
211
|
if (!has_result.ok) {
|
|
200
212
|
errors.push(`Failed to check changesets for ${pkg_name}: ${has_result.message}`);
|
|
@@ -203,7 +215,7 @@ export const generate_publishing_plan = async (
|
|
|
203
215
|
|
|
204
216
|
if (has_result.value) {
|
|
205
217
|
// Predict version from changesets
|
|
206
|
-
const prediction = await ops.predict_next_version({repo, log});
|
|
218
|
+
const prediction = await ops.predict_next_version({ repo, log });
|
|
207
219
|
|
|
208
220
|
if (!prediction) {
|
|
209
221
|
// No changesets found - this shouldn't happen since has_changesets returned true
|
|
@@ -217,7 +229,7 @@ export const generate_publishing_plan = async (
|
|
|
217
229
|
|
|
218
230
|
// Capture changeset details for verbose output
|
|
219
231
|
if (verbose) {
|
|
220
|
-
const changesets_result = await ops.read_changesets({repo, log});
|
|
232
|
+
const changesets_result = await ops.read_changesets({ repo, log });
|
|
221
233
|
if (changesets_result.ok) {
|
|
222
234
|
const files = changesets_result.value
|
|
223
235
|
.filter((cs) => cs.packages.some((p) => p.name === pkg_name))
|
|
@@ -226,11 +238,11 @@ export const generate_publishing_plan = async (
|
|
|
226
238
|
return {
|
|
227
239
|
filename: cs.filename,
|
|
228
240
|
bump_type: pkg_entry?.bump_type || prediction.bump_type,
|
|
229
|
-
summary: cs.summary
|
|
241
|
+
summary: cs.summary
|
|
230
242
|
};
|
|
231
243
|
});
|
|
232
244
|
if (files.length > 0) {
|
|
233
|
-
verbose_changeset_details.push({package_name: pkg_name, files});
|
|
245
|
+
verbose_changeset_details.push({ package_name: pkg_name, files });
|
|
234
246
|
}
|
|
235
247
|
}
|
|
236
248
|
}
|
|
@@ -251,7 +263,7 @@ export const generate_publishing_plan = async (
|
|
|
251
263
|
to: prediction.version,
|
|
252
264
|
bump_type: prediction.bump_type,
|
|
253
265
|
breaking: is_breaking,
|
|
254
|
-
has_changesets: true
|
|
266
|
+
has_changesets: true
|
|
255
267
|
});
|
|
256
268
|
}
|
|
257
269
|
}
|
|
@@ -272,10 +284,10 @@ export const generate_publishing_plan = async (
|
|
|
272
284
|
|
|
273
285
|
// Recalculate dependency updates based on current predicted versions
|
|
274
286
|
// (breaking_cascades not needed during iteration, only calculated at the end)
|
|
275
|
-
const {dependency_updates} = calculate_dependency_updates(
|
|
287
|
+
const { dependency_updates } = calculate_dependency_updates(
|
|
276
288
|
repos,
|
|
277
289
|
predicted_versions,
|
|
278
|
-
breaking_packages
|
|
290
|
+
breaking_packages
|
|
279
291
|
);
|
|
280
292
|
|
|
281
293
|
// Process packages to check for bump escalation and auto-generated changesets
|
|
@@ -290,7 +302,7 @@ export const generate_publishing_plan = async (
|
|
|
290
302
|
const required_bump = get_required_bump_for_dependencies(
|
|
291
303
|
repo,
|
|
292
304
|
dependency_updates,
|
|
293
|
-
breaking_packages
|
|
305
|
+
breaking_packages
|
|
294
306
|
);
|
|
295
307
|
|
|
296
308
|
// Find triggering dependency for verbose output
|
|
@@ -300,7 +312,7 @@ export const generate_publishing_plan = async (
|
|
|
300
312
|
(u) =>
|
|
301
313
|
u.dependent_package === pkg_name &&
|
|
302
314
|
(u.type === 'dependencies' || u.type === 'peerDependencies') &&
|
|
303
|
-
breaking_packages.has(u.updated_dependency)
|
|
315
|
+
breaking_packages.has(u.updated_dependency)
|
|
304
316
|
);
|
|
305
317
|
if (relevant_updates.length > 0) {
|
|
306
318
|
triggering_dep = `${relevant_updates[0]!.updated_dependency} BREAKING`;
|
|
@@ -325,7 +337,7 @@ export const generate_publishing_plan = async (
|
|
|
325
337
|
// Capture verbose data before updating
|
|
326
338
|
if (verbose) {
|
|
327
339
|
const changeset_detail = verbose_changeset_details.find(
|
|
328
|
-
(d) => d.package_name === pkg_name
|
|
340
|
+
(d) => d.package_name === pkg_name
|
|
329
341
|
);
|
|
330
342
|
verbose_iteration_packages.push({
|
|
331
343
|
name: pkg_name,
|
|
@@ -335,7 +347,7 @@ export const generate_publishing_plan = async (
|
|
|
335
347
|
triggering_dep,
|
|
336
348
|
action: 'escalation',
|
|
337
349
|
version_to: new_version,
|
|
338
|
-
is_breaking: is_breaking_change(old_version, required_bump)
|
|
350
|
+
is_breaking: is_breaking_change(old_version, required_bump)
|
|
339
351
|
});
|
|
340
352
|
}
|
|
341
353
|
|
|
@@ -376,7 +388,7 @@ export const generate_publishing_plan = async (
|
|
|
376
388
|
triggering_dep,
|
|
377
389
|
action: 'auto_changeset',
|
|
378
390
|
version_to: new_version,
|
|
379
|
-
is_breaking
|
|
391
|
+
is_breaking
|
|
380
392
|
});
|
|
381
393
|
}
|
|
382
394
|
|
|
@@ -391,7 +403,7 @@ export const generate_publishing_plan = async (
|
|
|
391
403
|
bump_type: required_bump,
|
|
392
404
|
breaking: is_breaking,
|
|
393
405
|
has_changesets: false,
|
|
394
|
-
will_generate_changeset: true
|
|
406
|
+
will_generate_changeset: true
|
|
395
407
|
});
|
|
396
408
|
|
|
397
409
|
// Update predicted versions
|
|
@@ -405,7 +417,7 @@ export const generate_publishing_plan = async (
|
|
|
405
417
|
verbose_iterations.push({
|
|
406
418
|
iteration,
|
|
407
419
|
packages: verbose_iteration_packages,
|
|
408
|
-
new_changes: verbose_new_changes
|
|
420
|
+
new_changes: verbose_new_changes
|
|
409
421
|
});
|
|
410
422
|
}
|
|
411
423
|
}
|
|
@@ -416,10 +428,10 @@ export const generate_publishing_plan = async (
|
|
|
416
428
|
const pending_packages: Array<string> = [];
|
|
417
429
|
|
|
418
430
|
// Recalculate one more time to see what's pending
|
|
419
|
-
const {dependency_updates: pending_updates} = calculate_dependency_updates(
|
|
431
|
+
const { dependency_updates: pending_updates } = calculate_dependency_updates(
|
|
420
432
|
repos,
|
|
421
433
|
predicted_versions,
|
|
422
|
-
breaking_packages
|
|
434
|
+
breaking_packages
|
|
423
435
|
);
|
|
424
436
|
|
|
425
437
|
for (const repo of repos) {
|
|
@@ -428,7 +440,7 @@ export const generate_publishing_plan = async (
|
|
|
428
440
|
const required_bump = get_required_bump_for_dependencies(
|
|
429
441
|
repo,
|
|
430
442
|
pending_updates,
|
|
431
|
-
breaking_packages
|
|
443
|
+
breaking_packages
|
|
432
444
|
);
|
|
433
445
|
|
|
434
446
|
// Check if this package would need processing
|
|
@@ -450,22 +462,22 @@ export const generate_publishing_plan = async (
|
|
|
450
462
|
warnings.push(
|
|
451
463
|
`Reached maximum iterations (${GITOPS_MAX_ITERATIONS_DEFAULT}) without full convergence - ` +
|
|
452
464
|
`${pending_count} package(s) may still need processing: ${pending_packages.join(', ')}. ` +
|
|
453
|
-
`Estimated ${estimated_iterations} more iteration(s) needed
|
|
465
|
+
`Estimated ${estimated_iterations} more iteration(s) needed.`
|
|
454
466
|
);
|
|
455
467
|
}
|
|
456
468
|
|
|
457
469
|
// Final dependency updates calculation after convergence
|
|
458
|
-
const {dependency_updates, breaking_cascades} = calculate_dependency_updates(
|
|
470
|
+
const { dependency_updates, breaking_cascades } = calculate_dependency_updates(
|
|
459
471
|
repos,
|
|
460
472
|
predicted_versions,
|
|
461
|
-
breaking_packages
|
|
473
|
+
breaking_packages
|
|
462
474
|
);
|
|
463
475
|
|
|
464
476
|
// Identify packages with no changes
|
|
465
477
|
for (const repo of repos) {
|
|
466
478
|
const has_version_change = version_changes.some((vc) => vc.package_name === repo.library.name);
|
|
467
479
|
if (!has_version_change) {
|
|
468
|
-
const has_result = await ops.has_changesets({repo});
|
|
480
|
+
const has_result = await ops.has_changesets({ repo });
|
|
469
481
|
if (has_result.ok && !has_result.value) {
|
|
470
482
|
info.push(repo.library.name);
|
|
471
483
|
}
|
|
@@ -478,11 +490,11 @@ export const generate_publishing_plan = async (
|
|
|
478
490
|
// Build propagation chains from breaking_cascades
|
|
479
491
|
const propagation_chains: Array<VerbosePropagationChain> = [];
|
|
480
492
|
for (const [source, affected] of breaking_cascades) {
|
|
481
|
-
const chain: Array<{pkg: string; dep_type: 'prod' | 'peer'; action: string}> = [];
|
|
493
|
+
const chain: Array<{ pkg: string; dep_type: 'prod' | 'peer'; action: string }> = [];
|
|
482
494
|
for (const pkg of affected) {
|
|
483
495
|
// Determine dep type and action
|
|
484
496
|
const update = dependency_updates.find(
|
|
485
|
-
(u) => u.dependent_package === pkg && u.updated_dependency === source
|
|
497
|
+
(u) => u.dependent_package === pkg && u.updated_dependency === source
|
|
486
498
|
);
|
|
487
499
|
const dep_type: 'prod' | 'peer' = update?.type === 'peerDependencies' ? 'peer' : 'prod';
|
|
488
500
|
const version_change = version_changes.find((vc) => vc.package_name === pkg);
|
|
@@ -492,16 +504,16 @@ export const generate_publishing_plan = async (
|
|
|
492
504
|
} else if (version_change?.needs_bump_escalation) {
|
|
493
505
|
action = 'bump escalation';
|
|
494
506
|
}
|
|
495
|
-
chain.push({pkg, dep_type, action});
|
|
507
|
+
chain.push({ pkg, dep_type, action });
|
|
496
508
|
}
|
|
497
509
|
if (chain.length > 0) {
|
|
498
|
-
propagation_chains.push({source, chain});
|
|
510
|
+
propagation_chains.push({ source, chain });
|
|
499
511
|
}
|
|
500
512
|
}
|
|
501
513
|
|
|
502
514
|
// Build graph summary
|
|
503
|
-
const prod_peer_edges: Array<{from: string; to: string; type: 'prod' | 'peer'}> = [];
|
|
504
|
-
const dev_edges: Array<{from: string; to: string}> = [];
|
|
515
|
+
const prod_peer_edges: Array<{ from: string; to: string; type: 'prod' | 'peer' }> = [];
|
|
516
|
+
const dev_edges: Array<{ from: string; to: string }> = [];
|
|
505
517
|
let internal_dep_count = 0;
|
|
506
518
|
|
|
507
519
|
for (const [pkg_name, node] of graph.nodes) {
|
|
@@ -510,12 +522,12 @@ export const generate_publishing_plan = async (
|
|
|
510
522
|
if (graph.nodes.has(dep_name)) {
|
|
511
523
|
internal_dep_count++;
|
|
512
524
|
if (spec.type === 'dev') {
|
|
513
|
-
dev_edges.push({from: pkg_name, to: dep_name});
|
|
525
|
+
dev_edges.push({ from: pkg_name, to: dep_name });
|
|
514
526
|
} else {
|
|
515
527
|
prod_peer_edges.push({
|
|
516
528
|
from: pkg_name,
|
|
517
529
|
to: dep_name,
|
|
518
|
-
type: spec.type === 'peer' ? 'peer' : 'prod'
|
|
530
|
+
type: spec.type === 'peer' ? 'peer' : 'prod'
|
|
519
531
|
});
|
|
520
532
|
}
|
|
521
533
|
}
|
|
@@ -532,9 +544,9 @@ export const generate_publishing_plan = async (
|
|
|
532
544
|
prod_peer_edges,
|
|
533
545
|
dev_edges,
|
|
534
546
|
prod_cycle_count: production_cycles.length,
|
|
535
|
-
dev_cycle_count: dev_cycles.length
|
|
547
|
+
dev_cycle_count: dev_cycles.length
|
|
536
548
|
},
|
|
537
|
-
total_iterations: iteration
|
|
549
|
+
total_iterations: iteration
|
|
538
550
|
};
|
|
539
551
|
}
|
|
540
552
|
|
|
@@ -546,6 +558,6 @@ export const generate_publishing_plan = async (
|
|
|
546
558
|
warnings,
|
|
547
559
|
info,
|
|
548
560
|
errors,
|
|
549
|
-
verbose_data
|
|
561
|
+
verbose_data
|
|
550
562
|
};
|
|
551
563
|
};
|