@fuzdev/fuz_gitops 0.57.0
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/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/ModulesDetail.svelte +180 -0
- package/dist/ModulesDetail.svelte.d.ts +10 -0
- package/dist/ModulesDetail.svelte.d.ts.map +1 -0
- package/dist/ModulesNav.svelte +43 -0
- package/dist/ModulesNav.svelte.d.ts +11 -0
- package/dist/ModulesNav.svelte.d.ts.map +1 -0
- package/dist/ModulesPage.svelte +50 -0
- package/dist/ModulesPage.svelte.d.ts +9 -0
- package/dist/ModulesPage.svelte.d.ts.map +1 -0
- package/dist/PageFooter.svelte +15 -0
- package/dist/PageFooter.svelte.d.ts +19 -0
- package/dist/PageFooter.svelte.d.ts.map +1 -0
- package/dist/PageHeader.svelte +35 -0
- package/dist/PageHeader.svelte.d.ts +19 -0
- package/dist/PageHeader.svelte.d.ts.map +1 -0
- package/dist/PullRequestsDetail.svelte +53 -0
- package/dist/PullRequestsDetail.svelte.d.ts +10 -0
- package/dist/PullRequestsDetail.svelte.d.ts.map +1 -0
- package/dist/PullRequestsPage.svelte +47 -0
- package/dist/PullRequestsPage.svelte.d.ts +11 -0
- package/dist/PullRequestsPage.svelte.d.ts.map +1 -0
- package/dist/ReposTable.svelte +189 -0
- package/dist/ReposTable.svelte.d.ts +9 -0
- package/dist/ReposTable.svelte.d.ts.map +1 -0
- package/dist/ReposTree.svelte +88 -0
- package/dist/ReposTree.svelte.d.ts +11 -0
- package/dist/ReposTree.svelte.d.ts.map +1 -0
- package/dist/ReposTreeNav.svelte +55 -0
- package/dist/ReposTreeNav.svelte.d.ts +11 -0
- package/dist/ReposTreeNav.svelte.d.ts.map +1 -0
- package/dist/TablePage.svelte +46 -0
- package/dist/TablePage.svelte.d.ts +9 -0
- package/dist/TablePage.svelte.d.ts.map +1 -0
- package/dist/TreeItemPage.svelte +75 -0
- package/dist/TreeItemPage.svelte.d.ts +10 -0
- package/dist/TreeItemPage.svelte.d.ts.map +1 -0
- package/dist/TreePage.svelte +64 -0
- package/dist/TreePage.svelte.d.ts +9 -0
- package/dist/TreePage.svelte.d.ts.map +1 -0
- package/dist/changeset_generator.d.ts +38 -0
- package/dist/changeset_generator.d.ts.map +1 -0
- package/dist/changeset_generator.js +110 -0
- package/dist/changeset_reader.d.ts +75 -0
- package/dist/changeset_reader.d.ts.map +1 -0
- package/dist/changeset_reader.js +167 -0
- package/dist/constants.d.ts +9 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +8 -0
- package/dist/dependency_graph.d.ts +120 -0
- package/dist/dependency_graph.d.ts.map +1 -0
- package/dist/dependency_graph.js +341 -0
- package/dist/dependency_updater.d.ts +46 -0
- package/dist/dependency_updater.d.ts.map +1 -0
- package/dist/dependency_updater.js +213 -0
- package/dist/fetch_repo_data.d.ts +19 -0
- package/dist/fetch_repo_data.d.ts.map +1 -0
- package/dist/fetch_repo_data.js +49 -0
- package/dist/fs_fetch_value_cache.d.ts +24 -0
- package/dist/fs_fetch_value_cache.d.ts.map +1 -0
- package/dist/fs_fetch_value_cache.js +61 -0
- package/dist/git_operations.d.ts +54 -0
- package/dist/git_operations.d.ts.map +1 -0
- package/dist/git_operations.js +144 -0
- package/dist/github.d.ts +91 -0
- package/dist/github.d.ts.map +1 -0
- package/dist/github.js +94 -0
- package/dist/github_helpers.d.ts +10 -0
- package/dist/github_helpers.d.ts.map +1 -0
- package/dist/github_helpers.js +13 -0
- package/dist/gitops_analyze.task.d.ts +17 -0
- package/dist/gitops_analyze.task.d.ts.map +1 -0
- package/dist/gitops_analyze.task.js +188 -0
- package/dist/gitops_config.d.ts +56 -0
- package/dist/gitops_config.d.ts.map +1 -0
- package/dist/gitops_config.js +63 -0
- package/dist/gitops_plan.task.d.ts +28 -0
- package/dist/gitops_plan.task.d.ts.map +1 -0
- package/dist/gitops_plan.task.js +217 -0
- package/dist/gitops_publish.task.d.ts +29 -0
- package/dist/gitops_publish.task.d.ts.map +1 -0
- package/dist/gitops_publish.task.js +178 -0
- package/dist/gitops_sync.task.d.ts +18 -0
- package/dist/gitops_sync.task.d.ts.map +1 -0
- package/dist/gitops_sync.task.js +95 -0
- package/dist/gitops_task_helpers.d.ts +63 -0
- package/dist/gitops_task_helpers.d.ts.map +1 -0
- package/dist/gitops_task_helpers.js +84 -0
- package/dist/gitops_validate.task.d.ts +12 -0
- package/dist/gitops_validate.task.d.ts.map +1 -0
- package/dist/gitops_validate.task.js +210 -0
- package/dist/graph_validation.d.ts +39 -0
- package/dist/graph_validation.d.ts.map +1 -0
- package/dist/graph_validation.js +79 -0
- package/dist/local_repo.d.ts +84 -0
- package/dist/local_repo.d.ts.map +1 -0
- package/dist/local_repo.js +213 -0
- package/dist/log_helpers.d.ts +43 -0
- package/dist/log_helpers.d.ts.map +1 -0
- package/dist/log_helpers.js +98 -0
- package/dist/multi_repo_publisher.d.ts +34 -0
- package/dist/multi_repo_publisher.d.ts.map +1 -0
- package/dist/multi_repo_publisher.js +364 -0
- package/dist/npm_install_helpers.d.ts +23 -0
- package/dist/npm_install_helpers.d.ts.map +1 -0
- package/dist/npm_install_helpers.js +60 -0
- package/dist/npm_registry.d.ts +46 -0
- package/dist/npm_registry.d.ts.map +1 -0
- package/dist/npm_registry.js +96 -0
- package/dist/operations.d.ts +409 -0
- package/dist/operations.d.ts.map +1 -0
- package/dist/operations.js +34 -0
- package/dist/operations_defaults.d.ts +19 -0
- package/dist/operations_defaults.d.ts.map +1 -0
- package/dist/operations_defaults.js +279 -0
- package/dist/output_helpers.d.ts +27 -0
- package/dist/output_helpers.d.ts.map +1 -0
- package/dist/output_helpers.js +39 -0
- package/dist/paths.d.ts +11 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +10 -0
- package/dist/preflight_checks.d.ts +47 -0
- package/dist/preflight_checks.d.ts.map +1 -0
- package/dist/preflight_checks.js +181 -0
- package/dist/publishing_plan.d.ts +100 -0
- package/dist/publishing_plan.d.ts.map +1 -0
- package/dist/publishing_plan.js +353 -0
- package/dist/publishing_plan_helpers.d.ts +30 -0
- package/dist/publishing_plan_helpers.d.ts.map +1 -0
- package/dist/publishing_plan_helpers.js +112 -0
- package/dist/publishing_plan_logging.d.ts +18 -0
- package/dist/publishing_plan_logging.d.ts.map +1 -0
- package/dist/publishing_plan_logging.js +342 -0
- package/dist/repo.svelte.d.ts +52 -0
- package/dist/repo.svelte.d.ts.map +1 -0
- package/dist/repo.svelte.js +70 -0
- package/dist/repo_ops.d.ts +57 -0
- package/dist/repo_ops.d.ts.map +1 -0
- package/dist/repo_ops.js +167 -0
- package/dist/resolved_gitops_config.d.ts +9 -0
- package/dist/resolved_gitops_config.d.ts.map +1 -0
- package/dist/resolved_gitops_config.js +12 -0
- package/dist/semver.d.ts +24 -0
- package/dist/semver.d.ts.map +1 -0
- package/dist/semver.js +140 -0
- package/dist/serialization_types.d.ts +57 -0
- package/dist/serialization_types.d.ts.map +1 -0
- package/dist/serialization_types.js +40 -0
- package/dist/version_utils.d.ts +48 -0
- package/dist/version_utils.d.ts.map +1 -0
- package/dist/version_utils.js +125 -0
- package/package.json +107 -0
- package/src/lib/changeset_generator.ts +162 -0
- package/src/lib/changeset_reader.ts +218 -0
- package/src/lib/constants.ts +8 -0
- package/src/lib/dependency_graph.ts +423 -0
- package/src/lib/dependency_updater.ts +297 -0
- package/src/lib/fetch_repo_data.ts +64 -0
- package/src/lib/fs_fetch_value_cache.ts +75 -0
- package/src/lib/git_operations.ts +208 -0
- package/src/lib/github.ts +128 -0
- package/src/lib/github_helpers.ts +31 -0
- package/src/lib/gitops_analyze.task.ts +261 -0
- package/src/lib/gitops_config.ts +123 -0
- package/src/lib/gitops_plan.task.ts +272 -0
- package/src/lib/gitops_publish.task.ts +227 -0
- package/src/lib/gitops_sync.task.ts +109 -0
- package/src/lib/gitops_task_helpers.ts +126 -0
- package/src/lib/gitops_validate.task.ts +248 -0
- package/src/lib/graph_validation.ts +109 -0
- package/src/lib/local_repo.ts +359 -0
- package/src/lib/log_helpers.ts +147 -0
- package/src/lib/multi_repo_publisher.ts +464 -0
- package/src/lib/npm_install_helpers.ts +85 -0
- package/src/lib/npm_registry.ts +143 -0
- package/src/lib/operations.ts +334 -0
- package/src/lib/operations_defaults.ts +335 -0
- package/src/lib/output_helpers.ts +64 -0
- package/src/lib/paths.ts +11 -0
- package/src/lib/preflight_checks.ts +269 -0
- package/src/lib/publishing_plan.ts +531 -0
- package/src/lib/publishing_plan_helpers.ts +145 -0
- package/src/lib/publishing_plan_logging.ts +470 -0
- package/src/lib/repo.svelte.ts +95 -0
- package/src/lib/repo_ops.ts +213 -0
- package/src/lib/resolved_gitops_config.ts +27 -0
- package/src/lib/semver.ts +166 -0
- package/src/lib/serialization_types.ts +90 -0
- package/src/lib/version_utils.ts +150 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logging and formatting functions for publishing plans.
|
|
3
|
+
*
|
|
4
|
+
* Includes both regular plan output and verbose diagnostic sections.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type {Logger} from '@fuzdev/fuz_util/log.js';
|
|
8
|
+
import {styleText as st} from 'node:util';
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
PublishingPlan,
|
|
12
|
+
VersionChange,
|
|
13
|
+
DependencyUpdate,
|
|
14
|
+
VerboseData,
|
|
15
|
+
VerboseChangesetDetail,
|
|
16
|
+
VerboseIteration,
|
|
17
|
+
VerbosePropagationChain,
|
|
18
|
+
VerboseGraphSummary,
|
|
19
|
+
} from './publishing_plan.js';
|
|
20
|
+
|
|
21
|
+
export interface LogPlanOptions {
|
|
22
|
+
verbose?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const SEPARATOR = '────────────────────────────────────────';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Logs a section header with separators.
|
|
29
|
+
*/
|
|
30
|
+
const log_section_header = (title: string, log: Logger): void => {
|
|
31
|
+
log.info(st('dim', SEPARATOR));
|
|
32
|
+
log.info(st('dim', title));
|
|
33
|
+
log.info(st('dim', SEPARATOR));
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Formats a dependency update as diff-style output.
|
|
38
|
+
* Shows - old / + new for the dependency version.
|
|
39
|
+
*/
|
|
40
|
+
const format_dep_diff = (dep_name: string, current: string, next: string): Array<string> => {
|
|
41
|
+
return [
|
|
42
|
+
st('red', ` - "${dep_name}": "${current}"`),
|
|
43
|
+
st('green', ` + "${dep_name}": "${next}"`),
|
|
44
|
+
];
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Gets dependency updates for a specific package, grouped by dependency name.
|
|
49
|
+
*/
|
|
50
|
+
const get_updates_for_package = (
|
|
51
|
+
pkg_name: string,
|
|
52
|
+
dependency_updates: Array<DependencyUpdate>,
|
|
53
|
+
): Map<string, Array<DependencyUpdate>> => {
|
|
54
|
+
const updates: Map<string, Array<DependencyUpdate>> = new Map();
|
|
55
|
+
for (const update of dependency_updates) {
|
|
56
|
+
if (update.dependent_package === pkg_name) {
|
|
57
|
+
const dep_updates = updates.get(update.updated_dependency) || [];
|
|
58
|
+
dep_updates.push(update);
|
|
59
|
+
updates.set(update.updated_dependency, dep_updates);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return updates;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Logs a single version change with diff-style dependency updates.
|
|
67
|
+
*/
|
|
68
|
+
const log_version_change_with_diffs = (
|
|
69
|
+
change: VersionChange,
|
|
70
|
+
index: number,
|
|
71
|
+
total: number,
|
|
72
|
+
dependency_updates: Array<DependencyUpdate>,
|
|
73
|
+
breaking_cascades: Map<string, Array<string>>,
|
|
74
|
+
log: Logger,
|
|
75
|
+
): void => {
|
|
76
|
+
const breaking_indicator = change.breaking ? st('red', ' BREAKING') : '';
|
|
77
|
+
const position = st('dim', `[${index + 1}/${total}]`);
|
|
78
|
+
|
|
79
|
+
// Determine scenario label
|
|
80
|
+
let scenario_label = '';
|
|
81
|
+
if (change.needs_bump_escalation) {
|
|
82
|
+
scenario_label = st('yellow', ` [${change.existing_bump} → ${change.required_bump}]`);
|
|
83
|
+
} else if (change.will_generate_changeset) {
|
|
84
|
+
scenario_label = st('cyan', ' [auto-changeset]');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Main version line
|
|
88
|
+
log.info(
|
|
89
|
+
`${position} ${change.package_name}: ${change.from} → ${st('green', change.to)} ` +
|
|
90
|
+
`(${change.bump_type})${scenario_label}${breaking_indicator}`,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// Show escalation reason
|
|
94
|
+
if (change.needs_bump_escalation) {
|
|
95
|
+
log.info(
|
|
96
|
+
st(
|
|
97
|
+
'dim',
|
|
98
|
+
` changesets specify ${change.existing_bump}, dependencies require ${change.required_bump}`,
|
|
99
|
+
),
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Show trigger reason for auto-changesets
|
|
104
|
+
if (change.will_generate_changeset) {
|
|
105
|
+
// Find what triggered this
|
|
106
|
+
const triggers: Array<string> = [];
|
|
107
|
+
for (const [pkg, affected] of breaking_cascades) {
|
|
108
|
+
if (affected.includes(change.package_name)) {
|
|
109
|
+
triggers.push(`${pkg} (BREAKING)`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (triggers.length > 0) {
|
|
113
|
+
log.info(st('dim', ` triggered by: ${triggers.join(', ')}`));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Show dependency diffs for this package
|
|
118
|
+
const pkg_updates = get_updates_for_package(change.package_name, dependency_updates);
|
|
119
|
+
if (pkg_updates.size > 0) {
|
|
120
|
+
for (const [dep_name, updates] of pkg_updates) {
|
|
121
|
+
if (updates.length === 0) continue;
|
|
122
|
+
const update = updates[0]!;
|
|
123
|
+
for (const line of format_dep_diff(dep_name, update.current_version, update.new_version)) {
|
|
124
|
+
log.info(line);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Logs a complete publishing plan to the console.
|
|
132
|
+
*
|
|
133
|
+
* Displays errors, publishing order, version changes grouped by scenario,
|
|
134
|
+
* dependency-only updates, warnings, and a summary.
|
|
135
|
+
*/
|
|
136
|
+
export const log_publishing_plan = (
|
|
137
|
+
plan: PublishingPlan,
|
|
138
|
+
log: Logger,
|
|
139
|
+
options: LogPlanOptions = {},
|
|
140
|
+
): void => {
|
|
141
|
+
const {
|
|
142
|
+
publishing_order,
|
|
143
|
+
version_changes,
|
|
144
|
+
dependency_updates,
|
|
145
|
+
breaking_cascades,
|
|
146
|
+
warnings,
|
|
147
|
+
info,
|
|
148
|
+
errors,
|
|
149
|
+
} = plan;
|
|
150
|
+
|
|
151
|
+
// Errors first (blocking issues)
|
|
152
|
+
if (errors.length > 0) {
|
|
153
|
+
log.error(st('red', 'Errors:'));
|
|
154
|
+
for (const error of errors) {
|
|
155
|
+
log.error(` ${error}`);
|
|
156
|
+
}
|
|
157
|
+
log.info('');
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Publishing order
|
|
161
|
+
if (publishing_order.length > 0) {
|
|
162
|
+
log.info(st('cyan', 'Publishing Order:'));
|
|
163
|
+
log.info(` ${publishing_order.join(' → ')}`);
|
|
164
|
+
log.info('');
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Version changes with diffs
|
|
168
|
+
if (version_changes.length > 0) {
|
|
169
|
+
// Sort by publishing order
|
|
170
|
+
const ordered_changes = [...version_changes].sort((a, b) => {
|
|
171
|
+
const idx_a = publishing_order.indexOf(a.package_name);
|
|
172
|
+
const idx_b = publishing_order.indexOf(b.package_name);
|
|
173
|
+
return idx_a - idx_b;
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Separate into groups for headers
|
|
177
|
+
const with_changesets = ordered_changes.filter(
|
|
178
|
+
(vc) => vc.has_changesets && !vc.needs_bump_escalation,
|
|
179
|
+
);
|
|
180
|
+
const with_escalation = ordered_changes.filter((vc) => vc.needs_bump_escalation);
|
|
181
|
+
const with_auto_changesets = ordered_changes.filter((vc) => vc.will_generate_changeset);
|
|
182
|
+
|
|
183
|
+
// Log each group with diff-style output
|
|
184
|
+
if (with_changesets.length > 0) {
|
|
185
|
+
log.info(st('cyan', 'Version Changes (from changesets):'));
|
|
186
|
+
for (const change of with_changesets) {
|
|
187
|
+
const idx = ordered_changes.indexOf(change);
|
|
188
|
+
log_version_change_with_diffs(
|
|
189
|
+
change,
|
|
190
|
+
idx,
|
|
191
|
+
ordered_changes.length,
|
|
192
|
+
dependency_updates,
|
|
193
|
+
breaking_cascades,
|
|
194
|
+
log,
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
log.info('');
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (with_escalation.length > 0) {
|
|
201
|
+
log.info(st('yellow', 'Version Changes (bump escalation):'));
|
|
202
|
+
for (const change of with_escalation) {
|
|
203
|
+
const idx = ordered_changes.indexOf(change);
|
|
204
|
+
log_version_change_with_diffs(
|
|
205
|
+
change,
|
|
206
|
+
idx,
|
|
207
|
+
ordered_changes.length,
|
|
208
|
+
dependency_updates,
|
|
209
|
+
breaking_cascades,
|
|
210
|
+
log,
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
log.info('');
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if (with_auto_changesets.length > 0) {
|
|
217
|
+
log.info(st('cyan', 'Version Changes (auto-generated):'));
|
|
218
|
+
for (const change of with_auto_changesets) {
|
|
219
|
+
const idx = ordered_changes.indexOf(change);
|
|
220
|
+
log_version_change_with_diffs(
|
|
221
|
+
change,
|
|
222
|
+
idx,
|
|
223
|
+
ordered_changes.length,
|
|
224
|
+
dependency_updates,
|
|
225
|
+
breaking_cascades,
|
|
226
|
+
log,
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
log.info('');
|
|
230
|
+
}
|
|
231
|
+
} else {
|
|
232
|
+
log.info(st('dim', 'No packages to publish'));
|
|
233
|
+
log.info('');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Dependency-only updates (no republish) - packages getting dep updates but not publishing
|
|
237
|
+
const dep_only_packages: Set<string> = new Set();
|
|
238
|
+
for (const update of dependency_updates) {
|
|
239
|
+
const has_version_change = version_changes.some(
|
|
240
|
+
(vc) => vc.package_name === update.dependent_package,
|
|
241
|
+
);
|
|
242
|
+
if (!has_version_change) {
|
|
243
|
+
dep_only_packages.add(update.dependent_package);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (dep_only_packages.size > 0) {
|
|
248
|
+
log.info(st('dim', 'Dependency Updates (no republish):'));
|
|
249
|
+
for (const pkg of dep_only_packages) {
|
|
250
|
+
log.info(st('dim', ` ${pkg}:`));
|
|
251
|
+
const pkg_updates = get_updates_for_package(pkg, dependency_updates);
|
|
252
|
+
for (const [dep_name, updates] of pkg_updates) {
|
|
253
|
+
if (updates.length === 0) continue;
|
|
254
|
+
const update = updates[0]!;
|
|
255
|
+
// Use dim styling for non-publishing packages
|
|
256
|
+
log.info(st('dim', ` - "${dep_name}": "${update.current_version}"`));
|
|
257
|
+
log.info(st('dim', ` + "${dep_name}": "${update.new_version}"`));
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
log.info('');
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Warnings
|
|
264
|
+
if (warnings.length > 0) {
|
|
265
|
+
log.warn(st('yellow', 'Warnings:'));
|
|
266
|
+
for (const warning of warnings) {
|
|
267
|
+
log.warn(` ${warning}`);
|
|
268
|
+
}
|
|
269
|
+
log.info('');
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Info (packages with no changes)
|
|
273
|
+
if (info.length > 0) {
|
|
274
|
+
log.info(st('dim', `No changes: ${info.join(', ')}`));
|
|
275
|
+
log.info('');
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Summary
|
|
279
|
+
const major_count = version_changes.filter((vc) => vc.breaking).length;
|
|
280
|
+
const auto_count = version_changes.filter((vc) => vc.will_generate_changeset).length;
|
|
281
|
+
log.info(st('cyan', 'Summary:'));
|
|
282
|
+
log.info(` ${version_changes.length} packages to publish`);
|
|
283
|
+
if (auto_count > 0) {
|
|
284
|
+
log.info(` ${auto_count} auto-generated changesets`);
|
|
285
|
+
}
|
|
286
|
+
if (major_count > 0) {
|
|
287
|
+
log.info(st('yellow', ` ${major_count} breaking changes`));
|
|
288
|
+
}
|
|
289
|
+
log.info(` ${dep_only_packages.size} packages with dependency-only updates`);
|
|
290
|
+
if (warnings.length > 0) {
|
|
291
|
+
log.info(st('yellow', ` ${warnings.length} warnings`));
|
|
292
|
+
}
|
|
293
|
+
if (errors.length > 0) {
|
|
294
|
+
log.info(st('red', ` ${errors.length} errors`));
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Verbose output
|
|
298
|
+
if (options.verbose && plan.verbose_data) {
|
|
299
|
+
log_verbose(plan.verbose_data, log);
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
// ============================================================================
|
|
304
|
+
// Verbose logging functions
|
|
305
|
+
// ============================================================================
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Logs all verbose sections in order.
|
|
309
|
+
*/
|
|
310
|
+
const log_verbose = (data: VerboseData, log: Logger): void => {
|
|
311
|
+
log.info(''); // Blank line before verbose sections
|
|
312
|
+
|
|
313
|
+
log_verbose_changeset_details(data.changeset_details, log);
|
|
314
|
+
log_verbose_iteration_details(data.iterations, data.total_iterations, log);
|
|
315
|
+
log_verbose_propagation_chains(data.propagation_chains, log);
|
|
316
|
+
log_verbose_graph_summary(data.graph_summary, log);
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Logs changeset file details per package.
|
|
321
|
+
*/
|
|
322
|
+
const log_verbose_changeset_details = (
|
|
323
|
+
details: Array<VerboseChangesetDetail>,
|
|
324
|
+
log: Logger,
|
|
325
|
+
): void => {
|
|
326
|
+
if (details.length === 0) return;
|
|
327
|
+
|
|
328
|
+
log_section_header('Changeset Details', log);
|
|
329
|
+
|
|
330
|
+
for (const pkg of details) {
|
|
331
|
+
log.info(st('dim', `${pkg.package_name}:`));
|
|
332
|
+
for (const file of pkg.files) {
|
|
333
|
+
const summary_text = file.summary ? `: "${file.summary}"` : '';
|
|
334
|
+
log.info(st('dim', ` .changeset/${file.filename} (${file.bump_type})${summary_text}`));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
log.info('');
|
|
338
|
+
};
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* Logs fixed-point iteration details.
|
|
342
|
+
*/
|
|
343
|
+
const log_verbose_iteration_details = (
|
|
344
|
+
iterations: Array<VerboseIteration>,
|
|
345
|
+
total: number,
|
|
346
|
+
log: Logger,
|
|
347
|
+
): void => {
|
|
348
|
+
if (iterations.length === 0) return;
|
|
349
|
+
|
|
350
|
+
log_section_header('Fixed-Point Iteration', log);
|
|
351
|
+
|
|
352
|
+
for (const iter of iterations) {
|
|
353
|
+
if (iter.new_changes === 0 && iter.packages.length === 0) {
|
|
354
|
+
log.info(st('dim', `Iteration ${iter.iteration}:`));
|
|
355
|
+
log.info(st('dim', ' No new changes'));
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
log.info(st('dim', `Iteration ${iter.iteration}:`));
|
|
360
|
+
for (const pkg of iter.packages) {
|
|
361
|
+
const parts: Array<string> = [];
|
|
362
|
+
|
|
363
|
+
// Changeset info
|
|
364
|
+
if (pkg.changeset_count > 0) {
|
|
365
|
+
parts.push(`changesets=${pkg.changeset_count}`);
|
|
366
|
+
if (pkg.bump_from_changesets) {
|
|
367
|
+
parts.push(`bump=${pkg.bump_from_changesets}`);
|
|
368
|
+
}
|
|
369
|
+
} else {
|
|
370
|
+
parts.push('no changesets');
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Required bump from deps
|
|
374
|
+
if (pkg.required_bump && pkg.triggering_dep) {
|
|
375
|
+
parts.push(`required=${pkg.required_bump} (from ${pkg.triggering_dep})`);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Action
|
|
379
|
+
if (pkg.action === 'auto_changeset') {
|
|
380
|
+
parts.push('→ auto-generate');
|
|
381
|
+
} else if (pkg.action === 'escalation') {
|
|
382
|
+
parts.push('→ escalation');
|
|
383
|
+
} else if (pkg.action === 'publish') {
|
|
384
|
+
// Regular publish, no special label needed
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Version
|
|
388
|
+
if (pkg.version_to) {
|
|
389
|
+
const breaking_label = pkg.is_breaking ? ' (BREAKING)' : '';
|
|
390
|
+
parts.push(`→ ${pkg.version_to}${breaking_label}`);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
log.info(st('dim', ` ${pkg.name}: ${parts.join(', ')}`));
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (iter.new_changes > 0) {
|
|
397
|
+
log.info(st('dim', ` New changes: ${iter.new_changes}`));
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
log.info(st('dim', `Converged after ${total} iteration(s)`));
|
|
402
|
+
log.info('');
|
|
403
|
+
};
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Logs breaking change propagation chains as tree structure.
|
|
407
|
+
*/
|
|
408
|
+
const log_verbose_propagation_chains = (
|
|
409
|
+
chains: Array<VerbosePropagationChain>,
|
|
410
|
+
log: Logger,
|
|
411
|
+
): void => {
|
|
412
|
+
if (chains.length === 0) return;
|
|
413
|
+
|
|
414
|
+
log_section_header('Breaking Change Propagation', log);
|
|
415
|
+
|
|
416
|
+
for (const chain of chains) {
|
|
417
|
+
log.info(st('dim', `${chain.source} (source)`));
|
|
418
|
+
|
|
419
|
+
for (let i = 0; i < chain.chain.length; i++) {
|
|
420
|
+
const item = chain.chain[i]!;
|
|
421
|
+
const indent = ' '.repeat(i);
|
|
422
|
+
const connector = '└─';
|
|
423
|
+
log.info(
|
|
424
|
+
st('dim', `${indent}${connector} ${item.pkg} (${item.dep_type} dep) → ${item.action}`),
|
|
425
|
+
);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
log.info('');
|
|
429
|
+
};
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Logs dependency graph summary.
|
|
433
|
+
*/
|
|
434
|
+
const log_verbose_graph_summary = (summary: VerboseGraphSummary, log: Logger): void => {
|
|
435
|
+
log_section_header('Dependency Graph', log);
|
|
436
|
+
|
|
437
|
+
log.info(
|
|
438
|
+
st(
|
|
439
|
+
'dim',
|
|
440
|
+
`${summary.package_count} packages, ${summary.internal_dep_count} internal dependencies`,
|
|
441
|
+
),
|
|
442
|
+
);
|
|
443
|
+
log.info('');
|
|
444
|
+
|
|
445
|
+
// Production/Peer edges
|
|
446
|
+
if (summary.prod_peer_edges.length > 0) {
|
|
447
|
+
log.info(st('dim', 'Production/Peer:'));
|
|
448
|
+
for (const edge of summary.prod_peer_edges) {
|
|
449
|
+
log.info(st('dim', ` ${edge.from} → ${edge.to} (${edge.type})`));
|
|
450
|
+
}
|
|
451
|
+
} else {
|
|
452
|
+
log.info(st('dim', 'Production/Peer: (none)'));
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Dev edges
|
|
456
|
+
if (summary.dev_edges.length > 0) {
|
|
457
|
+
log.info(st('dim', 'Dev:'));
|
|
458
|
+
for (const edge of summary.dev_edges) {
|
|
459
|
+
log.info(st('dim', ` ${edge.from} → ${edge.to}`));
|
|
460
|
+
}
|
|
461
|
+
} else {
|
|
462
|
+
log.info(st('dim', 'Dev: (none)'));
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
log.info('');
|
|
466
|
+
log.info(
|
|
467
|
+
st('dim', `Cycles: ${summary.prod_cycle_count} production, ${summary.dev_cycle_count} dev`),
|
|
468
|
+
);
|
|
469
|
+
log.info('');
|
|
470
|
+
};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import {create_context} from '@fuzdev/fuz_ui/context_helpers.js';
|
|
2
|
+
import type {LibraryJson} from '@fuzdev/fuz_util/library_json.js';
|
|
3
|
+
import type {PackageJson} from '@fuzdev/fuz_util/package_json.js';
|
|
4
|
+
import type {SourceJson} from '@fuzdev/fuz_util/source_json.js';
|
|
5
|
+
import type {Url} from '@fuzdev/fuz_util/url.js';
|
|
6
|
+
import {Library} from '@fuzdev/fuz_ui/library.svelte.js';
|
|
7
|
+
import type {Module} from '@fuzdev/fuz_ui/module.svelte.js';
|
|
8
|
+
|
|
9
|
+
import {GithubCheckRunsItem, type GithubPullRequest} from './github.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Serialized repo data as stored in repos.ts (JSON).
|
|
13
|
+
*/
|
|
14
|
+
export interface RepoJson {
|
|
15
|
+
library_json: LibraryJson;
|
|
16
|
+
check_runs: GithubCheckRunsItem | null;
|
|
17
|
+
pull_requests: Array<GithubPullRequest> | null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Runtime repo with Library composition for package metadata.
|
|
22
|
+
*
|
|
23
|
+
* Wraps a Library instance and adds GitHub-specific data (CI status, PRs).
|
|
24
|
+
* Convenience getters delegate to `this.library.*` for common properties.
|
|
25
|
+
*/
|
|
26
|
+
export class Repo {
|
|
27
|
+
readonly library: Library;
|
|
28
|
+
check_runs: GithubCheckRunsItem | null;
|
|
29
|
+
pull_requests: Array<GithubPullRequest> | null;
|
|
30
|
+
|
|
31
|
+
// Convenience getters delegating to library
|
|
32
|
+
get name(): string {
|
|
33
|
+
return this.library.name;
|
|
34
|
+
}
|
|
35
|
+
get repo_name(): string {
|
|
36
|
+
return this.library.repo_name;
|
|
37
|
+
}
|
|
38
|
+
get repo_url(): Url {
|
|
39
|
+
return this.library.repo_url;
|
|
40
|
+
}
|
|
41
|
+
get owner_name(): string | null {
|
|
42
|
+
return this.library.owner_name;
|
|
43
|
+
}
|
|
44
|
+
get homepage_url(): Url | null {
|
|
45
|
+
return this.library.homepage_url;
|
|
46
|
+
}
|
|
47
|
+
get logo_url(): Url | null {
|
|
48
|
+
return this.library.logo_url;
|
|
49
|
+
}
|
|
50
|
+
get logo_alt(): string {
|
|
51
|
+
return this.library.logo_alt;
|
|
52
|
+
}
|
|
53
|
+
get published(): boolean {
|
|
54
|
+
return this.library.published;
|
|
55
|
+
}
|
|
56
|
+
get npm_url(): Url | null {
|
|
57
|
+
return this.library.npm_url;
|
|
58
|
+
}
|
|
59
|
+
get changelog_url(): Url | null {
|
|
60
|
+
return this.library.changelog_url;
|
|
61
|
+
}
|
|
62
|
+
get package_json(): PackageJson {
|
|
63
|
+
return this.library.package_json;
|
|
64
|
+
}
|
|
65
|
+
get source_json(): SourceJson {
|
|
66
|
+
return this.library.source_json;
|
|
67
|
+
}
|
|
68
|
+
get modules(): Array<Module> {
|
|
69
|
+
return this.library.modules;
|
|
70
|
+
}
|
|
71
|
+
get org_url(): string | null {
|
|
72
|
+
return this.library.org_url;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
constructor(repo_json: RepoJson) {
|
|
76
|
+
this.library = new Library(repo_json.library_json);
|
|
77
|
+
this.check_runs = repo_json.check_runs;
|
|
78
|
+
this.pull_requests = repo_json.pull_requests;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export interface Repos {
|
|
83
|
+
repo: Repo;
|
|
84
|
+
repos: Array<Repo>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const repos_context = create_context<Repos>();
|
|
88
|
+
|
|
89
|
+
export const repos_parse = (repos: Array<Repo>, homepage_url: string): Repos => {
|
|
90
|
+
// We expect to find this because it's sourced from the local package.json
|
|
91
|
+
const repo = repos.find((d) => d.homepage_url === homepage_url);
|
|
92
|
+
if (!repo) throw Error(`Cannot find repo with homepage_url: ${homepage_url}`);
|
|
93
|
+
|
|
94
|
+
return {repo, repos};
|
|
95
|
+
};
|