@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,18 +1,18 @@
|
|
|
1
|
-
import {TaskError, type Task} from '@fuzdev/gro';
|
|
2
|
-
import {z} from 'zod';
|
|
3
|
-
import {readFile, writeFile} from 'node:fs/promises';
|
|
4
|
-
import {format_file} from '@fuzdev/gro/format_file.
|
|
5
|
-
import {basename, resolve} from 'node:path';
|
|
6
|
-
import {print_path} from '@fuzdev/gro/paths.
|
|
7
|
-
import {load_from_env} from '@fuzdev/gro/env.
|
|
8
|
-
import {package_json_load} from '@fuzdev/gro/package_json.
|
|
9
|
-
import {existsSync} from 'node:fs';
|
|
10
|
-
import {compactReplacer} from 'svelte-docinfo';
|
|
11
|
-
|
|
12
|
-
import {fetch_repo_data} from './fetch_repo_data.
|
|
13
|
-
import {create_fs_fetch_value_cache} from './fs_fetch_value_cache.
|
|
14
|
-
import {get_gitops_ready} from './gitops_task_helpers.
|
|
15
|
-
import {GITOPS_CONFIG_PATH_DEFAULT} from './gitops_constants.
|
|
1
|
+
import { TaskError, type Task } from '@fuzdev/gro';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { format_file } from '@fuzdev/gro/format_file.ts';
|
|
5
|
+
import { basename, resolve } from 'node:path';
|
|
6
|
+
import { print_path } from '@fuzdev/gro/paths.ts';
|
|
7
|
+
import { load_from_env } from '@fuzdev/gro/env.ts';
|
|
8
|
+
import { package_json_load } from '@fuzdev/gro/package_json.ts';
|
|
9
|
+
import { existsSync } from 'node:fs';
|
|
10
|
+
import { compactReplacer } from 'svelte-docinfo';
|
|
11
|
+
|
|
12
|
+
import { fetch_repo_data } from './fetch_repo_data.ts';
|
|
13
|
+
import { create_fs_fetch_value_cache } from './fs_fetch_value_cache.ts';
|
|
14
|
+
import { get_gitops_ready } from './gitops_task_helpers.ts';
|
|
15
|
+
import { GITOPS_CONFIG_PATH_DEFAULT } from './gitops_constants.ts';
|
|
16
16
|
|
|
17
17
|
// TODO add flag to ignore or invalidate cache -- no-cache? clean?
|
|
18
18
|
|
|
@@ -20,28 +20,28 @@ import {GITOPS_CONFIG_PATH_DEFAULT} from './gitops_constants.js';
|
|
|
20
20
|
export const Args = z.strictObject({
|
|
21
21
|
config: z
|
|
22
22
|
.string()
|
|
23
|
-
.meta({description: 'path to the gitops config file, absolute or relative to the cwd'})
|
|
23
|
+
.meta({ description: 'path to the gitops config file, absolute or relative to the cwd' })
|
|
24
24
|
.default(GITOPS_CONFIG_PATH_DEFAULT),
|
|
25
25
|
dir: z
|
|
26
26
|
.string()
|
|
27
|
-
.meta({description: 'path containing the repos, defaults to the parent of the config dir'})
|
|
27
|
+
.meta({ description: 'path containing the repos, defaults to the parent of the config dir' })
|
|
28
28
|
.optional(),
|
|
29
29
|
outdir: z
|
|
30
30
|
.string()
|
|
31
|
-
.meta({description: 'path to the directory for the generated files, defaults to $routes/'})
|
|
31
|
+
.meta({ description: 'path to the directory for the generated files, defaults to $routes/' })
|
|
32
32
|
.optional(),
|
|
33
|
-
download: z.boolean().meta({description: 'download all missing local repos'}).default(false),
|
|
33
|
+
download: z.boolean().meta({ description: 'download all missing local repos' }).default(false),
|
|
34
34
|
check: z
|
|
35
35
|
.boolean()
|
|
36
|
-
.meta({description: 'check repos are ready without fetching remote data'})
|
|
36
|
+
.meta({ description: 'check repos are ready without fetching remote data' })
|
|
37
37
|
.default(false),
|
|
38
38
|
allow_dirty: z
|
|
39
39
|
.boolean()
|
|
40
40
|
.meta({
|
|
41
41
|
description:
|
|
42
|
-
'sync (switch branch, pull) tolerating uncommitted changes instead of failing on a dirty workspace'
|
|
42
|
+
'sync (switch branch, pull) tolerating uncommitted changes instead of failing on a dirty workspace'
|
|
43
43
|
})
|
|
44
|
-
.default(false)
|
|
44
|
+
.default(false)
|
|
45
45
|
});
|
|
46
46
|
export type Args = z.infer<typeof Args>;
|
|
47
47
|
|
|
@@ -53,17 +53,26 @@ export type Args = z.infer<typeof Args>;
|
|
|
53
53
|
export const task: Task<Args> = {
|
|
54
54
|
Args,
|
|
55
55
|
summary: 'syncs local repos and generates UI data from repo metadata',
|
|
56
|
-
run: async (
|
|
57
|
-
const {
|
|
56
|
+
run: async (ctx) => {
|
|
57
|
+
const { args, log, invoke_task } = ctx;
|
|
58
|
+
// `ctx.svelte_config` is a lazy getter, so it's only read when `outdir` isn't provided
|
|
59
|
+
const {
|
|
60
|
+
config,
|
|
61
|
+
dir,
|
|
62
|
+
outdir = (await ctx.svelte_config).routes_path,
|
|
63
|
+
download,
|
|
64
|
+
check,
|
|
65
|
+
allow_dirty
|
|
66
|
+
} = args;
|
|
58
67
|
|
|
59
68
|
// `gitops_sync` is the task whose job is to mutate working trees, so it always syncs.
|
|
60
|
-
const {local_repos} = await get_gitops_ready({
|
|
69
|
+
const { local_repos } = await get_gitops_ready({
|
|
61
70
|
config,
|
|
62
71
|
dir,
|
|
63
72
|
download,
|
|
64
73
|
sync: true,
|
|
65
74
|
allow_dirty,
|
|
66
|
-
log
|
|
75
|
+
log
|
|
67
76
|
});
|
|
68
77
|
|
|
69
78
|
const outfile_json = resolve(outdir, 'repos.json');
|
|
@@ -96,8 +105,8 @@ export const task: Task<Args> = {
|
|
|
96
105
|
log.info(`generating ${outfile_json} and ${outfile_ts}`);
|
|
97
106
|
|
|
98
107
|
// Generate repos.json with the raw data
|
|
99
|
-
const json_contents =
|
|
100
|
-
|
|
108
|
+
const json_contents = format_file(JSON.stringify(repos_json, compactReplacer), {
|
|
109
|
+
lang: 'json'
|
|
101
110
|
});
|
|
102
111
|
const existing_json = existsSync(outfile_json) ? await readFile(outfile_json, 'utf8') : '';
|
|
103
112
|
const json_changed = existing_json !== json_contents;
|
|
@@ -123,7 +132,7 @@ export const task: Task<Args> = {
|
|
|
123
132
|
export const repos_json: Array<RepoJson> = json as unknown as Array<RepoJson>;
|
|
124
133
|
`;
|
|
125
134
|
// TODO think about possibly using the `gen` functionality in this task, not sure what the API design could look like
|
|
126
|
-
const formatted_ts =
|
|
135
|
+
const formatted_ts = format_file(ts_contents, { filepath: outfile_ts });
|
|
127
136
|
const existing_ts = existsSync(outfile_ts) ? await readFile(outfile_ts, 'utf8') : '';
|
|
128
137
|
if (existing_ts === formatted_ts) {
|
|
129
138
|
log.info(`no changes to ${print_path(outfile_ts)}`);
|
|
@@ -142,5 +151,5 @@ export const task: Task<Args> = {
|
|
|
142
151
|
} else {
|
|
143
152
|
log.info('repos cache did not change');
|
|
144
153
|
}
|
|
145
|
-
}
|
|
154
|
+
}
|
|
146
155
|
};
|
|
@@ -16,17 +16,17 @@
|
|
|
16
16
|
* @module
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {TaskError} from '@fuzdev/gro';
|
|
20
|
-
import {styleText as st} from 'node:util';
|
|
21
|
-
import {resolve, dirname} from 'node:path';
|
|
22
|
-
import {print_path} from '@fuzdev/gro/paths.
|
|
23
|
-
import type {Logger} from '@fuzdev/fuz_util/log.
|
|
19
|
+
import { TaskError } from '@fuzdev/gro';
|
|
20
|
+
import { styleText as st } from 'node:util';
|
|
21
|
+
import { resolve, dirname } from 'node:path';
|
|
22
|
+
import { print_path } from '@fuzdev/gro/paths.ts';
|
|
23
|
+
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
24
24
|
|
|
25
|
-
import {load_gitops_config, type GitopsConfig} from './gitops_config.
|
|
26
|
-
import {local_repos_load, local_repos_ensure, type LocalRepo} from './local_repo.
|
|
27
|
-
import {resolve_gitops_config} from './resolved_gitops_config.
|
|
28
|
-
import {DEFAULT_REPOS_DIR} from './paths.
|
|
29
|
-
import type {GitOperations, NpmOperations} from './operations.
|
|
25
|
+
import { load_gitops_config, type GitopsConfig } from './gitops_config.ts';
|
|
26
|
+
import { local_repos_load, local_repos_ensure, type LocalRepo } from './local_repo.ts';
|
|
27
|
+
import { resolve_gitops_config } from './resolved_gitops_config.ts';
|
|
28
|
+
import { DEFAULT_REPOS_DIR } from './paths.ts';
|
|
29
|
+
import type { GitOperations, NpmOperations } from './operations.ts';
|
|
30
30
|
|
|
31
31
|
export interface GetGitopsReadyOptions {
|
|
32
32
|
config: string;
|
|
@@ -75,14 +75,14 @@ export interface GetGitopsReadyOptions {
|
|
|
75
75
|
* @throws {TaskError} if config loading or repo resolution fails
|
|
76
76
|
*/
|
|
77
77
|
export const get_gitops_ready = async (
|
|
78
|
-
options: GetGitopsReadyOptions
|
|
78
|
+
options: GetGitopsReadyOptions
|
|
79
79
|
): Promise<{
|
|
80
80
|
config_path: string;
|
|
81
81
|
repos_dir: string;
|
|
82
82
|
gitops_config: GitopsConfig;
|
|
83
83
|
local_repos: Array<LocalRepo>;
|
|
84
84
|
}> => {
|
|
85
|
-
const {config, dir, download, log, git_ops, npm_ops, parallel, concurrency, sync, allow_dirty} =
|
|
85
|
+
const { config, dir, download, log, git_ops, npm_ops, parallel, concurrency, sync, allow_dirty } =
|
|
86
86
|
options;
|
|
87
87
|
const config_path = resolve(config);
|
|
88
88
|
const gitops_config = await import_gitops_config(config_path);
|
|
@@ -91,12 +91,12 @@ export const get_gitops_ready = async (
|
|
|
91
91
|
const repos_dir = resolve_gitops_paths({
|
|
92
92
|
config,
|
|
93
93
|
dir,
|
|
94
|
-
config_repos_dir: gitops_config.repos_dir
|
|
94
|
+
config_repos_dir: gitops_config.repos_dir
|
|
95
95
|
}).repos_dir;
|
|
96
96
|
|
|
97
97
|
log?.info(
|
|
98
98
|
`resolving gitops configs on the filesystem in ${repos_dir}`,
|
|
99
|
-
gitops_config.repos.map((r) => r.repo_url)
|
|
99
|
+
gitops_config.repos.map((r) => r.repo_url)
|
|
100
100
|
);
|
|
101
101
|
const resolved_config = resolve_gitops_config(gitops_config, repos_dir);
|
|
102
102
|
|
|
@@ -106,7 +106,7 @@ export const get_gitops_ready = async (
|
|
|
106
106
|
gitops_config,
|
|
107
107
|
download,
|
|
108
108
|
log,
|
|
109
|
-
npm_ops
|
|
109
|
+
npm_ops
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
const local_repos = await local_repos_load({
|
|
@@ -117,10 +117,10 @@ export const get_gitops_ready = async (
|
|
|
117
117
|
parallel,
|
|
118
118
|
concurrency,
|
|
119
119
|
sync,
|
|
120
|
-
allow_dirty
|
|
120
|
+
allow_dirty
|
|
121
121
|
});
|
|
122
122
|
|
|
123
|
-
return {config_path, repos_dir, gitops_config, local_repos};
|
|
123
|
+
return { config_path, repos_dir, gitops_config, local_repos };
|
|
124
124
|
};
|
|
125
125
|
|
|
126
126
|
export interface ResolveGitopsPathsOptions {
|
|
@@ -130,9 +130,9 @@ export interface ResolveGitopsPathsOptions {
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
export const resolve_gitops_paths = (
|
|
133
|
-
options: ResolveGitopsPathsOptions
|
|
134
|
-
): {config_path: string; repos_dir: string} => {
|
|
135
|
-
const {config, dir, config_repos_dir} = options;
|
|
133
|
+
options: ResolveGitopsPathsOptions
|
|
134
|
+
): { config_path: string; repos_dir: string } => {
|
|
135
|
+
const { config, dir, config_repos_dir } = options;
|
|
136
136
|
const config_path = resolve(config);
|
|
137
137
|
const config_dir = dirname(config_path);
|
|
138
138
|
|
|
@@ -144,7 +144,7 @@ export const resolve_gitops_paths = (
|
|
|
144
144
|
? resolve(config_dir, config_repos_dir)
|
|
145
145
|
: resolve(config_dir, DEFAULT_REPOS_DIR);
|
|
146
146
|
|
|
147
|
-
return {config_path, repos_dir};
|
|
147
|
+
return { config_path, repos_dir };
|
|
148
148
|
};
|
|
149
149
|
|
|
150
150
|
export const import_gitops_config = async (config_path: string): Promise<GitopsConfig> => {
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import type {Task} from '@fuzdev/gro';
|
|
2
|
-
import {z} from 'zod';
|
|
3
|
-
import {styleText as st} from 'node:util';
|
|
1
|
+
import type { Task } from '@fuzdev/gro';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { styleText as st } from 'node:util';
|
|
4
4
|
|
|
5
|
-
import {get_gitops_ready} from './gitops_task_helpers.
|
|
6
|
-
import {analyze_repos, type DependencyAnalysis} from './graph_validation.
|
|
5
|
+
import { get_gitops_ready } from './gitops_task_helpers.ts';
|
|
6
|
+
import { analyze_repos, type DependencyAnalysis } from './graph_validation.ts';
|
|
7
7
|
import {
|
|
8
8
|
generate_publishing_plan,
|
|
9
9
|
log_publishing_plan,
|
|
10
|
-
type PublishingPlan
|
|
11
|
-
} from './publishing_plan.
|
|
12
|
-
import {execute_publishing_plan, type PublishingOptions} from './multi_repo_publisher.
|
|
13
|
-
import {log_dependency_analysis} from './log_helpers.
|
|
14
|
-
import {GITOPS_CONFIG_PATH_DEFAULT} from './gitops_constants.
|
|
15
|
-
import {reconcile_ci, repo_has_workflows} from './ci_reconcile.
|
|
10
|
+
type PublishingPlan
|
|
11
|
+
} from './publishing_plan.ts';
|
|
12
|
+
import { execute_publishing_plan, type PublishingOptions } from './multi_repo_publisher.ts';
|
|
13
|
+
import { log_dependency_analysis } from './log_helpers.ts';
|
|
14
|
+
import { GITOPS_CONFIG_PATH_DEFAULT } from './gitops_constants.ts';
|
|
15
|
+
import { reconcile_ci, repo_has_workflows } from './ci_reconcile.ts';
|
|
16
16
|
|
|
17
17
|
/** @nodocs */
|
|
18
18
|
export const Args = z.strictObject({
|
|
19
19
|
config: z
|
|
20
20
|
.string()
|
|
21
|
-
.meta({description: 'path to the gitops config file, absolute or relative to the cwd'})
|
|
21
|
+
.meta({ description: 'path to the gitops config file, absolute or relative to the cwd' })
|
|
22
22
|
.default(GITOPS_CONFIG_PATH_DEFAULT),
|
|
23
23
|
dir: z
|
|
24
24
|
.string()
|
|
25
|
-
.meta({description: 'path containing the repos, defaults to the parent of the config dir'})
|
|
25
|
+
.meta({ description: 'path containing the repos, defaults to the parent of the config dir' })
|
|
26
26
|
.optional(),
|
|
27
|
-
verbose: z.boolean().meta({description: 'show additional details'}).default(false),
|
|
27
|
+
verbose: z.boolean().meta({ description: 'show additional details' }).default(false),
|
|
28
28
|
sync: z
|
|
29
29
|
.boolean()
|
|
30
30
|
.meta({
|
|
31
31
|
description:
|
|
32
|
-
'sync repos (switch branch, pull, install) before validating instead of reading the working tree as-is'
|
|
32
|
+
'sync repos (switch branch, pull, install) before validating instead of reading the working tree as-is'
|
|
33
33
|
})
|
|
34
|
-
.default(false)
|
|
34
|
+
.default(false)
|
|
35
35
|
});
|
|
36
36
|
export type Args = z.infer<typeof Args>;
|
|
37
37
|
|
|
@@ -40,8 +40,8 @@ export const task: Task<Args> = {
|
|
|
40
40
|
Args,
|
|
41
41
|
summary:
|
|
42
42
|
'validate gitops configuration by running all read-only commands and checking for issues',
|
|
43
|
-
run: async ({args, log}) => {
|
|
44
|
-
const {config, dir, verbose, sync} = args;
|
|
43
|
+
run: async ({ args, log }) => {
|
|
44
|
+
const { config, dir, verbose, sync } = args;
|
|
45
45
|
|
|
46
46
|
log.info(st('cyan', 'Running Gitops Validation Suite'));
|
|
47
47
|
log.info(st('dim', 'This runs all read-only commands and checks for consistency.'));
|
|
@@ -61,7 +61,7 @@ export const task: Task<Args> = {
|
|
|
61
61
|
|
|
62
62
|
// Load repos once (shared by all commands); read the working tree as-is unless `--sync`
|
|
63
63
|
log.info(st('dim', 'Loading repositories...'));
|
|
64
|
-
const {local_repos} = await get_gitops_ready({config, dir, download: false, sync, log});
|
|
64
|
+
const { local_repos } = await get_gitops_ready({ config, dir, download: false, sync, log });
|
|
65
65
|
log.info(st('dim', ` Found ${local_repos.length} local repos`));
|
|
66
66
|
|
|
67
67
|
// 1. Run gitops_analyze
|
|
@@ -69,7 +69,7 @@ export const task: Task<Args> = {
|
|
|
69
69
|
const analyze_start = Date.now();
|
|
70
70
|
try {
|
|
71
71
|
// Build dependency graph and analyze cycles/wildcards (tolerating cycles)
|
|
72
|
-
const {analysis} = analyze_repos(local_repos);
|
|
72
|
+
const { analysis } = analyze_repos(local_repos);
|
|
73
73
|
|
|
74
74
|
const analyze_duration = Date.now() - analyze_start;
|
|
75
75
|
|
|
@@ -93,7 +93,7 @@ export const task: Task<Args> = {
|
|
|
93
93
|
duration: analyze_duration,
|
|
94
94
|
warning_details,
|
|
95
95
|
info_details,
|
|
96
|
-
analysis
|
|
96
|
+
analysis
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
log.info(st('green', ` ✓ gitops_analyze completed in ${analyze_duration}ms`));
|
|
@@ -111,7 +111,7 @@ export const task: Task<Args> = {
|
|
|
111
111
|
success: false,
|
|
112
112
|
warnings: 0,
|
|
113
113
|
errors: 1,
|
|
114
|
-
duration: analyze_duration
|
|
114
|
+
duration: analyze_duration
|
|
115
115
|
});
|
|
116
116
|
log.error(st('red', ` ✗ gitops_analyze failed: ${error}`));
|
|
117
117
|
}
|
|
@@ -121,7 +121,7 @@ export const task: Task<Args> = {
|
|
|
121
121
|
log.info(st('yellow', 'Running gitops_plan...'));
|
|
122
122
|
const plan_start = Date.now();
|
|
123
123
|
try {
|
|
124
|
-
const plan = await generate_publishing_plan(local_repos, {verbose});
|
|
124
|
+
const plan = await generate_publishing_plan(local_repos, { verbose });
|
|
125
125
|
publishing_plan = plan;
|
|
126
126
|
const plan_duration = Date.now() - plan_start;
|
|
127
127
|
|
|
@@ -133,12 +133,12 @@ export const task: Task<Args> = {
|
|
|
133
133
|
success: errors === 0,
|
|
134
134
|
warnings,
|
|
135
135
|
errors,
|
|
136
|
-
duration: plan_duration
|
|
136
|
+
duration: plan_duration
|
|
137
137
|
});
|
|
138
138
|
|
|
139
139
|
log.info(st('green', ` ✓ gitops_plan completed in ${plan_duration}ms`));
|
|
140
140
|
if (verbose) {
|
|
141
|
-
log_publishing_plan(plan, log, {verbose});
|
|
141
|
+
log_publishing_plan(plan, log, { verbose });
|
|
142
142
|
}
|
|
143
143
|
if (warnings > 0) {
|
|
144
144
|
log.warn(st('yellow', ` ⚠️ Found ${warnings} warning(s)`));
|
|
@@ -153,7 +153,7 @@ export const task: Task<Args> = {
|
|
|
153
153
|
success: false,
|
|
154
154
|
warnings: 0,
|
|
155
155
|
errors: 1,
|
|
156
|
-
duration: plan_duration
|
|
156
|
+
duration: plan_duration
|
|
157
157
|
});
|
|
158
158
|
log.error(st('red', ` ✗ gitops_plan failed: ${error}`));
|
|
159
159
|
}
|
|
@@ -164,14 +164,14 @@ export const task: Task<Args> = {
|
|
|
164
164
|
try {
|
|
165
165
|
const options: PublishingOptions = {
|
|
166
166
|
wetrun: false,
|
|
167
|
-
log: undefined
|
|
167
|
+
log: undefined // Silent for validation
|
|
168
168
|
};
|
|
169
169
|
|
|
170
170
|
// Reuse the plan from step 2 (regenerate only if that step failed to produce one).
|
|
171
171
|
const result = await execute_publishing_plan(
|
|
172
172
|
local_repos,
|
|
173
|
-
publishing_plan ?? (await generate_publishing_plan(local_repos, {verbose})),
|
|
174
|
-
options
|
|
173
|
+
publishing_plan ?? (await generate_publishing_plan(local_repos, { verbose })),
|
|
174
|
+
options
|
|
175
175
|
);
|
|
176
176
|
const dry_duration = Date.now() - dry_start;
|
|
177
177
|
|
|
@@ -184,7 +184,7 @@ export const task: Task<Args> = {
|
|
|
184
184
|
success: result.ok,
|
|
185
185
|
warnings: 0,
|
|
186
186
|
errors,
|
|
187
|
-
duration: dry_duration
|
|
187
|
+
duration: dry_duration
|
|
188
188
|
});
|
|
189
189
|
|
|
190
190
|
log.info(st('green', ` ✓ gitops_publish (dry run) completed in ${dry_duration}ms`));
|
|
@@ -198,7 +198,7 @@ export const task: Task<Args> = {
|
|
|
198
198
|
success: false,
|
|
199
199
|
warnings: 0,
|
|
200
200
|
errors: 1,
|
|
201
|
-
duration: dry_duration
|
|
201
|
+
duration: dry_duration
|
|
202
202
|
});
|
|
203
203
|
log.error(st('red', ` ✗ gitops_publish (dry run) failed: ${error}`));
|
|
204
204
|
}
|
|
@@ -217,21 +217,21 @@ export const task: Task<Args> = {
|
|
|
217
217
|
// always `true` today. The gate exists for a future caller that loads a
|
|
218
218
|
// partial set; until then the skip path is inert and untested.
|
|
219
219
|
checkable: true,
|
|
220
|
-
archived: r.repo_config.archived
|
|
221
|
-
}))
|
|
220
|
+
archived: r.repo_config.archived
|
|
221
|
+
}))
|
|
222
222
|
);
|
|
223
223
|
const ci_duration = Date.now() - ci_start;
|
|
224
224
|
const drift_details = ci_drift.map((d) =>
|
|
225
225
|
d.kind === 'missing_ci'
|
|
226
226
|
? `${d.repo_url}: ci=true but no workflow files`
|
|
227
|
-
: `${d.repo_url}: ci=false but workflow files present
|
|
227
|
+
: `${d.repo_url}: ci=false but workflow files present`
|
|
228
228
|
);
|
|
229
229
|
results.push({
|
|
230
230
|
command: 'ci_reconcile',
|
|
231
231
|
success: ci_drift.length === 0,
|
|
232
232
|
warnings: 0,
|
|
233
233
|
errors: ci_drift.length,
|
|
234
|
-
duration: ci_duration
|
|
234
|
+
duration: ci_duration
|
|
235
235
|
});
|
|
236
236
|
if (ci_drift.length === 0) {
|
|
237
237
|
log.info(st('green', ` ✓ ci_reconcile completed in ${ci_duration}ms`));
|
|
@@ -248,7 +248,7 @@ export const task: Task<Args> = {
|
|
|
248
248
|
success: false,
|
|
249
249
|
warnings: 0,
|
|
250
250
|
errors: 1,
|
|
251
|
-
duration: ci_duration
|
|
251
|
+
duration: ci_duration
|
|
252
252
|
});
|
|
253
253
|
log.error(st('red', ` ✗ ci_reconcile failed: ${error}`));
|
|
254
254
|
}
|
|
@@ -295,7 +295,7 @@ export const task: Task<Args> = {
|
|
|
295
295
|
log.info(st('green', '✓ All validation checks passed'));
|
|
296
296
|
if (total_warnings > 0) {
|
|
297
297
|
log.warn(
|
|
298
|
-
st('yellow', `⚠️ Note: ${total_warnings} warning(s) found - review output above.`)
|
|
298
|
+
st('yellow', `⚠️ Note: ${total_warnings} warning(s) found - review output above.`)
|
|
299
299
|
);
|
|
300
300
|
}
|
|
301
301
|
} else {
|
|
@@ -305,5 +305,5 @@ export const task: Task<Args> = {
|
|
|
305
305
|
log.error(st('red', '❌ Validation failed - review the errors above.'));
|
|
306
306
|
throw new Error('Validation failed');
|
|
307
307
|
}
|
|
308
|
-
}
|
|
308
|
+
}
|
|
309
309
|
};
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
* @module
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import type {Logger} from '@fuzdev/fuz_util/log.
|
|
17
|
-
import {TaskError} from '@fuzdev/gro';
|
|
18
|
-
import {styleText as st} from 'node:util';
|
|
16
|
+
import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
17
|
+
import { TaskError } from '@fuzdev/gro';
|
|
18
|
+
import { styleText as st } from 'node:util';
|
|
19
19
|
|
|
20
|
-
import {DependencyGraph, DependencyGraphBuilder} from './dependency_graph.
|
|
21
|
-
import type
|
|
20
|
+
import { DependencyGraph, DependencyGraphBuilder } from './dependency_graph.ts';
|
|
21
|
+
import { repo_is_npm, type LocalRepo } from './local_repo.ts';
|
|
22
22
|
|
|
23
23
|
export interface GraphValidationResult {
|
|
24
24
|
graph: DependencyGraph;
|
|
@@ -45,9 +45,9 @@ export const validate_dependency_graph = (
|
|
|
45
45
|
throw_on_prod_cycles?: boolean;
|
|
46
46
|
log_cycles?: boolean;
|
|
47
47
|
log_order?: boolean;
|
|
48
|
-
} = {}
|
|
48
|
+
} = {}
|
|
49
49
|
): GraphValidationResult => {
|
|
50
|
-
const {log, throw_on_prod_cycles = true, log_cycles = true, log_order = true} = options;
|
|
50
|
+
const { log, throw_on_prod_cycles = true, log_cycles = true, log_order = true } = options;
|
|
51
51
|
|
|
52
52
|
// Build dependency graph
|
|
53
53
|
log?.info('📊 Analyzing dependencies...');
|
|
@@ -55,7 +55,7 @@ export const validate_dependency_graph = (
|
|
|
55
55
|
const graph = builder.build_from_repos(repos);
|
|
56
56
|
|
|
57
57
|
// Check for cycles
|
|
58
|
-
const {production_cycles, dev_cycles} = graph.detect_cycles_by_type();
|
|
58
|
+
const { production_cycles, dev_cycles } = graph.detect_cycles_by_type();
|
|
59
59
|
|
|
60
60
|
// Log production cycles
|
|
61
61
|
if (production_cycles.length > 0 && log_cycles) {
|
|
@@ -67,7 +67,7 @@ export const validate_dependency_graph = (
|
|
|
67
67
|
if (throw_on_prod_cycles) {
|
|
68
68
|
throw new TaskError(
|
|
69
69
|
`Cannot publish with production/peer dependency cycles. ` +
|
|
70
|
-
`These must be resolved before publishing
|
|
70
|
+
`These must be resolved before publishing.`
|
|
71
71
|
);
|
|
72
72
|
}
|
|
73
73
|
}
|
|
@@ -106,7 +106,7 @@ export const validate_dependency_graph = (
|
|
|
106
106
|
publishing_order,
|
|
107
107
|
production_cycles,
|
|
108
108
|
dev_cycles,
|
|
109
|
-
sort_error
|
|
109
|
+
sort_error
|
|
110
110
|
};
|
|
111
111
|
};
|
|
112
112
|
|
|
@@ -127,11 +127,12 @@ export interface RepoAnalysis {
|
|
|
127
127
|
* (no `log`) to avoid emitting a redundant "Analyzing dependencies" line.
|
|
128
128
|
*/
|
|
129
129
|
export const analyze_repos = (repos: Array<LocalRepo>): RepoAnalysis => {
|
|
130
|
-
|
|
130
|
+
// Only npm packages form the dependency graph; non-npm repos (e.g. cargo) are excluded.
|
|
131
|
+
const { graph, publishing_order: order } = validate_dependency_graph(repos.filter(repo_is_npm), {
|
|
131
132
|
throw_on_prod_cycles: false, // report, don't throw
|
|
132
133
|
log_cycles: false, // callers format their own cycle output
|
|
133
|
-
log_order: false
|
|
134
|
+
log_order: false
|
|
134
135
|
});
|
|
135
136
|
const analysis = new DependencyGraphBuilder().analyze(graph);
|
|
136
|
-
return {graph, analysis, publishing_order: order.length > 0 ? order : null};
|
|
137
|
+
return { graph, analysis, publishing_order: order.length > 0 ? order : null };
|
|
137
138
|
};
|