@fuzdev/fuz_gitops 0.62.0 → 0.64.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 +6 -6
- package/dist/ModulesDetail.svelte +10 -10
- package/dist/ReposTable.svelte +2 -2
- package/dist/ReposTreeNav.svelte +2 -2
- package/dist/gitops_publish.task.d.ts +1 -1
- package/dist/gitops_publish.task.d.ts.map +1 -1
- package/dist/gitops_publish.task.js +4 -7
- package/dist/gitops_validate.task.js +7 -7
- package/dist/multi_repo_publisher.d.ts +1 -1
- package/dist/multi_repo_publisher.d.ts.map +1 -1
- package/dist/multi_repo_publisher.js +12 -12
- package/dist/publishing_plan_logging.js +2 -2
- package/dist/serialization_types.d.ts +1 -1
- package/dist/serialization_types.js +1 -1
- package/package.json +10 -10
- package/src/lib/gitops_publish.task.ts +4 -7
- package/src/lib/gitops_validate.task.ts +7 -7
- package/src/lib/multi_repo_publisher.ts +13 -13
- package/src/lib/publishing_plan_logging.ts +2 -2
- package/src/lib/serialization_types.ts +1 -1
package/README.md
CHANGED
|
@@ -96,17 +96,17 @@ gro gitops_sync --download # clone missing repos first
|
|
|
96
96
|
### Diagnostic commands (read-only)
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
|
-
gro gitops_validate
|
|
100
|
-
gro gitops_analyze
|
|
101
|
-
gro gitops_plan
|
|
102
|
-
gro gitops_publish
|
|
99
|
+
gro gitops_validate # run all validation checks (analyze + plan + dry run)
|
|
100
|
+
gro gitops_analyze # analyze dependency graph and detect cycles
|
|
101
|
+
gro gitops_plan # generate publishing plan showing version changes and cascades
|
|
102
|
+
gro gitops_publish # simulate publishing without side effects (dry run default)
|
|
103
103
|
```
|
|
104
104
|
|
|
105
105
|
### Publishing packages
|
|
106
106
|
|
|
107
107
|
```bash
|
|
108
|
-
gro gitops_publish # publish all repos with changesets
|
|
109
|
-
gro gitops_publish --no-plan # skip plan confirmation
|
|
108
|
+
gro gitops_publish --wetrun # actually publish all repos with changesets
|
|
109
|
+
gro gitops_publish --wetrun --no-plan # skip plan confirmation
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
**Note:** If publishing fails, simply re-run the same command. Already-published packages are automatically skipped (changesets consumed), failed packages retried naturally.
|
|
@@ -121,29 +121,29 @@
|
|
|
121
121
|
font-size: var(--font_size_lg);
|
|
122
122
|
position: sticky;
|
|
123
123
|
top: 0;
|
|
124
|
-
background-color: var(--
|
|
124
|
+
background-color: var(--shade_00);
|
|
125
125
|
}
|
|
126
126
|
.modules {
|
|
127
127
|
padding: var(--space_sm);
|
|
128
128
|
}
|
|
129
129
|
.module {
|
|
130
130
|
margin-bottom: var(--space_lg);
|
|
131
|
-
--link_color: var(--
|
|
131
|
+
--link_color: var(--text_70);
|
|
132
132
|
}
|
|
133
133
|
.module_file {
|
|
134
134
|
margin-bottom: var(--space_xs);
|
|
135
135
|
}
|
|
136
136
|
.ts {
|
|
137
|
-
--link_color: var(--
|
|
137
|
+
--link_color: var(--color_a_50);
|
|
138
138
|
}
|
|
139
139
|
.svelte {
|
|
140
|
-
--link_color: var(--
|
|
140
|
+
--link_color: var(--color_e_50);
|
|
141
141
|
}
|
|
142
142
|
.css {
|
|
143
|
-
--link_color: var(--
|
|
143
|
+
--link_color: var(--color_b_50);
|
|
144
144
|
}
|
|
145
145
|
.json {
|
|
146
|
-
--link_color: var(--
|
|
146
|
+
--link_color: var(--color_f_50);
|
|
147
147
|
}
|
|
148
148
|
/* TODO extract */
|
|
149
149
|
.declarations {
|
|
@@ -160,16 +160,16 @@
|
|
|
160
160
|
font-size: var(--font_size_sm);
|
|
161
161
|
}
|
|
162
162
|
.variable_declaration {
|
|
163
|
-
color: var(--
|
|
163
|
+
color: var(--color_d_50);
|
|
164
164
|
}
|
|
165
165
|
.function_declaration {
|
|
166
|
-
color: var(--
|
|
166
|
+
color: var(--color_c_50);
|
|
167
167
|
}
|
|
168
168
|
.type_declaration {
|
|
169
|
-
color: var(--
|
|
169
|
+
color: var(--color_g_50);
|
|
170
170
|
}
|
|
171
171
|
.class_declaration {
|
|
172
|
-
color: var(--
|
|
172
|
+
color: var(--color_f_50);
|
|
173
173
|
}
|
|
174
174
|
/* TODO extract */
|
|
175
175
|
.nav_wrapper {
|
package/dist/ReposTable.svelte
CHANGED
|
@@ -180,11 +180,11 @@
|
|
|
180
180
|
padding: 0 var(--space_xs);
|
|
181
181
|
}
|
|
182
182
|
tr:hover {
|
|
183
|
-
background-color: var(--
|
|
183
|
+
background-color: var(--fg_50);
|
|
184
184
|
}
|
|
185
185
|
.latest {
|
|
186
186
|
/* TODO even lighter, add `--text_color_7` to Fuz probably, or change the scaling of `--text_color_3` and `--text_color_5` */
|
|
187
|
-
color: var(--
|
|
187
|
+
color: var(--text_50);
|
|
188
188
|
opacity: var(--disabled_opacity);
|
|
189
189
|
}
|
|
190
190
|
</style>
|
package/dist/ReposTreeNav.svelte
CHANGED
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
}
|
|
50
50
|
/* TODO should be a CSS class or variable, probably add :focus behavior */
|
|
51
51
|
.names a:hover {
|
|
52
|
-
background-color: var(--
|
|
52
|
+
background-color: var(--fg_50);
|
|
53
53
|
}
|
|
54
54
|
.names a:is(:active, .selected) {
|
|
55
|
-
background-color: var(--
|
|
55
|
+
background-color: var(--fg_70);
|
|
56
56
|
}
|
|
57
57
|
</style>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitops_publish.task.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gitops_publish.task.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,eAAe,CAAC;AACxC,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AActB,cAAc;AACd,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"gitops_publish.task.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gitops_publish.task.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,eAAe,CAAC;AACxC,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AActB,cAAc;AACd,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;kBAkCf,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;AAExC,cAAc;AACd,eAAO,MAAM,IAAI,EAAE,IAAI,CAAC,IAAI,CA0F3B,CAAC"}
|
|
@@ -20,10 +20,7 @@ export const Args = z.strictObject({
|
|
|
20
20
|
.enum(['exact', 'caret', 'tilde'])
|
|
21
21
|
.meta({ description: 'version strategy for peer dependencies' })
|
|
22
22
|
.default('caret'),
|
|
23
|
-
|
|
24
|
-
.boolean()
|
|
25
|
-
.meta({ description: 'perform a dry run without actually publishing' })
|
|
26
|
-
.default(false),
|
|
23
|
+
wetrun: z.boolean().meta({ description: 'actually publish (default is dry run)' }).default(false),
|
|
27
24
|
format: z
|
|
28
25
|
.enum(['stdout', 'json', 'markdown'])
|
|
29
26
|
.meta({ description: 'output format' })
|
|
@@ -50,7 +47,7 @@ export const task = {
|
|
|
50
47
|
summary: 'publish all repos in dependency order',
|
|
51
48
|
Args,
|
|
52
49
|
run: async ({ args, log }) => {
|
|
53
|
-
const { config, dir, peer_strategy,
|
|
50
|
+
const { config, dir, peer_strategy, wetrun, format, deploy, plan, max_wait, skip_install, outfile, verbose, } = args;
|
|
54
51
|
// Load repos
|
|
55
52
|
const { local_repos: repos } = await get_gitops_ready({
|
|
56
53
|
config,
|
|
@@ -59,7 +56,7 @@ export const task = {
|
|
|
59
56
|
log,
|
|
60
57
|
});
|
|
61
58
|
// Show plan if requested (skip for dry runs)
|
|
62
|
-
if (plan &&
|
|
59
|
+
if (plan && wetrun) {
|
|
63
60
|
log.info(st('cyan', 'Publishing Plan'));
|
|
64
61
|
const plan_result = await generate_publishing_plan(repos, { log, verbose });
|
|
65
62
|
log_publishing_plan(plan_result, log, { verbose });
|
|
@@ -77,7 +74,7 @@ export const task = {
|
|
|
77
74
|
}
|
|
78
75
|
// Publishing options
|
|
79
76
|
const options = {
|
|
80
|
-
|
|
77
|
+
wetrun,
|
|
81
78
|
update_deps: true, // Always update dependencies
|
|
82
79
|
version_strategy: peer_strategy,
|
|
83
80
|
deploy,
|
|
@@ -123,12 +123,12 @@ export const task = {
|
|
|
123
123
|
});
|
|
124
124
|
log.error(st('red', ` ✗ gitops_plan failed: ${error}`));
|
|
125
125
|
}
|
|
126
|
-
// 3. Run gitops_publish
|
|
127
|
-
log.info(st('yellow', 'Running gitops_publish
|
|
126
|
+
// 3. Run gitops_publish (dry run)
|
|
127
|
+
log.info(st('yellow', 'Running gitops_publish (dry run)...'));
|
|
128
128
|
const dry_start = Date.now();
|
|
129
129
|
try {
|
|
130
130
|
const options = {
|
|
131
|
-
|
|
131
|
+
wetrun: false,
|
|
132
132
|
update_deps: true,
|
|
133
133
|
log: undefined, // Silent for validation
|
|
134
134
|
};
|
|
@@ -138,13 +138,13 @@ export const task = {
|
|
|
138
138
|
// We'll just check if it succeeded
|
|
139
139
|
const errors = result.ok ? 0 : result.failed.length;
|
|
140
140
|
results.push({
|
|
141
|
-
command: 'gitops_publish
|
|
141
|
+
command: 'gitops_publish (dry run)',
|
|
142
142
|
success: result.ok,
|
|
143
143
|
warnings: 0,
|
|
144
144
|
errors,
|
|
145
145
|
duration: dry_duration,
|
|
146
146
|
});
|
|
147
|
-
log.info(st('green', ` ✓ gitops_publish
|
|
147
|
+
log.info(st('green', ` ✓ gitops_publish (dry run) completed in ${dry_duration}ms`));
|
|
148
148
|
if (errors > 0) {
|
|
149
149
|
log.error(st('red', ` ❌ Found ${errors} error(s)`));
|
|
150
150
|
}
|
|
@@ -152,13 +152,13 @@ export const task = {
|
|
|
152
152
|
catch (error) {
|
|
153
153
|
const dry_duration = Date.now() - dry_start;
|
|
154
154
|
results.push({
|
|
155
|
-
command: 'gitops_publish
|
|
155
|
+
command: 'gitops_publish (dry run)',
|
|
156
156
|
success: false,
|
|
157
157
|
warnings: 0,
|
|
158
158
|
errors: 1,
|
|
159
159
|
duration: dry_duration,
|
|
160
160
|
});
|
|
161
|
-
log.error(st('red', ` ✗ gitops_publish
|
|
161
|
+
log.error(st('red', ` ✗ gitops_publish (dry run) failed: ${error}`));
|
|
162
162
|
}
|
|
163
163
|
// Summary
|
|
164
164
|
const total_duration = Date.now() - start_time;
|
|
@@ -3,7 +3,7 @@ import type { LocalRepo } from './local_repo.js';
|
|
|
3
3
|
import { type VersionStrategy } from './dependency_updater.js';
|
|
4
4
|
import type { GitopsOperations } from './operations.js';
|
|
5
5
|
export interface PublishingOptions {
|
|
6
|
-
|
|
6
|
+
wetrun: boolean;
|
|
7
7
|
update_deps: boolean;
|
|
8
8
|
version_strategy?: VersionStrategy;
|
|
9
9
|
deploy?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multi_repo_publisher.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/multi_repo_publisher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAKpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAsB,KAAK,eAAe,EAAC,MAAM,yBAAyB,CAAC;AAIlF,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAUtD,MAAM,WAAW,iBAAiB;IACjC,
|
|
1
|
+
{"version":3,"file":"multi_repo_publisher.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/multi_repo_publisher.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAKpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAsB,KAAK,eAAe,EAAC,MAAM,yBAAyB,CAAC;AAIlF,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,iBAAiB,CAAC;AAUtD,MAAM,WAAW,iBAAiB;IACjC,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,eAAe,CAAC;IACnC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IACvC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACnC,MAAM,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAC,CAAC,CAAC;IAC5C,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,aAAa,GACzB,OAAO,KAAK,CAAC,SAAS,CAAC,EACvB,SAAS,iBAAiB,KACxB,OAAO,CAAC,gBAAgB,CAqU1B,CAAC"}
|
|
@@ -9,9 +9,9 @@ import { GITOPS_MAX_ITERATIONS_DEFAULT, GITOPS_NPM_WAIT_TIMEOUT_DEFAULT, } from
|
|
|
9
9
|
import { install_with_cache_healing } from './npm_install_helpers.js';
|
|
10
10
|
export const publish_repos = async (repos, options) => {
|
|
11
11
|
const start_time = Date.now();
|
|
12
|
-
const {
|
|
12
|
+
const { wetrun, update_deps, log, ops = default_gitops_operations } = options;
|
|
13
13
|
// Preflight checks (skip for dry runs since we're not actually publishing)
|
|
14
|
-
if (
|
|
14
|
+
if (wetrun) {
|
|
15
15
|
const preflight_options = {
|
|
16
16
|
skip_changesets: false, // Always check for changesets
|
|
17
17
|
required_branch: 'main',
|
|
@@ -30,7 +30,7 @@ export const publish_repos = async (repos, options) => {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
else {
|
|
33
|
-
log?.info('⏭️ Skipping preflight checks
|
|
33
|
+
log?.info('⏭️ Skipping preflight checks (dry run)');
|
|
34
34
|
}
|
|
35
35
|
// Build dependency graph and validate
|
|
36
36
|
const { publishing_order: order } = validate_dependency_graph(repos, {
|
|
@@ -77,7 +77,7 @@ export const publish_repos = async (repos, options) => {
|
|
|
77
77
|
// Skip packages without changesets
|
|
78
78
|
// In real publish: They might get auto-changesets during dependency updates
|
|
79
79
|
// In dry run: We can't simulate auto-changesets, so just skip
|
|
80
|
-
if (
|
|
80
|
+
if (!wetrun) {
|
|
81
81
|
// Silent skip in dry run - plan shows which packages get auto-changesets
|
|
82
82
|
continue;
|
|
83
83
|
}
|
|
@@ -97,7 +97,7 @@ export const publish_repos = async (repos, options) => {
|
|
|
97
97
|
published_in_iteration = true;
|
|
98
98
|
published_count++;
|
|
99
99
|
log?.info(st('green', ` ✅ Published ${pkg_name}@${version.new_version}`));
|
|
100
|
-
if (
|
|
100
|
+
if (wetrun) {
|
|
101
101
|
// 2. Wait for this package to be available on NPM
|
|
102
102
|
log?.info(` ⏳ Waiting for ${pkg_name}@${version.new_version} on NPM...`);
|
|
103
103
|
const wait_result = await ops.npm.wait_for_package({
|
|
@@ -157,7 +157,7 @@ export const publish_repos = async (repos, options) => {
|
|
|
157
157
|
}
|
|
158
158
|
// Phase 1b: Batch install dependencies for repos with updated package.json
|
|
159
159
|
// This ensures workspace stays consistent before next iteration
|
|
160
|
-
if (
|
|
160
|
+
if (wetrun && !options.skip_install && changed_in_iteration.size > 0) {
|
|
161
161
|
log?.info(st('cyan', '\n📦 Installing dependencies for updated repos...\n'));
|
|
162
162
|
for (const pkg_name of changed_in_iteration) {
|
|
163
163
|
const repo = repos.find((r) => r.library.name === pkg_name);
|
|
@@ -197,7 +197,7 @@ export const publish_repos = async (repos, options) => {
|
|
|
197
197
|
// Phase 2: Update all dev dependencies (can have cycles)
|
|
198
198
|
// Dev dep changes require deployment even without version bumps (rebuild needed)
|
|
199
199
|
const dev_updated_repos = new Set();
|
|
200
|
-
if (update_deps && published.size > 0 &&
|
|
200
|
+
if (update_deps && published.size > 0 && wetrun) {
|
|
201
201
|
log?.info(st('cyan', '\n🔄 Updating dev dependencies...\n'));
|
|
202
202
|
for (const repo of repos) {
|
|
203
203
|
const dev_updates = new Map();
|
|
@@ -224,7 +224,7 @@ export const publish_repos = async (repos, options) => {
|
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
226
|
// Phase 2b: Install dev dependencies for repos with dev dep updates
|
|
227
|
-
if (
|
|
227
|
+
if (wetrun && !options.skip_install && dev_updated_repos.size > 0) {
|
|
228
228
|
log?.info(st('cyan', '\n📦 Installing dev dependencies for updated repos...\n'));
|
|
229
229
|
for (const pkg_name of dev_updated_repos) {
|
|
230
230
|
const repo = repos.find((r) => r.library.name === pkg_name);
|
|
@@ -245,7 +245,7 @@ export const publish_repos = async (repos, options) => {
|
|
|
245
245
|
}
|
|
246
246
|
// Phase 3: Deploy repos with changes (optional)
|
|
247
247
|
// Deploys only repos that were: published, had prod/peer deps updated, or had dev deps updated
|
|
248
|
-
if (options.deploy &&
|
|
248
|
+
if (options.deploy && wetrun) {
|
|
249
249
|
const repos_to_deploy = repos.filter((r) => changed_repos.has(r.library.name));
|
|
250
250
|
log?.info(st('cyan', `\n🚢 Deploying ${repos_to_deploy.length}/${repos.length} repos with changes...\n`));
|
|
251
251
|
for (const repo of repos_to_deploy) {
|
|
@@ -300,9 +300,9 @@ export const publish_repos = async (repos, options) => {
|
|
|
300
300
|
* @throws {Error} if changeset prediction fails (dry run) or publish fails (real)
|
|
301
301
|
*/
|
|
302
302
|
const publish_single_repo = async (repo, options, ops = default_gitops_operations) => {
|
|
303
|
-
const {
|
|
303
|
+
const { wetrun, log } = options;
|
|
304
304
|
const old_version = repo.library.package_json.version || '0.0.0';
|
|
305
|
-
if (
|
|
305
|
+
if (!wetrun) {
|
|
306
306
|
// In dry run, predict version from changesets
|
|
307
307
|
const prediction = await ops.changeset.predict_next_version({ repo, log });
|
|
308
308
|
if (!prediction) {
|
|
@@ -321,7 +321,7 @@ const publish_single_repo = async (repo, options, ops = default_gitops_operation
|
|
|
321
321
|
new_version,
|
|
322
322
|
bump_type,
|
|
323
323
|
breaking,
|
|
324
|
-
commit: '
|
|
324
|
+
commit: 'simulated',
|
|
325
325
|
tag: `v${new_version}`,
|
|
326
326
|
};
|
|
327
327
|
}
|
|
@@ -210,9 +210,9 @@ export const log_publishing_plan = (plan, log, options = {}) => {
|
|
|
210
210
|
log_verbose(plan.verbose_data, log);
|
|
211
211
|
}
|
|
212
212
|
};
|
|
213
|
-
//
|
|
213
|
+
//
|
|
214
214
|
// Verbose logging functions
|
|
215
|
-
//
|
|
215
|
+
//
|
|
216
216
|
/**
|
|
217
217
|
* Logs all verbose sections in order.
|
|
218
218
|
*/
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - Dependency graph structures (`SerializedGraph`)
|
|
7
7
|
* - Publishing plan predictions (`SerializedPublishingPlan`)
|
|
8
8
|
*
|
|
9
|
-
* Used by `gitops_analyze`, `gitops_plan`, and `gitops_publish
|
|
9
|
+
* Used by `gitops_analyze`, `gitops_plan`, and `gitops_publish` (dry run) when
|
|
10
10
|
* `--format json` or `--outfile` is specified.
|
|
11
11
|
*
|
|
12
12
|
* @module
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - Dependency graph structures (`SerializedGraph`)
|
|
7
7
|
* - Publishing plan predictions (`SerializedPublishingPlan`)
|
|
8
8
|
*
|
|
9
|
-
* Used by `gitops_analyze`, `gitops_plan`, and `gitops_publish
|
|
9
|
+
* Used by `gitops_analyze`, `gitops_plan`, and `gitops_publish` (dry run) when
|
|
10
10
|
* `--format json` or `--outfile` is specified.
|
|
11
11
|
*
|
|
12
12
|
* @module
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fuzdev/fuz_gitops",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.64.0",
|
|
4
4
|
"description": "a tool for managing many repos",
|
|
5
5
|
"glyph": "🪄",
|
|
6
6
|
"logo": "logo.svg",
|
|
@@ -39,24 +39,24 @@
|
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@changesets/changelog-git": "^0.2.1",
|
|
42
|
-
"@fuzdev/fuz_code": "^0.
|
|
43
|
-
"@fuzdev/fuz_css": "^0.
|
|
44
|
-
"@fuzdev/fuz_ui": "^0.
|
|
45
|
-
"@fuzdev/fuz_util": "^0.
|
|
42
|
+
"@fuzdev/fuz_code": "^0.41.0",
|
|
43
|
+
"@fuzdev/fuz_css": "^0.47.0",
|
|
44
|
+
"@fuzdev/fuz_ui": "^0.181.1",
|
|
45
|
+
"@fuzdev/fuz_util": "^0.48.3",
|
|
46
46
|
"@ryanatkn/eslint-config": "^0.9.0",
|
|
47
|
-
"@ryanatkn/gro": "^0.
|
|
47
|
+
"@ryanatkn/gro": "^0.190.0",
|
|
48
48
|
"@sveltejs/adapter-static": "^3.0.10",
|
|
49
|
-
"@sveltejs/kit": "^2.
|
|
49
|
+
"@sveltejs/kit": "^2.50.1",
|
|
50
50
|
"@sveltejs/package": "^2.5.7",
|
|
51
|
-
"@sveltejs/vite-plugin-svelte": "^6.2.
|
|
51
|
+
"@sveltejs/vite-plugin-svelte": "^6.2.4",
|
|
52
52
|
"@types/node": "^24.10.1",
|
|
53
53
|
"@webref/css": "^8.2.0",
|
|
54
54
|
"eslint": "^9.39.1",
|
|
55
55
|
"eslint-plugin-svelte": "^3.13.1",
|
|
56
56
|
"prettier": "^3.7.4",
|
|
57
57
|
"prettier-plugin-svelte": "^3.4.1",
|
|
58
|
-
"svelte": "^5.
|
|
59
|
-
"svelte-check": "^4.3.
|
|
58
|
+
"svelte": "^5.49.1",
|
|
59
|
+
"svelte-check": "^4.3.6",
|
|
60
60
|
"tslib": "^2.8.1",
|
|
61
61
|
"typescript": "^5.9.3",
|
|
62
62
|
"typescript-eslint": "^8.48.1",
|
|
@@ -27,10 +27,7 @@ export const Args = z.strictObject({
|
|
|
27
27
|
.enum(['exact', 'caret', 'tilde'])
|
|
28
28
|
.meta({description: 'version strategy for peer dependencies'})
|
|
29
29
|
.default('caret' as const),
|
|
30
|
-
|
|
31
|
-
.boolean()
|
|
32
|
-
.meta({description: 'perform a dry run without actually publishing'})
|
|
33
|
-
.default(false),
|
|
30
|
+
wetrun: z.boolean().meta({description: 'actually publish (default is dry run)'}).default(false),
|
|
34
31
|
format: z
|
|
35
32
|
.enum(['stdout', 'json', 'markdown'])
|
|
36
33
|
.meta({description: 'output format'})
|
|
@@ -63,7 +60,7 @@ export const task: Task<Args> = {
|
|
|
63
60
|
config,
|
|
64
61
|
dir,
|
|
65
62
|
peer_strategy,
|
|
66
|
-
|
|
63
|
+
wetrun,
|
|
67
64
|
format,
|
|
68
65
|
deploy,
|
|
69
66
|
plan,
|
|
@@ -82,7 +79,7 @@ export const task: Task<Args> = {
|
|
|
82
79
|
});
|
|
83
80
|
|
|
84
81
|
// Show plan if requested (skip for dry runs)
|
|
85
|
-
if (plan &&
|
|
82
|
+
if (plan && wetrun) {
|
|
86
83
|
log.info(st('cyan', 'Publishing Plan'));
|
|
87
84
|
const plan_result = await generate_publishing_plan(repos, {log, verbose});
|
|
88
85
|
log_publishing_plan(plan_result, log, {verbose});
|
|
@@ -103,7 +100,7 @@ export const task: Task<Args> = {
|
|
|
103
100
|
|
|
104
101
|
// Publishing options
|
|
105
102
|
const options: PublishingOptions = {
|
|
106
|
-
|
|
103
|
+
wetrun,
|
|
107
104
|
update_deps: true, // Always update dependencies
|
|
108
105
|
version_strategy: peer_strategy,
|
|
109
106
|
deploy,
|
|
@@ -153,12 +153,12 @@ export const task: Task<Args> = {
|
|
|
153
153
|
log.error(st('red', ` ✗ gitops_plan failed: ${error}`));
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
// 3. Run gitops_publish
|
|
157
|
-
log.info(st('yellow', 'Running gitops_publish
|
|
156
|
+
// 3. Run gitops_publish (dry run)
|
|
157
|
+
log.info(st('yellow', 'Running gitops_publish (dry run)...'));
|
|
158
158
|
const dry_start = Date.now();
|
|
159
159
|
try {
|
|
160
160
|
const options: PublishingOptions = {
|
|
161
|
-
|
|
161
|
+
wetrun: false,
|
|
162
162
|
update_deps: true,
|
|
163
163
|
log: undefined, // Silent for validation
|
|
164
164
|
};
|
|
@@ -171,27 +171,27 @@ export const task: Task<Args> = {
|
|
|
171
171
|
const errors = result.ok ? 0 : result.failed.length;
|
|
172
172
|
|
|
173
173
|
results.push({
|
|
174
|
-
command: 'gitops_publish
|
|
174
|
+
command: 'gitops_publish (dry run)',
|
|
175
175
|
success: result.ok,
|
|
176
176
|
warnings: 0,
|
|
177
177
|
errors,
|
|
178
178
|
duration: dry_duration,
|
|
179
179
|
});
|
|
180
180
|
|
|
181
|
-
log.info(st('green', ` ✓ gitops_publish
|
|
181
|
+
log.info(st('green', ` ✓ gitops_publish (dry run) completed in ${dry_duration}ms`));
|
|
182
182
|
if (errors > 0) {
|
|
183
183
|
log.error(st('red', ` ❌ Found ${errors} error(s)`));
|
|
184
184
|
}
|
|
185
185
|
} catch (error) {
|
|
186
186
|
const dry_duration = Date.now() - dry_start;
|
|
187
187
|
results.push({
|
|
188
|
-
command: 'gitops_publish
|
|
188
|
+
command: 'gitops_publish (dry run)',
|
|
189
189
|
success: false,
|
|
190
190
|
warnings: 0,
|
|
191
191
|
errors: 1,
|
|
192
192
|
duration: dry_duration,
|
|
193
193
|
});
|
|
194
|
-
log.error(st('red', ` ✗ gitops_publish
|
|
194
|
+
log.error(st('red', ` ✗ gitops_publish (dry run) failed: ${error}`));
|
|
195
195
|
}
|
|
196
196
|
|
|
197
197
|
// Summary
|
|
@@ -19,7 +19,7 @@ import {install_with_cache_healing} from './npm_install_helpers.js';
|
|
|
19
19
|
/* eslint-disable no-await-in-loop */
|
|
20
20
|
|
|
21
21
|
export interface PublishingOptions {
|
|
22
|
-
|
|
22
|
+
wetrun: boolean;
|
|
23
23
|
update_deps: boolean;
|
|
24
24
|
version_strategy?: VersionStrategy;
|
|
25
25
|
deploy?: boolean;
|
|
@@ -51,10 +51,10 @@ export const publish_repos = async (
|
|
|
51
51
|
options: PublishingOptions,
|
|
52
52
|
): Promise<PublishingResult> => {
|
|
53
53
|
const start_time = Date.now();
|
|
54
|
-
const {
|
|
54
|
+
const {wetrun, update_deps, log, ops = default_gitops_operations} = options;
|
|
55
55
|
|
|
56
56
|
// Preflight checks (skip for dry runs since we're not actually publishing)
|
|
57
|
-
if (
|
|
57
|
+
if (wetrun) {
|
|
58
58
|
const preflight_options: PreflightOptions = {
|
|
59
59
|
skip_changesets: false, // Always check for changesets
|
|
60
60
|
required_branch: 'main',
|
|
@@ -73,7 +73,7 @@ export const publish_repos = async (
|
|
|
73
73
|
throw new TaskError(`Preflight checks failed: ${preflight.errors.join(', ')}`);
|
|
74
74
|
}
|
|
75
75
|
} else {
|
|
76
|
-
log?.info('⏭️ Skipping preflight checks
|
|
76
|
+
log?.info('⏭️ Skipping preflight checks (dry run)');
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
// Build dependency graph and validate
|
|
@@ -131,7 +131,7 @@ export const publish_repos = async (
|
|
|
131
131
|
// Skip packages without changesets
|
|
132
132
|
// In real publish: They might get auto-changesets during dependency updates
|
|
133
133
|
// In dry run: We can't simulate auto-changesets, so just skip
|
|
134
|
-
if (
|
|
134
|
+
if (!wetrun) {
|
|
135
135
|
// Silent skip in dry run - plan shows which packages get auto-changesets
|
|
136
136
|
continue;
|
|
137
137
|
} else {
|
|
@@ -152,7 +152,7 @@ export const publish_repos = async (
|
|
|
152
152
|
published_count++;
|
|
153
153
|
log?.info(st('green', ` ✅ Published ${pkg_name}@${version.new_version}`));
|
|
154
154
|
|
|
155
|
-
if (
|
|
155
|
+
if (wetrun) {
|
|
156
156
|
// 2. Wait for this package to be available on NPM
|
|
157
157
|
log?.info(` ⏳ Waiting for ${pkg_name}@${version.new_version} on NPM...`);
|
|
158
158
|
const wait_result = await ops.npm.wait_for_package({
|
|
@@ -221,7 +221,7 @@ export const publish_repos = async (
|
|
|
221
221
|
|
|
222
222
|
// Phase 1b: Batch install dependencies for repos with updated package.json
|
|
223
223
|
// This ensures workspace stays consistent before next iteration
|
|
224
|
-
if (
|
|
224
|
+
if (wetrun && !options.skip_install && changed_in_iteration.size > 0) {
|
|
225
225
|
log?.info(st('cyan', '\n📦 Installing dependencies for updated repos...\n'));
|
|
226
226
|
|
|
227
227
|
for (const pkg_name of changed_in_iteration) {
|
|
@@ -269,7 +269,7 @@ export const publish_repos = async (
|
|
|
269
269
|
// Phase 2: Update all dev dependencies (can have cycles)
|
|
270
270
|
// Dev dep changes require deployment even without version bumps (rebuild needed)
|
|
271
271
|
const dev_updated_repos: Set<string> = new Set();
|
|
272
|
-
if (update_deps && published.size > 0 &&
|
|
272
|
+
if (update_deps && published.size > 0 && wetrun) {
|
|
273
273
|
log?.info(st('cyan', '\n🔄 Updating dev dependencies...\n'));
|
|
274
274
|
|
|
275
275
|
for (const repo of repos) {
|
|
@@ -300,7 +300,7 @@ export const publish_repos = async (
|
|
|
300
300
|
}
|
|
301
301
|
|
|
302
302
|
// Phase 2b: Install dev dependencies for repos with dev dep updates
|
|
303
|
-
if (
|
|
303
|
+
if (wetrun && !options.skip_install && dev_updated_repos.size > 0) {
|
|
304
304
|
log?.info(st('cyan', '\n📦 Installing dev dependencies for updated repos...\n'));
|
|
305
305
|
|
|
306
306
|
for (const pkg_name of dev_updated_repos) {
|
|
@@ -322,7 +322,7 @@ export const publish_repos = async (
|
|
|
322
322
|
|
|
323
323
|
// Phase 3: Deploy repos with changes (optional)
|
|
324
324
|
// Deploys only repos that were: published, had prod/peer deps updated, or had dev deps updated
|
|
325
|
-
if (options.deploy &&
|
|
325
|
+
if (options.deploy && wetrun) {
|
|
326
326
|
const repos_to_deploy = repos.filter((r) => changed_repos.has(r.library.name));
|
|
327
327
|
log?.info(
|
|
328
328
|
st(
|
|
@@ -390,11 +390,11 @@ const publish_single_repo = async (
|
|
|
390
390
|
options: PublishingOptions,
|
|
391
391
|
ops: GitopsOperations = default_gitops_operations,
|
|
392
392
|
): Promise<PublishedVersion> => {
|
|
393
|
-
const {
|
|
393
|
+
const {wetrun, log} = options;
|
|
394
394
|
|
|
395
395
|
const old_version = repo.library.package_json.version || '0.0.0';
|
|
396
396
|
|
|
397
|
-
if (
|
|
397
|
+
if (!wetrun) {
|
|
398
398
|
// In dry run, predict version from changesets
|
|
399
399
|
const prediction = await ops.changeset.predict_next_version({repo, log});
|
|
400
400
|
|
|
@@ -417,7 +417,7 @@ const publish_single_repo = async (
|
|
|
417
417
|
new_version,
|
|
418
418
|
bump_type,
|
|
419
419
|
breaking,
|
|
420
|
-
commit: '
|
|
420
|
+
commit: 'simulated',
|
|
421
421
|
tag: `v${new_version}`,
|
|
422
422
|
};
|
|
423
423
|
}
|
|
@@ -302,9 +302,9 @@ export const log_publishing_plan = (
|
|
|
302
302
|
}
|
|
303
303
|
};
|
|
304
304
|
|
|
305
|
-
//
|
|
305
|
+
//
|
|
306
306
|
// Verbose logging functions
|
|
307
|
-
//
|
|
307
|
+
//
|
|
308
308
|
|
|
309
309
|
/**
|
|
310
310
|
* Logs all verbose sections in order.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - Dependency graph structures (`SerializedGraph`)
|
|
7
7
|
* - Publishing plan predictions (`SerializedPublishingPlan`)
|
|
8
8
|
*
|
|
9
|
-
* Used by `gitops_analyze`, `gitops_plan`, and `gitops_publish
|
|
9
|
+
* Used by `gitops_analyze`, `gitops_plan`, and `gitops_publish` (dry run) when
|
|
10
10
|
* `--format json` or `--outfile` is specified.
|
|
11
11
|
*
|
|
12
12
|
* @module
|