@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
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import type {Logger} from '@fuzdev/fuz_util/log.
|
|
2
|
-
import {TaskError} from '@fuzdev/gro';
|
|
3
|
-
import {join} from 'node:path';
|
|
4
|
-
import {styleText as st} from 'node:util';
|
|
1
|
+
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
2
|
+
import { TaskError } from '@fuzdev/gro';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { styleText as st } from 'node:util';
|
|
5
5
|
|
|
6
|
-
import type
|
|
7
|
-
import {update_package_json, type VersionStrategy} from './dependency_updater.
|
|
6
|
+
import { repo_is_npm, type LocalRepo } from './local_repo.ts';
|
|
7
|
+
import { update_package_json, type VersionStrategy } from './dependency_updater.ts';
|
|
8
8
|
import {
|
|
9
9
|
generate_publishing_plan,
|
|
10
10
|
type VersionChange,
|
|
11
11
|
type DependencyUpdate,
|
|
12
|
-
type PublishingPlan
|
|
13
|
-
} from './publishing_plan.
|
|
14
|
-
import type {PreflightOptions} from './preflight_checks.
|
|
15
|
-
import type {GitopsOperations} from './operations.
|
|
16
|
-
import {default_gitops_operations} from './operations_defaults.
|
|
17
|
-
import {GITOPS_NPM_WAIT_TIMEOUT_DEFAULT} from './gitops_constants.
|
|
12
|
+
type PublishingPlan
|
|
13
|
+
} from './publishing_plan.ts';
|
|
14
|
+
import type { PreflightOptions } from './preflight_checks.ts';
|
|
15
|
+
import type { GitopsOperations } from './operations.ts';
|
|
16
|
+
import { default_gitops_operations } from './operations_defaults.ts';
|
|
17
|
+
import { GITOPS_NPM_WAIT_TIMEOUT_DEFAULT } from './gitops_constants.ts';
|
|
18
18
|
import {
|
|
19
19
|
type PublishingEvent,
|
|
20
20
|
type PublishingRunSummary,
|
|
21
|
-
summarize_events
|
|
22
|
-
} from './publishing_event.
|
|
21
|
+
summarize_events
|
|
22
|
+
} from './publishing_event.ts';
|
|
23
23
|
import {
|
|
24
24
|
type PublishingEventHandler,
|
|
25
25
|
capture_handler,
|
|
26
|
-
multi_handler
|
|
27
|
-
} from './publishing_event_handler.
|
|
26
|
+
multi_handler
|
|
27
|
+
} from './publishing_event_handler.ts';
|
|
28
28
|
|
|
29
29
|
export interface PublishingOptions {
|
|
30
30
|
wetrun: boolean;
|
|
@@ -50,7 +50,7 @@ export interface PublishedVersion {
|
|
|
50
50
|
export interface PublishingResult {
|
|
51
51
|
ok: boolean;
|
|
52
52
|
published: Array<PublishedVersion>;
|
|
53
|
-
failed: Array<{name: string; error: Error}>;
|
|
53
|
+
failed: Array<{ name: string; error: Error }>;
|
|
54
54
|
duration: number;
|
|
55
55
|
/** The structured event stream for this run, in emission order. */
|
|
56
56
|
events: Array<PublishingEvent>;
|
|
@@ -64,13 +64,13 @@ export interface PublishingResult {
|
|
|
64
64
|
|
|
65
65
|
export const publish_repos = async (
|
|
66
66
|
repos: Array<LocalRepo>,
|
|
67
|
-
options: PublishingOptions
|
|
67
|
+
options: PublishingOptions
|
|
68
68
|
): Promise<PublishingResult> => {
|
|
69
|
-
const {log, ops = default_gitops_operations} = options;
|
|
69
|
+
const { log, ops = default_gitops_operations } = options;
|
|
70
70
|
// Convenience entry: generate the plan, then execute it. Callers that already hold a
|
|
71
71
|
// plan (e.g. to display and confirm it first) call `execute_publishing_plan` directly,
|
|
72
72
|
// so the plan is generated exactly once per command.
|
|
73
|
-
const plan = await generate_publishing_plan(repos, {log, ops: ops.changeset});
|
|
73
|
+
const plan = await generate_publishing_plan(repos, { log, ops: ops.changeset });
|
|
74
74
|
return execute_publishing_plan(repos, plan, options);
|
|
75
75
|
};
|
|
76
76
|
|
|
@@ -83,19 +83,23 @@ export const publish_repos = async (
|
|
|
83
83
|
* `ok: false`. This is the single error gate — `--no-plan` can't bypass it.
|
|
84
84
|
*/
|
|
85
85
|
export const execute_publishing_plan = async (
|
|
86
|
-
|
|
86
|
+
all_repos: Array<LocalRepo>,
|
|
87
87
|
plan: PublishingPlan,
|
|
88
|
-
options: PublishingOptions
|
|
88
|
+
options: PublishingOptions
|
|
89
89
|
): Promise<PublishingResult> => {
|
|
90
90
|
const start_time = Date.now();
|
|
91
|
-
const {wetrun, log, ops = default_gitops_operations} = options;
|
|
91
|
+
const { wetrun, log, ops = default_gitops_operations } = options;
|
|
92
|
+
|
|
93
|
+
// Only npm repos publish; drop any non-npm repos (e.g. cargo) so preflight and the
|
|
94
|
+
// executor's name lookup never touch them. The plan already excludes them too.
|
|
95
|
+
const repos = all_repos.filter(repo_is_npm);
|
|
92
96
|
|
|
93
97
|
// Fail loud on an incomplete plan. Executing one with errors would silently skip the
|
|
94
98
|
// affected packages. A wetrun aborts before touching npm or git; a dry run proceeds
|
|
95
99
|
// (no side effects) but the result is not ok (see the summary below).
|
|
96
100
|
if (wetrun && plan.errors.length > 0) {
|
|
97
101
|
throw new TaskError(
|
|
98
|
-
`Cannot publish — the plan has ${plan.errors.length} error(s):\n ${plan.errors.join('\n ')}
|
|
102
|
+
`Cannot publish — the plan has ${plan.errors.length} error(s):\n ${plan.errors.join('\n ')}`
|
|
99
103
|
);
|
|
100
104
|
}
|
|
101
105
|
|
|
@@ -111,7 +115,7 @@ export const execute_publishing_plan = async (
|
|
|
111
115
|
const preflight_options: PreflightOptions = {
|
|
112
116
|
skip_changesets: false, // Always check for changesets
|
|
113
117
|
required_branch: 'main',
|
|
114
|
-
log
|
|
118
|
+
log
|
|
115
119
|
};
|
|
116
120
|
const preflight = await ops.preflight.run_preflight_checks({
|
|
117
121
|
repos,
|
|
@@ -119,7 +123,7 @@ export const execute_publishing_plan = async (
|
|
|
119
123
|
git_ops: ops.git,
|
|
120
124
|
npm_ops: ops.npm,
|
|
121
125
|
build_ops: ops.build,
|
|
122
|
-
changeset_ops: ops.changeset
|
|
126
|
+
changeset_ops: ops.changeset
|
|
123
127
|
});
|
|
124
128
|
|
|
125
129
|
if (!preflight.ok) {
|
|
@@ -134,13 +138,13 @@ export const execute_publishing_plan = async (
|
|
|
134
138
|
// frozen topological order directly, re-deriving nothing.
|
|
135
139
|
const order = plan.publishing_order;
|
|
136
140
|
const plan_changes: Map<string, VersionChange> = new Map(
|
|
137
|
-
plan.version_changes.map((vc) => [vc.package_name, vc])
|
|
141
|
+
plan.version_changes.map((vc) => [vc.package_name, vc])
|
|
138
142
|
);
|
|
139
143
|
if (order.length > 0) {
|
|
140
144
|
log?.info(` Publishing order: ${order.join(' → ')}`);
|
|
141
145
|
}
|
|
142
146
|
|
|
143
|
-
emit({event: 'run_started', wetrun, total: order.length});
|
|
147
|
+
emit({ event: 'run_started', wetrun, total: order.length });
|
|
144
148
|
|
|
145
149
|
const published: Map<string, PublishedVersion> = new Map();
|
|
146
150
|
const failed: Map<string, Error> = new Map();
|
|
@@ -161,7 +165,7 @@ export const execute_publishing_plan = async (
|
|
|
161
165
|
|
|
162
166
|
// Not in the plan = no changesets and no dependency updates = nothing to publish.
|
|
163
167
|
if (!planned) {
|
|
164
|
-
emit({event: 'package_skipped', name: pkg_name, reason: 'no changesets'});
|
|
168
|
+
emit({ event: 'package_skipped', name: pkg_name, reason: 'no changesets' });
|
|
165
169
|
log?.info(st('yellow', ` ⚠️ Skipping ${pkg_name} - no changesets`));
|
|
166
170
|
continue;
|
|
167
171
|
}
|
|
@@ -178,8 +182,8 @@ export const execute_publishing_plan = async (
|
|
|
178
182
|
log?.info(
|
|
179
183
|
st(
|
|
180
184
|
'dim',
|
|
181
|
-
` [${i + 1}/${order.length}] ${wetrun ? 'Publishing' : 'Would publish'} ${pkg_name}
|
|
182
|
-
)
|
|
185
|
+
` [${i + 1}/${order.length}] ${wetrun ? 'Publishing' : 'Would publish'} ${pkg_name}...`
|
|
186
|
+
)
|
|
183
187
|
);
|
|
184
188
|
const version = await publish_single_repo(repo, options, ops, planned);
|
|
185
189
|
|
|
@@ -190,10 +194,10 @@ export const execute_publishing_plan = async (
|
|
|
190
194
|
if (wetrun && version.new_version !== planned.to) {
|
|
191
195
|
const err = new Error(
|
|
192
196
|
`Plan drift for ${pkg_name}: published ${version.new_version} but the plan predicted ${planned.to}. ` +
|
|
193
|
-
`Aborting — re-run 'gro gitops_publish --wetrun' to re-plan from the current state
|
|
197
|
+
`Aborting — re-run 'gro gitops_publish --wetrun' to re-plan from the current state.`
|
|
194
198
|
);
|
|
195
199
|
failed.set(pkg_name, err);
|
|
196
|
-
emit({event: 'package_failed', name: pkg_name, error: err.message, code: 'drift'});
|
|
200
|
+
emit({ event: 'package_failed', name: pkg_name, error: err.message, code: 'drift' });
|
|
197
201
|
log?.error(st('red', ` ❌ ${err.message}`));
|
|
198
202
|
break;
|
|
199
203
|
}
|
|
@@ -208,12 +212,12 @@ export const execute_publishing_plan = async (
|
|
|
208
212
|
bump_type: version.bump_type,
|
|
209
213
|
breaking: version.breaking,
|
|
210
214
|
commit: version.commit,
|
|
211
|
-
tag: version.tag
|
|
215
|
+
tag: version.tag
|
|
212
216
|
});
|
|
213
217
|
log?.info(
|
|
214
218
|
wetrun
|
|
215
219
|
? st('green', ` ✅ Published ${pkg_name}@${version.new_version}`)
|
|
216
|
-
: st('cyan', ` ◇ Would publish ${pkg_name}@${version.new_version}`)
|
|
220
|
+
: st('cyan', ` ◇ Would publish ${pkg_name}@${version.new_version}`)
|
|
217
221
|
);
|
|
218
222
|
|
|
219
223
|
if (wetrun) {
|
|
@@ -226,9 +230,9 @@ export const execute_publishing_plan = async (
|
|
|
226
230
|
max_attempts: 30,
|
|
227
231
|
initial_delay: 1000,
|
|
228
232
|
max_delay: 60000,
|
|
229
|
-
timeout: options.max_wait ?? GITOPS_NPM_WAIT_TIMEOUT_DEFAULT
|
|
233
|
+
timeout: options.max_wait ?? GITOPS_NPM_WAIT_TIMEOUT_DEFAULT
|
|
230
234
|
},
|
|
231
|
-
log
|
|
235
|
+
log
|
|
232
236
|
});
|
|
233
237
|
|
|
234
238
|
if (!wait_result.ok) {
|
|
@@ -236,14 +240,14 @@ export const execute_publishing_plan = async (
|
|
|
236
240
|
// carries a typed `timeout` signal, so we know this is a network failure
|
|
237
241
|
// without sniffing the message.
|
|
238
242
|
const err = new Error(
|
|
239
|
-
`Failed to wait for package: ${wait_result.message}${wait_result.timeout ? ' (timeout)' : ''}
|
|
243
|
+
`Failed to wait for package: ${wait_result.message}${wait_result.timeout ? ' (timeout)' : ''}`
|
|
240
244
|
);
|
|
241
245
|
failed.set(pkg_name, err);
|
|
242
|
-
emit({event: 'package_failed', name: pkg_name, error: err.message, code: 'network'});
|
|
246
|
+
emit({ event: 'package_failed', name: pkg_name, error: err.message, code: 'network' });
|
|
243
247
|
log?.error(st('red', ` ❌ Failed to publish ${pkg_name}: ${err.message}`));
|
|
244
248
|
break; // fail fast
|
|
245
249
|
}
|
|
246
|
-
emit({event: 'npm_waited', name: pkg_name, version: version.new_version});
|
|
250
|
+
emit({ event: 'npm_waited', name: pkg_name, version: version.new_version });
|
|
247
251
|
|
|
248
252
|
// 3. Update every dependent the plan says has a prod/peer dep on this package.
|
|
249
253
|
// This rewrites their package.json ranges and creates their auto-changeset,
|
|
@@ -254,7 +258,7 @@ export const execute_publishing_plan = async (
|
|
|
254
258
|
published,
|
|
255
259
|
(update) =>
|
|
256
260
|
update.updated_dependency === pkg_name &&
|
|
257
|
-
(update.type === 'dependencies' || update.type === 'peerDependencies')
|
|
261
|
+
(update.type === 'dependencies' || update.type === 'peerDependencies')
|
|
258
262
|
);
|
|
259
263
|
for (const [dependent_name, updates] of dependent_updates) {
|
|
260
264
|
const dependent_repo = repo_by_name.get(dependent_name);
|
|
@@ -273,7 +277,7 @@ export const execute_publishing_plan = async (
|
|
|
273
277
|
dependency: dep_name,
|
|
274
278
|
version: dep_version,
|
|
275
279
|
dep_type: dependency_update_type(plan, dependent_name, dep_name),
|
|
276
|
-
creates_changeset: republishes
|
|
280
|
+
creates_changeset: republishes
|
|
277
281
|
});
|
|
278
282
|
}
|
|
279
283
|
changed_repos.add(dependent_name); // Mark as changed for deployment
|
|
@@ -283,7 +287,7 @@ export const execute_publishing_plan = async (
|
|
|
283
287
|
published_versions: published, // creates the auto-changeset
|
|
284
288
|
log,
|
|
285
289
|
git_ops: ops.git,
|
|
286
|
-
fs_ops: ops.fs
|
|
290
|
+
fs_ops: ops.fs
|
|
287
291
|
});
|
|
288
292
|
} else {
|
|
289
293
|
// update-only leaf: rewrite ranges + commit, no changeset (it won't republish)
|
|
@@ -291,7 +295,7 @@ export const execute_publishing_plan = async (
|
|
|
291
295
|
strategy: options.version_strategy || 'caret',
|
|
292
296
|
log,
|
|
293
297
|
git_ops: ops.git,
|
|
294
|
-
fs_ops: ops.fs
|
|
298
|
+
fs_ops: ops.fs
|
|
295
299
|
});
|
|
296
300
|
}
|
|
297
301
|
}
|
|
@@ -306,7 +310,7 @@ export const execute_publishing_plan = async (
|
|
|
306
310
|
// TODO: emit a precise code once the npm/process ops return typed errors —
|
|
307
311
|
// today a publish-step cause lives in unstructured stderr, so use the honest
|
|
308
312
|
// coarse bucket rather than guessing 'auth'/'network'/'build' from the message.
|
|
309
|
-
code: 'publish'
|
|
313
|
+
code: 'publish'
|
|
310
314
|
});
|
|
311
315
|
log?.error(st('red', ` ❌ Failed to publish ${pkg_name}: ${err.message}`));
|
|
312
316
|
break; // Always fail fast on error
|
|
@@ -323,7 +327,7 @@ export const execute_publishing_plan = async (
|
|
|
323
327
|
const dev_updates_by_repo = group_dependency_updates(
|
|
324
328
|
plan.dependency_updates,
|
|
325
329
|
published,
|
|
326
|
-
(update) => update.type === 'devDependencies'
|
|
330
|
+
(update) => update.type === 'devDependencies'
|
|
327
331
|
);
|
|
328
332
|
|
|
329
333
|
if (dev_updates_by_repo.size > 0) {
|
|
@@ -342,7 +346,7 @@ export const execute_publishing_plan = async (
|
|
|
342
346
|
dependency: dep_name,
|
|
343
347
|
version: dep_version,
|
|
344
348
|
dep_type: 'dev',
|
|
345
|
-
creates_changeset: false
|
|
349
|
+
creates_changeset: false // dev-dep updates redeploy without republishing
|
|
346
350
|
});
|
|
347
351
|
}
|
|
348
352
|
changed_repos.add(repo_name); // Mark as changed for deployment
|
|
@@ -353,7 +357,7 @@ export const execute_publishing_plan = async (
|
|
|
353
357
|
strategy: options.version_strategy || 'caret',
|
|
354
358
|
log,
|
|
355
359
|
git_ops: ops.git,
|
|
356
|
-
fs_ops: ops.fs
|
|
360
|
+
fs_ops: ops.fs
|
|
357
361
|
});
|
|
358
362
|
}
|
|
359
363
|
}
|
|
@@ -367,15 +371,12 @@ export const execute_publishing_plan = async (
|
|
|
367
371
|
.map((name) => repo_by_name.get(name))
|
|
368
372
|
.filter((r): r is LocalRepo => r !== undefined);
|
|
369
373
|
log?.info(
|
|
370
|
-
st(
|
|
371
|
-
'cyan',
|
|
372
|
-
`\n🚢 Deploying ${repos_to_deploy.length}/${repos.length} repos with changes...\n`,
|
|
373
|
-
),
|
|
374
|
+
st('cyan', `\n🚢 Deploying ${repos_to_deploy.length}/${repos.length} repos with changes...\n`)
|
|
374
375
|
);
|
|
375
376
|
|
|
376
377
|
for (const repo of repos_to_deploy) {
|
|
377
378
|
try {
|
|
378
|
-
emit({event: 'deploy_started', name: repo.library.name});
|
|
379
|
+
emit({ event: 'deploy_started', name: repo.library.name });
|
|
379
380
|
log?.info(` Deploying ${repo.library.name}...`);
|
|
380
381
|
// Build fresh (no --no-build): a deployed site bundles its dependencies, so it
|
|
381
382
|
// must be rebuilt against the versions this run just published — the preflight
|
|
@@ -383,19 +384,19 @@ export const execute_publishing_plan = async (
|
|
|
383
384
|
const deploy_result = await ops.process.spawn({
|
|
384
385
|
cmd: 'gro',
|
|
385
386
|
args: ['deploy'],
|
|
386
|
-
cwd: repo.repo_dir
|
|
387
|
+
cwd: repo.repo_dir
|
|
387
388
|
});
|
|
388
389
|
|
|
389
390
|
if (deploy_result.ok) {
|
|
390
|
-
emit({event: 'deploy_completed', name: repo.library.name});
|
|
391
|
+
emit({ event: 'deploy_completed', name: repo.library.name });
|
|
391
392
|
log?.info(st('green', ` ✅ Deployed ${repo.library.name}`));
|
|
392
393
|
} else {
|
|
393
|
-
emit({event: 'deploy_failed', name: repo.library.name, error: deploy_result.message});
|
|
394
|
+
emit({ event: 'deploy_failed', name: repo.library.name, error: deploy_result.message });
|
|
394
395
|
log?.warn(st('yellow', ` ⚠️ Failed to deploy ${repo.library.name}`));
|
|
395
396
|
}
|
|
396
397
|
} catch (error) {
|
|
397
398
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
398
|
-
emit({event: 'deploy_failed', name: repo.library.name, error: err.message});
|
|
399
|
+
emit({ event: 'deploy_failed', name: repo.library.name, error: err.message });
|
|
399
400
|
log?.error(st('red', ` ❌ Error deploying ${repo.library.name}: ${err.message}`));
|
|
400
401
|
}
|
|
401
402
|
}
|
|
@@ -431,8 +432,8 @@ export const execute_publishing_plan = async (
|
|
|
431
432
|
log?.info(
|
|
432
433
|
st(
|
|
433
434
|
'green',
|
|
434
|
-
`\n✨ Dry run complete — ${published.size} package(s) would be published. Re-run with --wetrun to publish
|
|
435
|
-
)
|
|
435
|
+
`\n✨ Dry run complete — ${published.size} package(s) would be published. Re-run with --wetrun to publish.`
|
|
436
|
+
)
|
|
436
437
|
);
|
|
437
438
|
// The dry run is driven by the same plan as `gro gitops_plan`, so this
|
|
438
439
|
// count includes bump escalations and auto-generated changesets — it
|
|
@@ -445,22 +446,22 @@ export const execute_publishing_plan = async (
|
|
|
445
446
|
'red',
|
|
446
447
|
wetrun
|
|
447
448
|
? '\n❌ Some packages failed to publish\n'
|
|
448
|
-
: '\n❌ Some packages failed during dry run\n'
|
|
449
|
-
)
|
|
449
|
+
: '\n❌ Some packages failed during dry run\n'
|
|
450
|
+
)
|
|
450
451
|
);
|
|
451
452
|
}
|
|
452
453
|
|
|
453
|
-
emit({event: 'run_finished', summary});
|
|
454
|
+
emit({ event: 'run_finished', summary });
|
|
454
455
|
|
|
455
456
|
return {
|
|
456
457
|
ok,
|
|
457
458
|
published: Array.from(published.values()),
|
|
458
|
-
failed: Array.from(failed.entries()).map(([name, error]) => ({name, error})),
|
|
459
|
+
failed: Array.from(failed.entries()).map(([name, error]) => ({ name, error })),
|
|
459
460
|
duration,
|
|
460
461
|
events: capture.events,
|
|
461
462
|
summary,
|
|
462
463
|
plan_errors: plan.errors,
|
|
463
|
-
plan_warnings: plan.warnings
|
|
464
|
+
plan_warnings: plan.warnings
|
|
464
465
|
};
|
|
465
466
|
};
|
|
466
467
|
|
|
@@ -479,9 +480,9 @@ const publish_single_repo = async (
|
|
|
479
480
|
repo: LocalRepo,
|
|
480
481
|
options: PublishingOptions,
|
|
481
482
|
ops: GitopsOperations,
|
|
482
|
-
planned: VersionChange
|
|
483
|
+
planned: VersionChange
|
|
483
484
|
): Promise<PublishedVersion> => {
|
|
484
|
-
const {wetrun} = options;
|
|
485
|
+
const { wetrun } = options;
|
|
485
486
|
|
|
486
487
|
if (!wetrun) {
|
|
487
488
|
// Dry run reports the precomputed plan — the single source of truth for the
|
|
@@ -493,7 +494,7 @@ const publish_single_repo = async (
|
|
|
493
494
|
bump_type: planned.bump_type,
|
|
494
495
|
breaking: planned.breaking,
|
|
495
496
|
commit: 'simulated',
|
|
496
|
-
tag: `v${planned.to}
|
|
497
|
+
tag: `v${planned.to}`
|
|
497
498
|
};
|
|
498
499
|
}
|
|
499
500
|
|
|
@@ -501,7 +502,7 @@ const publish_single_repo = async (
|
|
|
501
502
|
const publish_result = await ops.process.spawn({
|
|
502
503
|
cmd: 'gro',
|
|
503
504
|
args: ['publish', '--no-build'],
|
|
504
|
-
cwd: repo.repo_dir
|
|
505
|
+
cwd: repo.repo_dir
|
|
505
506
|
});
|
|
506
507
|
|
|
507
508
|
if (!publish_result.ok) {
|
|
@@ -510,7 +511,7 @@ const publish_single_repo = async (
|
|
|
510
511
|
|
|
511
512
|
// Read the new version from package.json after gro publish
|
|
512
513
|
const package_json_path = join(repo.repo_dir, 'package.json');
|
|
513
|
-
const content_result = await ops.fs.readFile({path: package_json_path, encoding: 'utf8'});
|
|
514
|
+
const content_result = await ops.fs.readFile({ path: package_json_path, encoding: 'utf8' });
|
|
514
515
|
|
|
515
516
|
if (!content_result.ok) {
|
|
516
517
|
throw new Error(`Failed to read package.json: ${content_result.message}`);
|
|
@@ -520,7 +521,7 @@ const publish_single_repo = async (
|
|
|
520
521
|
const new_version = package_json.version;
|
|
521
522
|
|
|
522
523
|
// Get actual commit hash
|
|
523
|
-
const commit_result = await ops.git.current_commit_hash({cwd: repo.repo_dir});
|
|
524
|
+
const commit_result = await ops.git.current_commit_hash({ cwd: repo.repo_dir });
|
|
524
525
|
|
|
525
526
|
if (!commit_result.ok) {
|
|
526
527
|
throw new Error(`Failed to get commit hash: ${commit_result.message}`);
|
|
@@ -537,7 +538,7 @@ const publish_single_repo = async (
|
|
|
537
538
|
bump_type: planned.bump_type,
|
|
538
539
|
breaking: planned.breaking,
|
|
539
540
|
commit,
|
|
540
|
-
tag: `v${new_version}
|
|
541
|
+
tag: `v${new_version}`
|
|
541
542
|
};
|
|
542
543
|
};
|
|
543
544
|
|
|
@@ -550,7 +551,7 @@ const publish_single_repo = async (
|
|
|
550
551
|
export const group_dependency_updates = (
|
|
551
552
|
updates: Array<DependencyUpdate>,
|
|
552
553
|
published: Map<string, PublishedVersion>,
|
|
553
|
-
predicate: (update: DependencyUpdate) => boolean
|
|
554
|
+
predicate: (update: DependencyUpdate) => boolean
|
|
554
555
|
): Map<string, Map<string, string>> => {
|
|
555
556
|
const by_repo: Map<string, Map<string, string>> = new Map();
|
|
556
557
|
for (const update of updates) {
|
|
@@ -573,13 +574,13 @@ export const group_dependency_updates = (
|
|
|
573
574
|
const dependency_update_type = (
|
|
574
575
|
plan: PublishingPlan,
|
|
575
576
|
dependent: string,
|
|
576
|
-
dependency: string
|
|
577
|
+
dependency: string
|
|
577
578
|
): 'prod' | 'peer' =>
|
|
578
579
|
plan.dependency_updates.some(
|
|
579
580
|
(u) =>
|
|
580
581
|
u.dependent_package === dependent &&
|
|
581
582
|
u.updated_dependency === dependency &&
|
|
582
|
-
u.type === 'peerDependencies'
|
|
583
|
+
u.type === 'peerDependencies'
|
|
583
584
|
)
|
|
584
585
|
? 'peer'
|
|
585
586
|
: 'prod';
|
package/src/lib/npm_registry.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {Logger} from '@fuzdev/fuz_util/log.
|
|
2
|
-
import {spawn_out} from '@fuzdev/fuz_util/process.
|
|
3
|
-
import {wait} from '@fuzdev/fuz_util/async.
|
|
4
|
-
import {styleText as st} from 'node:util';
|
|
1
|
+
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
2
|
+
import { spawn_out } from '@fuzdev/fuz_util/process.ts';
|
|
3
|
+
import { wait } from '@fuzdev/fuz_util/async.ts';
|
|
4
|
+
import { styleText as st } from 'node:util';
|
|
5
5
|
|
|
6
6
|
export interface WaitOptions {
|
|
7
7
|
log?: Logger;
|
|
@@ -19,9 +19,9 @@ export interface PackageInfo {
|
|
|
19
19
|
export const check_package_available = async (
|
|
20
20
|
pkg: string,
|
|
21
21
|
version: string,
|
|
22
|
-
options: {log?: Logger} = {}
|
|
22
|
+
options: { log?: Logger } = {}
|
|
23
23
|
): Promise<boolean> => {
|
|
24
|
-
const {log} = options;
|
|
24
|
+
const { log } = options;
|
|
25
25
|
try {
|
|
26
26
|
// Use npm view to check if the specific version exists
|
|
27
27
|
const result = await spawn_out('npm', ['view', `${pkg}@${version}`, 'version']);
|
|
@@ -57,14 +57,14 @@ export const check_package_available = async (
|
|
|
57
57
|
export const wait_for_package = async (
|
|
58
58
|
pkg: string,
|
|
59
59
|
version: string,
|
|
60
|
-
options: WaitOptions = {}
|
|
60
|
+
options: WaitOptions = {}
|
|
61
61
|
): Promise<void> => {
|
|
62
62
|
const {
|
|
63
63
|
log,
|
|
64
64
|
max_attempts = 30,
|
|
65
65
|
initial_delay = 1000,
|
|
66
66
|
max_delay = 60000,
|
|
67
|
-
timeout = 300000
|
|
67
|
+
timeout = 300000 // 5 minutes default
|
|
68
68
|
} = options;
|
|
69
69
|
|
|
70
70
|
const start_time = Date.now();
|
|
@@ -81,7 +81,7 @@ export const wait_for_package = async (
|
|
|
81
81
|
|
|
82
82
|
// Check if package is available
|
|
83
83
|
|
|
84
|
-
if (await check_package_available(pkg, version, {log})) {
|
|
84
|
+
if (await check_package_available(pkg, version, { log })) {
|
|
85
85
|
log?.info(st('green', ` ✓ ${pkg}@${version} is now available on NPM`));
|
|
86
86
|
return;
|
|
87
87
|
}
|
|
@@ -113,9 +113,9 @@ export const wait_for_package = async (
|
|
|
113
113
|
*/
|
|
114
114
|
export const get_package_info = async (
|
|
115
115
|
pkg: string,
|
|
116
|
-
options: {log?: Logger} = {}
|
|
116
|
+
options: { log?: Logger } = {}
|
|
117
117
|
): Promise<PackageInfo | null> => {
|
|
118
|
-
const {log} = options;
|
|
118
|
+
const { log } = options;
|
|
119
119
|
try {
|
|
120
120
|
const result = await spawn_out('npm', ['view', pkg, '--json']);
|
|
121
121
|
|
|
@@ -123,7 +123,7 @@ export const get_package_info = async (
|
|
|
123
123
|
const data = JSON.parse(result.stdout);
|
|
124
124
|
return {
|
|
125
125
|
name: data.name,
|
|
126
|
-
version: data.version
|
|
126
|
+
version: data.version
|
|
127
127
|
};
|
|
128
128
|
}
|
|
129
129
|
|
|
@@ -136,7 +136,7 @@ export const get_package_info = async (
|
|
|
136
136
|
|
|
137
137
|
export const package_exists = async (
|
|
138
138
|
pkg: string,
|
|
139
|
-
options: {log?: Logger} = {}
|
|
139
|
+
options: { log?: Logger } = {}
|
|
140
140
|
): Promise<boolean> => {
|
|
141
141
|
const info = await get_package_info(pkg, options);
|
|
142
142
|
return info !== null;
|