@fuzdev/fuz_gitops 0.72.0 → 0.73.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/README.md +13 -6
- package/dist/changeset_generator.d.ts.map +1 -1
- package/dist/changeset_generator.js +2 -16
- package/dist/changeset_reader.d.ts +1 -1
- package/dist/changeset_reader.d.ts.map +1 -1
- package/dist/dependency_graph.js +1 -1
- package/dist/git_operations.d.ts +5 -0
- package/dist/git_operations.d.ts.map +1 -1
- package/dist/git_operations.js +5 -0
- package/dist/gitops_analyze.task.d.ts +1 -0
- package/dist/gitops_analyze.task.d.ts.map +1 -1
- package/dist/gitops_analyze.task.js +12 -17
- package/dist/gitops_plan.task.d.ts +1 -0
- package/dist/gitops_plan.task.d.ts.map +1 -1
- package/dist/gitops_plan.task.js +9 -2
- package/dist/gitops_publish.task.d.ts +2 -2
- package/dist/gitops_publish.task.d.ts.map +1 -1
- package/dist/gitops_publish.task.js +83 -28
- package/dist/gitops_run.task.d.ts +2 -1
- package/dist/gitops_run.task.d.ts.map +1 -1
- package/dist/gitops_run.task.js +40 -7
- package/dist/gitops_sync.task.d.ts +1 -0
- package/dist/gitops_sync.task.d.ts.map +1 -1
- package/dist/gitops_sync.task.js +16 -2
- package/dist/gitops_task_helpers.d.ts +16 -2
- package/dist/gitops_task_helpers.d.ts.map +1 -1
- package/dist/gitops_task_helpers.js +11 -3
- package/dist/gitops_validate.task.d.ts +1 -0
- package/dist/gitops_validate.task.d.ts.map +1 -1
- package/dist/gitops_validate.task.js +20 -20
- package/dist/graph_validation.d.ts +16 -1
- package/dist/graph_validation.d.ts.map +1 -1
- package/dist/graph_validation.js +15 -0
- package/dist/local_repo.d.ts +22 -10
- package/dist/local_repo.d.ts.map +1 -1
- package/dist/local_repo.js +92 -75
- package/dist/log_helpers.d.ts +0 -5
- package/dist/log_helpers.d.ts.map +1 -1
- package/dist/log_helpers.js +8 -19
- package/dist/multi_repo_publisher.d.ts +21 -2
- package/dist/multi_repo_publisher.d.ts.map +1 -1
- package/dist/multi_repo_publisher.js +279 -287
- package/dist/operations.d.ts +6 -26
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations_defaults.d.ts.map +1 -1
- package/dist/operations_defaults.js +1 -19
- package/dist/output_helpers.d.ts.map +1 -1
- package/dist/output_helpers.js +7 -6
- package/dist/paths.d.ts +0 -4
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +0 -4
- package/dist/publish_gate.d.ts +44 -0
- package/dist/publish_gate.d.ts.map +1 -0
- package/dist/publish_gate.js +32 -0
- package/dist/publish_steps.d.ts +60 -0
- package/dist/publish_steps.d.ts.map +1 -0
- package/dist/publish_steps.js +113 -0
- package/dist/publishing_event.d.ts +12 -19
- package/dist/publishing_event.d.ts.map +1 -1
- package/dist/publishing_event.js +16 -25
- package/dist/publishing_plan.d.ts +1 -2
- package/dist/publishing_plan.d.ts.map +1 -1
- package/dist/publishing_plan.js +18 -1
- package/dist/publishing_plan_helpers.d.ts +1 -1
- package/dist/publishing_plan_helpers.d.ts.map +1 -1
- package/dist/publishing_plan_helpers.js +2 -15
- package/dist/publishing_plan_logging.d.ts.map +1 -1
- package/dist/publishing_plan_logging.js +15 -23
- package/dist/version_utils.d.ts +17 -3
- package/dist/version_utils.d.ts.map +1 -1
- package/dist/version_utils.js +22 -0
- package/package.json +5 -6
- package/src/lib/changeset_generator.ts +10 -19
- package/src/lib/changeset_reader.ts +1 -2
- package/src/lib/dependency_graph.ts +1 -1
- package/src/lib/git_operations.ts +5 -0
- package/src/lib/gitops_analyze.task.ts +18 -23
- package/src/lib/gitops_plan.task.ts +10 -2
- package/src/lib/gitops_publish.task.ts +92 -27
- package/src/lib/gitops_run.task.ts +39 -7
- package/src/lib/gitops_sync.task.ts +18 -3
- package/src/lib/gitops_task_helpers.ts +20 -3
- package/src/lib/gitops_validate.task.ts +30 -22
- package/src/lib/graph_validation.ts +26 -0
- package/src/lib/local_repo.ts +114 -83
- package/src/lib/log_helpers.ts +8 -26
- package/src/lib/multi_repo_publisher.ts +336 -353
- package/src/lib/operations.ts +6 -22
- package/src/lib/operations_defaults.ts +1 -19
- package/src/lib/output_helpers.ts +7 -6
- package/src/lib/paths.ts +0 -5
- package/src/lib/publish_gate.ts +53 -0
- package/src/lib/publish_steps.ts +149 -0
- package/src/lib/publishing_event.ts +16 -25
- package/src/lib/publishing_plan.ts +23 -3
- package/src/lib/publishing_plan_helpers.ts +5 -18
- package/src/lib/publishing_plan_logging.ts +19 -39
- package/src/lib/version_utils.ts +30 -9
- package/dist/npm_install_helpers.d.ts +0 -23
- package/dist/npm_install_helpers.d.ts.map +0 -1
- package/dist/npm_install_helpers.js +0 -60
- package/dist/semver.d.ts +0 -26
- package/dist/semver.d.ts.map +0 -1
- package/dist/semver.js +0 -137
- package/dist/serialization_types.d.ts +0 -59
- package/dist/serialization_types.d.ts.map +0 -1
- package/dist/serialization_types.js +0 -42
- package/src/lib/npm_install_helpers.ts +0 -85
- package/src/lib/semver.ts +0 -170
- package/src/lib/serialization_types.ts +0 -92
package/dist/publishing_plan.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { styleText as st } from 'node:util';
|
|
2
2
|
import { validate_dependency_graph } from './graph_validation.js';
|
|
3
|
-
import { is_breaking_change, compare_bump_types, calculate_next_version } from './version_utils.js';
|
|
3
|
+
import { is_breaking_change, compare_bump_types, calculate_next_version, } from './version_utils.js';
|
|
4
4
|
import { default_changeset_operations } from './operations_defaults.js';
|
|
5
5
|
import { GITOPS_MAX_ITERATIONS_DEFAULT } from './gitops_constants.js';
|
|
6
6
|
import { calculate_dependency_updates, get_required_bump_for_dependencies, } from './publishing_plan_helpers.js';
|
|
@@ -70,6 +70,17 @@ export const generate_publishing_plan = async (repos, options = {}) => {
|
|
|
70
70
|
const repo = repos.find((r) => r.library.name === pkg_name);
|
|
71
71
|
if (!repo)
|
|
72
72
|
continue;
|
|
73
|
+
// Private packages never publish — exclude them from version changes entirely (no
|
|
74
|
+
// publish step, npm-wait, bump escalation, or auto-changeset). They keep their slot in
|
|
75
|
+
// the topological order. Flag a private package that carries a changeset, since that
|
|
76
|
+
// changeset can't be published.
|
|
77
|
+
if (repo.library.package_json.private) {
|
|
78
|
+
const private_has_changesets = await ops.has_changesets({ repo });
|
|
79
|
+
if (private_has_changesets.ok && private_has_changesets.value) {
|
|
80
|
+
warnings.push(`${pkg_name} is private — its changeset(s) will not be published`);
|
|
81
|
+
}
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
73
84
|
// Check for changesets
|
|
74
85
|
const has_result = await ops.has_changesets({ repo });
|
|
75
86
|
if (!has_result.ok) {
|
|
@@ -140,6 +151,10 @@ export const generate_publishing_plan = async (repos, options = {}) => {
|
|
|
140
151
|
// Process packages to check for bump escalation and auto-generated changesets
|
|
141
152
|
for (const repo of repos) {
|
|
142
153
|
const pkg_name = repo.library.name;
|
|
154
|
+
// Private packages are excluded from version changes (they never publish), so they
|
|
155
|
+
// never escalate or auto-generate a changeset.
|
|
156
|
+
if (repo.library.package_json.private)
|
|
157
|
+
continue;
|
|
143
158
|
// Get required bump from dependencies
|
|
144
159
|
const required_bump = get_required_bump_for_dependencies(repo, dependency_updates, breaking_packages);
|
|
145
160
|
// Find triggering dependency for verbose output
|
|
@@ -248,6 +263,8 @@ export const generate_publishing_plan = async (repos, options = {}) => {
|
|
|
248
263
|
const { dependency_updates: pending_updates } = calculate_dependency_updates(repos, predicted_versions, breaking_packages);
|
|
249
264
|
for (const repo of repos) {
|
|
250
265
|
const pkg_name = repo.library.name;
|
|
266
|
+
if (repo.library.package_json.private)
|
|
267
|
+
continue; // private packages never publish
|
|
251
268
|
const required_bump = get_required_bump_for_dependencies(repo, pending_updates, breaking_packages);
|
|
252
269
|
// Check if this package would need processing
|
|
253
270
|
const existing_entry = version_changes.find((vc) => vc.package_name === pkg_name);
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @module
|
|
7
7
|
*/
|
|
8
8
|
import type { LocalRepo } from './local_repo.js';
|
|
9
|
-
import type
|
|
9
|
+
import { type BumpType } from './version_utils.js';
|
|
10
10
|
import type { DependencyUpdate } from './publishing_plan.js';
|
|
11
11
|
/**
|
|
12
12
|
* Calculates all dependency updates between packages based on predicted versions.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publishing_plan_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/publishing_plan_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"publishing_plan_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/publishing_plan_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAoD,KAAK,QAAQ,EAAC,MAAM,oBAAoB,CAAC;AACpG,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,sBAAsB,CAAC;AAE3D;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,GACxC,OAAO,KAAK,CAAC,SAAS,CAAC,EACvB,oBAAoB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACvC,mBAAmB,GAAG,CAAC,MAAM,CAAC,KAC5B;IACF,kBAAkB,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAC5C,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;CAwE9C,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,kCAAkC,GAC9C,MAAM,SAAS,EACf,oBAAoB,KAAK,CAAC,gBAAgB,CAAC,EAC3C,mBAAmB,GAAG,CAAC,MAAM,CAAC,KAC5B,QAAQ,GAAG,IAqBb,CAAC"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*
|
|
6
6
|
* @module
|
|
7
7
|
*/
|
|
8
|
-
import { needs_update } from './version_utils.js';
|
|
8
|
+
import { needs_update, required_bump_for_dependency_update } from './version_utils.js';
|
|
9
9
|
/**
|
|
10
10
|
* Calculates all dependency updates between packages based on predicted versions.
|
|
11
11
|
*
|
|
@@ -29,7 +29,6 @@ export const calculate_dependency_updates = (repos, predicted_versions, breaking
|
|
|
29
29
|
current_version,
|
|
30
30
|
new_version,
|
|
31
31
|
type: 'dependencies',
|
|
32
|
-
causes_republish: true,
|
|
33
32
|
});
|
|
34
33
|
if (breaking_packages.has(dep_name)) {
|
|
35
34
|
const cascades = breaking_cascades.get(dep_name) || [];
|
|
@@ -52,7 +51,6 @@ export const calculate_dependency_updates = (repos, predicted_versions, breaking
|
|
|
52
51
|
current_version,
|
|
53
52
|
new_version,
|
|
54
53
|
type: 'peerDependencies',
|
|
55
|
-
causes_republish: true,
|
|
56
54
|
});
|
|
57
55
|
if (breaking_packages.has(dep_name)) {
|
|
58
56
|
const cascades = breaking_cascades.get(dep_name) || [];
|
|
@@ -75,7 +73,6 @@ export const calculate_dependency_updates = (repos, predicted_versions, breaking
|
|
|
75
73
|
current_version,
|
|
76
74
|
new_version,
|
|
77
75
|
type: 'devDependencies',
|
|
78
|
-
causes_republish: false,
|
|
79
76
|
});
|
|
80
77
|
}
|
|
81
78
|
}
|
|
@@ -100,15 +97,5 @@ export const get_required_bump_for_dependencies = (repo, dependency_updates, bre
|
|
|
100
97
|
}
|
|
101
98
|
// Check if any of these dependencies have breaking changes
|
|
102
99
|
const has_breaking_deps = relevant_updates.some((update) => breaking_packages.has(update.updated_dependency));
|
|
103
|
-
|
|
104
|
-
const [major] = current_version.split('.').map(Number);
|
|
105
|
-
const is_pre_1_0 = major === 0;
|
|
106
|
-
if (has_breaking_deps) {
|
|
107
|
-
// Breaking changes propagate
|
|
108
|
-
// Pre-1.0: use minor for breaking changes
|
|
109
|
-
// 1.0+: use major for breaking changes
|
|
110
|
-
return is_pre_1_0 ? 'minor' : 'major';
|
|
111
|
-
}
|
|
112
|
-
// For non-breaking dependency updates, use patch
|
|
113
|
-
return 'patch';
|
|
100
|
+
return required_bump_for_dependency_update(repo.library.package_json.version || '0.0.0', has_breaking_deps);
|
|
114
101
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publishing_plan_logging.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/publishing_plan_logging.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAGpD,OAAO,KAAK,EACX,cAAc,EAQd,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,cAAc;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AA2GD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,cAAc,EACpB,KAAK,MAAM,EACX,UAAS,cAAmB,KAC1B,
|
|
1
|
+
{"version":3,"file":"publishing_plan_logging.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/publishing_plan_logging.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAGpD,OAAO,KAAK,EACX,cAAc,EAQd,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,cAAc;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AA2GD;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,cAAc,EACpB,KAAK,MAAM,EACX,UAAS,cAAmB,KAC1B,IA6IF,CAAC"}
|
|
@@ -120,31 +120,23 @@ export const log_publishing_plan = (plan, log, options = {}) => {
|
|
|
120
120
|
const with_changesets = ordered_changes.filter((vc) => vc.has_changesets && !vc.needs_bump_escalation);
|
|
121
121
|
const with_escalation = ordered_changes.filter((vc) => vc.needs_bump_escalation);
|
|
122
122
|
const with_auto_changesets = ordered_changes.filter((vc) => vc.will_generate_changeset);
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
123
|
+
// A single running counter across all groups so positions read 1..N with no
|
|
124
|
+
// gaps. (Numbering per-group index would make the first group skip the numbers
|
|
125
|
+
// that land in a later group, e.g. jump from `[9/12]` to `[11/12]`.)
|
|
126
|
+
const total = with_changesets.length + with_escalation.length + with_auto_changesets.length;
|
|
127
|
+
let position = 0;
|
|
128
|
+
const log_change_group = (title, color, changes) => {
|
|
129
|
+
if (changes.length === 0)
|
|
130
|
+
return;
|
|
131
|
+
log.info(st(color, title));
|
|
132
|
+
for (const change of changes) {
|
|
133
|
+
log_version_change_with_diffs(change, position++, total, dependency_updates, breaking_cascades, log);
|
|
129
134
|
}
|
|
130
135
|
log.info('');
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const idx = ordered_changes.indexOf(change);
|
|
136
|
-
log_version_change_with_diffs(change, idx, ordered_changes.length, dependency_updates, breaking_cascades, log);
|
|
137
|
-
}
|
|
138
|
-
log.info('');
|
|
139
|
-
}
|
|
140
|
-
if (with_auto_changesets.length > 0) {
|
|
141
|
-
log.info(st('cyan', 'Version Changes (auto-generated):'));
|
|
142
|
-
for (const change of with_auto_changesets) {
|
|
143
|
-
const idx = ordered_changes.indexOf(change);
|
|
144
|
-
log_version_change_with_diffs(change, idx, ordered_changes.length, dependency_updates, breaking_cascades, log);
|
|
145
|
-
}
|
|
146
|
-
log.info('');
|
|
147
|
-
}
|
|
136
|
+
};
|
|
137
|
+
log_change_group('Version Changes (from changesets):', 'cyan', with_changesets);
|
|
138
|
+
log_change_group('Version Changes (bump escalation):', 'yellow', with_escalation);
|
|
139
|
+
log_change_group('Version Changes (auto-generated):', 'cyan', with_auto_changesets);
|
|
148
140
|
}
|
|
149
141
|
else {
|
|
150
142
|
log.info(st('dim', 'No packages to publish'));
|
package/dist/version_utils.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/** A semver bump kind: `major`, `minor`, or `patch`. */
|
|
2
|
+
export type BumpType = 'major' | 'minor' | 'patch';
|
|
2
3
|
export declare const is_wildcard: (version: string) => boolean;
|
|
3
4
|
/**
|
|
4
5
|
* Strips version prefix (^, ~, >=, <=, etc) from a version string.
|
|
@@ -47,8 +48,21 @@ export declare const get_update_prefix: (current_version: string, default_strate
|
|
|
47
48
|
* Pre-1.0: minor bumps are breaking
|
|
48
49
|
* 1.0+: major bumps are breaking
|
|
49
50
|
*/
|
|
50
|
-
export declare const is_breaking_change: (old_version: string, bump_type:
|
|
51
|
-
|
|
51
|
+
export declare const is_breaking_change: (old_version: string, bump_type: BumpType) => boolean;
|
|
52
|
+
/**
|
|
53
|
+
* The bump a package must take when one of its prod/peer dependencies updates.
|
|
54
|
+
* Pre-1.0: `minor` for a breaking dependency, otherwise `patch`.
|
|
55
|
+
* 1.0+: `major` for a breaking dependency, otherwise `patch`.
|
|
56
|
+
*
|
|
57
|
+
* Single source of truth for the dependency-driven bump rule, shared by the plan
|
|
58
|
+
* (`get_required_bump_for_dependencies`) and the auto-changeset generator
|
|
59
|
+
* (`calculate_required_bump`) so the two never drift.
|
|
60
|
+
*
|
|
61
|
+
* @param current_version - the package's current version, used to detect the pre-1.0 regime
|
|
62
|
+
* @param has_breaking_deps - whether any updated dependency is a breaking change
|
|
63
|
+
*/
|
|
64
|
+
export declare const required_bump_for_dependency_update: (current_version: string, has_breaking_deps: boolean) => BumpType;
|
|
65
|
+
export declare const detect_bump_type: (old_version: string, new_version: string) => BumpType;
|
|
52
66
|
/**
|
|
53
67
|
* Compares bump types. Returns positive if a > b, negative if a < b, 0 if equal.
|
|
54
68
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"version_utils.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/version_utils.ts"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"version_utils.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/version_utils.ts"],"names":[],"mappings":"AAEA,wDAAwD;AACxD,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnD,eAAO,MAAM,WAAW,GAAI,SAAS,MAAM,KAAG,OAE7C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS,MAAM,KAAG,MAEtD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,KAAG,MAGpD,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,gCAAgC,GAAI,SAAS,MAAM,KAAG,MAWlE,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,EAAE,aAAa,MAAM,KAAG,OASnE,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,GAC7B,iBAAiB,MAAM,EACvB,mBAAkB,GAAG,GAAG,GAAG,GAAG,EAAE,GAAG,IAAU,KAC3C,MAcF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,aAAa,MAAM,EAAE,WAAW,QAAQ,KAAG,OAW7E,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mCAAmC,GAC/C,iBAAiB,MAAM,EACvB,mBAAmB,OAAO,KACxB,QASF,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,aAAa,MAAM,EAAE,aAAa,MAAM,KAAG,QAO3E,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,GAAG,QAAQ,EAAE,GAAG,QAAQ,KAAG,MAO7D,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,iBAAiB,MAAM,EAAE,WAAW,QAAQ,KAAG,MAkBrF,CAAC"}
|
package/dist/version_utils.js
CHANGED
|
@@ -96,6 +96,28 @@ export const is_breaking_change = (old_version, bump_type) => {
|
|
|
96
96
|
return bump_type === 'major';
|
|
97
97
|
}
|
|
98
98
|
};
|
|
99
|
+
/**
|
|
100
|
+
* The bump a package must take when one of its prod/peer dependencies updates.
|
|
101
|
+
* Pre-1.0: `minor` for a breaking dependency, otherwise `patch`.
|
|
102
|
+
* 1.0+: `major` for a breaking dependency, otherwise `patch`.
|
|
103
|
+
*
|
|
104
|
+
* Single source of truth for the dependency-driven bump rule, shared by the plan
|
|
105
|
+
* (`get_required_bump_for_dependencies`) and the auto-changeset generator
|
|
106
|
+
* (`calculate_required_bump`) so the two never drift.
|
|
107
|
+
*
|
|
108
|
+
* @param current_version - the package's current version, used to detect the pre-1.0 regime
|
|
109
|
+
* @param has_breaking_deps - whether any updated dependency is a breaking change
|
|
110
|
+
*/
|
|
111
|
+
export const required_bump_for_dependency_update = (current_version, has_breaking_deps) => {
|
|
112
|
+
const [major] = current_version.split('.').map(Number);
|
|
113
|
+
const is_pre_1_0 = major === 0;
|
|
114
|
+
if (has_breaking_deps) {
|
|
115
|
+
// Breaking changes propagate: pre-1.0 uses minor, 1.0+ uses major
|
|
116
|
+
return is_pre_1_0 ? 'minor' : 'major';
|
|
117
|
+
}
|
|
118
|
+
// Non-breaking dependency updates only need a patch
|
|
119
|
+
return 'patch';
|
|
120
|
+
};
|
|
99
121
|
export const detect_bump_type = (old_version, new_version) => {
|
|
100
122
|
const old_parts = old_version.split('.').map(Number);
|
|
101
123
|
const new_parts = new_version.split('.').map(Number);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fuzdev/fuz_gitops",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.73.0",
|
|
4
4
|
"description": "a tool for managing many repos",
|
|
5
5
|
"glyph": "🪄",
|
|
6
6
|
"logo": "logo.svg",
|
|
@@ -42,10 +42,9 @@
|
|
|
42
42
|
"@fuzdev/blake3_wasm": "^0.1.1",
|
|
43
43
|
"@fuzdev/fuz_code": "^0.45.1",
|
|
44
44
|
"@fuzdev/fuz_css": "^0.61.1",
|
|
45
|
-
"@fuzdev/fuz_ui": "^0.198.
|
|
46
|
-
"@fuzdev/fuz_util": "^0.63.
|
|
47
|
-
"@fuzdev/gro": "^0.
|
|
48
|
-
"@jridgewell/trace-mapping": "^0.3.31",
|
|
45
|
+
"@fuzdev/fuz_ui": "^0.198.1",
|
|
46
|
+
"@fuzdev/fuz_util": "^0.63.2",
|
|
47
|
+
"@fuzdev/gro": "^0.202.0",
|
|
49
48
|
"@ryanatkn/eslint-config": "^0.12.1",
|
|
50
49
|
"@sveltejs/acorn-typescript": "^1.0.9",
|
|
51
50
|
"@sveltejs/adapter-static": "^3.0.10",
|
|
@@ -63,7 +62,7 @@
|
|
|
63
62
|
"prettier-plugin-svelte": "^3.5.1",
|
|
64
63
|
"svelte": "^5.56.0",
|
|
65
64
|
"svelte-check": "^4.4.6",
|
|
66
|
-
"svelte-docinfo": "^0.
|
|
65
|
+
"svelte-docinfo": "^0.4.0",
|
|
67
66
|
"svelte2tsx": "^0.7.52",
|
|
68
67
|
"tslib": "^2.8.1",
|
|
69
68
|
"typescript": "^5.9.3",
|
|
@@ -11,7 +11,11 @@ import {join} from 'node:path';
|
|
|
11
11
|
import type {Logger} from '@fuzdev/fuz_util/log.js';
|
|
12
12
|
import type {LocalRepo} from './local_repo.js';
|
|
13
13
|
import type {PublishedVersion} from './multi_repo_publisher.js';
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
strip_version_prefix,
|
|
16
|
+
required_bump_for_dependency_update,
|
|
17
|
+
type BumpType,
|
|
18
|
+
} from './version_utils.js';
|
|
15
19
|
import type {FsOperations} from './operations.js';
|
|
16
20
|
import {default_fs_operations} from './operations_defaults.js';
|
|
17
21
|
|
|
@@ -69,24 +73,11 @@ export const create_changeset_for_dependency_updates = async (
|
|
|
69
73
|
const calculate_required_bump = (
|
|
70
74
|
repo: LocalRepo,
|
|
71
75
|
updates: Array<DependencyVersionChange>,
|
|
72
|
-
):
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
// Check if any dependency had breaking changes
|
|
78
|
-
const has_breaking = updates.some((u) => u.breaking);
|
|
79
|
-
|
|
80
|
-
if (has_breaking) {
|
|
81
|
-
// Breaking changes propagate
|
|
82
|
-
// Pre-1.0: use minor for breaking changes
|
|
83
|
-
// 1.0+: use major for breaking changes
|
|
84
|
-
return is_pre_1_0 ? 'minor' : 'major';
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// For non-breaking dependency updates, always use patch
|
|
88
|
-
return 'patch';
|
|
89
|
-
};
|
|
76
|
+
): BumpType =>
|
|
77
|
+
required_bump_for_dependency_update(
|
|
78
|
+
repo.library.package_json.version || '0.0.0',
|
|
79
|
+
updates.some((u) => u.breaking),
|
|
80
|
+
);
|
|
90
81
|
|
|
91
82
|
/**
|
|
92
83
|
* Generates markdown changeset content for dependency updates.
|
|
@@ -13,8 +13,7 @@ import {readdir, readFile} from 'node:fs/promises';
|
|
|
13
13
|
import {join} from 'node:path';
|
|
14
14
|
|
|
15
15
|
import type {LocalRepo} from './local_repo.js';
|
|
16
|
-
import type
|
|
17
|
-
import {compare_bump_types, calculate_next_version} from './version_utils.js';
|
|
16
|
+
import {compare_bump_types, calculate_next_version, type BumpType} from './version_utils.js';
|
|
18
17
|
|
|
19
18
|
export interface ChangesetInfo {
|
|
20
19
|
filename: string;
|
|
@@ -66,7 +66,7 @@ export class DependencyGraph {
|
|
|
66
66
|
repo,
|
|
67
67
|
dependencies: new Map(),
|
|
68
68
|
dependents: new Set(),
|
|
69
|
-
publishable:
|
|
69
|
+
publishable: !library.package_json.private,
|
|
70
70
|
};
|
|
71
71
|
|
|
72
72
|
// Extract dependencies
|
|
@@ -84,6 +84,11 @@ export const git_push_tag = async (
|
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Returns `true` if the working tree has any changes — staged, unstaged, or
|
|
89
|
+
* untracked (`git status --porcelain`). Broader than `git_list_uncommitted_files`,
|
|
90
|
+
* which reports only tracked working-tree changes relative to HEAD.
|
|
91
|
+
*/
|
|
87
92
|
export const git_has_changes = async (options?: SpawnOptions): Promise<boolean> => {
|
|
88
93
|
const {stdout} = await spawn_out('git', ['status', '--porcelain'], options);
|
|
89
94
|
return stdout ? stdout.trim().length > 0 : false;
|
|
@@ -4,9 +4,9 @@ import {styleText as st} from 'node:util';
|
|
|
4
4
|
import type {Logger} from '@fuzdev/fuz_util/log.js';
|
|
5
5
|
|
|
6
6
|
import {get_gitops_ready} from './gitops_task_helpers.js';
|
|
7
|
-
import
|
|
7
|
+
import type {DependencyGraph} from './dependency_graph.js';
|
|
8
8
|
import type {LocalRepo} from './local_repo.js';
|
|
9
|
-
import {
|
|
9
|
+
import {analyze_repos, type DependencyAnalysis} from './graph_validation.js';
|
|
10
10
|
import {
|
|
11
11
|
format_wildcard_dependencies,
|
|
12
12
|
format_dev_cycles,
|
|
@@ -30,6 +30,13 @@ export const Args = z.strictObject({
|
|
|
30
30
|
.meta({description: 'output format'})
|
|
31
31
|
.default('stdout'),
|
|
32
32
|
outfile: z.string().meta({description: 'write output to file instead of logging'}).optional(),
|
|
33
|
+
sync: z
|
|
34
|
+
.boolean()
|
|
35
|
+
.meta({
|
|
36
|
+
description:
|
|
37
|
+
'sync repos (switch branch, pull, install) before analyzing instead of reading the working tree as-is',
|
|
38
|
+
})
|
|
39
|
+
.default(false),
|
|
33
40
|
});
|
|
34
41
|
export type Args = z.infer<typeof Args>;
|
|
35
42
|
|
|
@@ -38,25 +45,13 @@ export const task: Task<Args> = {
|
|
|
38
45
|
Args,
|
|
39
46
|
summary: 'analyze dependency structure and relationships across repos',
|
|
40
47
|
run: async ({args, log}) => {
|
|
41
|
-
const {config, dir, format, outfile} = args;
|
|
48
|
+
const {config, dir, format, outfile, sync} = args;
|
|
42
49
|
|
|
43
|
-
// Get repos ready (without downloading)
|
|
44
|
-
const {local_repos} = await get_gitops_ready({config, dir, download: false, log});
|
|
50
|
+
// Get repos ready (without downloading); read the working tree as-is unless `--sync`
|
|
51
|
+
const {local_repos} = await get_gitops_ready({config, dir, download: false, sync, log});
|
|
45
52
|
|
|
46
|
-
// Build dependency graph and
|
|
47
|
-
const {graph, publishing_order
|
|
48
|
-
log,
|
|
49
|
-
throw_on_prod_cycles: false, // Analyze should report, not throw
|
|
50
|
-
log_cycles: false, // We'll show cycles in our formatted output
|
|
51
|
-
log_order: false, // We'll show order in our formatted output
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
// Perform additional analysis
|
|
55
|
-
const builder = new DependencyGraphBuilder();
|
|
56
|
-
const analysis = builder.analyze(graph);
|
|
57
|
-
|
|
58
|
-
// Publishing order (may be null if prod cycles exist)
|
|
59
|
-
const publishing_order = order.length > 0 ? order : null;
|
|
53
|
+
// Build the dependency graph and analyze cycles/wildcards (tolerating cycles)
|
|
54
|
+
const {graph, analysis, publishing_order} = analyze_repos(local_repos);
|
|
60
55
|
|
|
61
56
|
// Format and output using output_helpers
|
|
62
57
|
const data = {
|
|
@@ -74,7 +69,7 @@ export const task: Task<Args> = {
|
|
|
74
69
|
interface AnalysisData {
|
|
75
70
|
repos: Array<LocalRepo>;
|
|
76
71
|
graph: DependencyGraph;
|
|
77
|
-
analysis:
|
|
72
|
+
analysis: DependencyAnalysis;
|
|
78
73
|
publishing_order: Array<string> | null;
|
|
79
74
|
}
|
|
80
75
|
|
|
@@ -102,7 +97,7 @@ const calculate_stats = (graph: DependencyGraph) => {
|
|
|
102
97
|
|
|
103
98
|
const format_json = (
|
|
104
99
|
graph: DependencyGraph,
|
|
105
|
-
analysis:
|
|
100
|
+
analysis: DependencyAnalysis,
|
|
106
101
|
publishing_order: Array<string> | null,
|
|
107
102
|
): string => {
|
|
108
103
|
const output = {
|
|
@@ -116,7 +111,7 @@ const format_json = (
|
|
|
116
111
|
const format_markdown = (
|
|
117
112
|
repos: Array<LocalRepo>,
|
|
118
113
|
graph: DependencyGraph,
|
|
119
|
-
analysis:
|
|
114
|
+
analysis: DependencyAnalysis,
|
|
120
115
|
publishing_order: Array<string> | null,
|
|
121
116
|
): Array<string> => {
|
|
122
117
|
const lines: Array<string> = ['# Dependency Analysis'];
|
|
@@ -192,7 +187,7 @@ const format_markdown = (
|
|
|
192
187
|
const format_stdout = (
|
|
193
188
|
repos: Array<LocalRepo>,
|
|
194
189
|
graph: DependencyGraph,
|
|
195
|
-
analysis:
|
|
190
|
+
analysis: DependencyAnalysis,
|
|
196
191
|
publishing_order: Array<string> | null,
|
|
197
192
|
log: Logger,
|
|
198
193
|
): void => {
|
|
@@ -28,6 +28,13 @@ export const Args = z.strictObject({
|
|
|
28
28
|
.default('stdout'),
|
|
29
29
|
outfile: z.string().meta({description: 'write output to file instead of logging'}).optional(),
|
|
30
30
|
verbose: z.boolean().meta({description: 'show additional details'}).default(false),
|
|
31
|
+
sync: z
|
|
32
|
+
.boolean()
|
|
33
|
+
.meta({
|
|
34
|
+
description:
|
|
35
|
+
'sync repos (switch branch, pull, install) before planning instead of reading the working tree as-is',
|
|
36
|
+
})
|
|
37
|
+
.default(false),
|
|
31
38
|
});
|
|
32
39
|
export type Args = z.infer<typeof Args>;
|
|
33
40
|
|
|
@@ -46,15 +53,16 @@ export const task: Task<Args> = {
|
|
|
46
53
|
summary: 'generate a publishing plan based on changesets',
|
|
47
54
|
Args,
|
|
48
55
|
run: async ({args, log}): Promise<void> => {
|
|
49
|
-
const {dir, config, format, outfile, verbose} = args;
|
|
56
|
+
const {dir, config, format, outfile, verbose, sync} = args;
|
|
50
57
|
|
|
51
58
|
log.info(st('cyan', 'Generating multi-repo publishing plan...'));
|
|
52
59
|
|
|
53
|
-
// Load local repos
|
|
60
|
+
// Load local repos; read the working tree as-is unless `--sync`
|
|
54
61
|
const {local_repos} = await get_gitops_ready({
|
|
55
62
|
config,
|
|
56
63
|
dir,
|
|
57
64
|
download: false, // Don't download if missing
|
|
65
|
+
sync,
|
|
58
66
|
log,
|
|
59
67
|
});
|
|
60
68
|
|