@fuzdev/fuz_gitops 0.78.0 → 0.79.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.
Files changed (196) hide show
  1. package/README.md +91 -17
  2. package/dist/ModulesDetail.svelte +22 -27
  3. package/dist/ModulesDetail.svelte.d.ts.map +1 -1
  4. package/dist/ModulesNav.svelte +8 -5
  5. package/dist/ModulesNav.svelte.d.ts.map +1 -1
  6. package/dist/ModulesPage.svelte +3 -5
  7. package/dist/ModulesPage.svelte.d.ts.map +1 -1
  8. package/dist/PageFooter.svelte +2 -2
  9. package/dist/PageHeader.svelte +6 -6
  10. package/dist/PageHeader.svelte.d.ts +0 -3
  11. package/dist/PageHeader.svelte.d.ts.map +1 -1
  12. package/dist/PullRequestsDetail.svelte +29 -20
  13. package/dist/PullRequestsDetail.svelte.d.ts.map +1 -1
  14. package/dist/PullRequestsPage.svelte +4 -6
  15. package/dist/PullRequestsPage.svelte.d.ts.map +1 -1
  16. package/dist/ReposTable.svelte +43 -55
  17. package/dist/ReposTable.svelte.d.ts.map +1 -1
  18. package/dist/ReposTree.svelte +9 -21
  19. package/dist/ReposTree.svelte.d.ts.map +1 -1
  20. package/dist/ReposTreeNav.svelte +9 -12
  21. package/dist/ReposTreeNav.svelte.d.ts.map +1 -1
  22. package/dist/TablePage.svelte +3 -5
  23. package/dist/TablePage.svelte.d.ts.map +1 -1
  24. package/dist/TreeItemPage.svelte +3 -5
  25. package/dist/TreeItemPage.svelte.d.ts.map +1 -1
  26. package/dist/TreePage.svelte +3 -5
  27. package/dist/TreePage.svelte.d.ts.map +1 -1
  28. package/dist/changeset_generator.d.ts.map +1 -1
  29. package/dist/changeset_generator.js +2 -2
  30. package/dist/changeset_reader.d.ts.map +1 -1
  31. package/dist/changeset_reader.js +3 -3
  32. package/dist/ci_reconcile.d.ts +6 -10
  33. package/dist/ci_reconcile.d.ts.map +1 -1
  34. package/dist/ci_reconcile.js +6 -8
  35. package/dist/dependency_graph.d.ts +26 -49
  36. package/dist/dependency_graph.d.ts.map +1 -1
  37. package/dist/dependency_graph.js +40 -83
  38. package/dist/dependency_updater.d.ts +1 -1
  39. package/dist/dependency_updater.d.ts.map +1 -1
  40. package/dist/dependency_updater.js +14 -9
  41. package/dist/fetch_repo_data.d.ts +34 -8
  42. package/dist/fetch_repo_data.d.ts.map +1 -1
  43. package/dist/fetch_repo_data.js +44 -22
  44. package/dist/fs_fetch_value_cache.d.ts +1 -1
  45. package/dist/fs_fetch_value_cache.d.ts.map +1 -1
  46. package/dist/fs_fetch_value_cache.js +3 -3
  47. package/dist/git_operations.d.ts +6 -49
  48. package/dist/git_operations.d.ts.map +1 -1
  49. package/dist/git_operations.js +13 -126
  50. package/dist/github.d.ts +17 -2
  51. package/dist/github.d.ts.map +1 -1
  52. package/dist/github.js +17 -8
  53. package/dist/github_helpers.d.ts.map +1 -1
  54. package/dist/github_helpers.js +3 -11
  55. package/dist/gitops_analyze.task.d.ts +24 -2
  56. package/dist/gitops_analyze.task.d.ts.map +1 -1
  57. package/dist/gitops_analyze.task.js +47 -34
  58. package/dist/gitops_config.d.ts +34 -79
  59. package/dist/gitops_config.d.ts.map +1 -1
  60. package/dist/gitops_config.js +76 -53
  61. package/dist/gitops_constants.d.ts +6 -4
  62. package/dist/gitops_constants.d.ts.map +1 -1
  63. package/dist/gitops_constants.js +6 -4
  64. package/dist/gitops_plan.task.d.ts +29 -3
  65. package/dist/gitops_plan.task.d.ts.map +1 -1
  66. package/dist/gitops_plan.task.js +83 -61
  67. package/dist/gitops_publish.task.d.ts +62 -2
  68. package/dist/gitops_publish.task.d.ts.map +1 -1
  69. package/dist/gitops_publish.task.js +193 -105
  70. package/dist/gitops_run.task.d.ts +74 -0
  71. package/dist/gitops_run.task.d.ts.map +1 -1
  72. package/dist/gitops_run.task.js +176 -162
  73. package/dist/gitops_sync.task.d.ts +65 -3
  74. package/dist/gitops_sync.task.d.ts.map +1 -1
  75. package/dist/gitops_sync.task.js +163 -37
  76. package/dist/gitops_task_helpers.d.ts +86 -59
  77. package/dist/gitops_task_helpers.d.ts.map +1 -1
  78. package/dist/gitops_task_helpers.js +120 -79
  79. package/dist/gitops_validate.task.d.ts +1 -2
  80. package/dist/gitops_validate.task.d.ts.map +1 -1
  81. package/dist/gitops_validate.task.js +25 -32
  82. package/dist/graph_validation.d.ts +16 -27
  83. package/dist/graph_validation.d.ts.map +1 -1
  84. package/dist/graph_validation.js +24 -65
  85. package/dist/local_repo.d.ts +50 -62
  86. package/dist/local_repo.d.ts.map +1 -1
  87. package/dist/local_repo.js +83 -196
  88. package/dist/log_helpers.d.ts +8 -8
  89. package/dist/log_helpers.d.ts.map +1 -1
  90. package/dist/multi_repo_publisher.d.ts +10 -0
  91. package/dist/multi_repo_publisher.d.ts.map +1 -1
  92. package/dist/multi_repo_publisher.js +125 -61
  93. package/dist/npm_registry.d.ts +23 -19
  94. package/dist/npm_registry.d.ts.map +1 -1
  95. package/dist/npm_registry.js +21 -48
  96. package/dist/operations.d.ts +75 -180
  97. package/dist/operations.d.ts.map +1 -1
  98. package/dist/operations.js +15 -7
  99. package/dist/operations_defaults.d.ts +17 -2
  100. package/dist/operations_defaults.d.ts.map +1 -1
  101. package/dist/operations_defaults.js +111 -128
  102. package/dist/output_helpers.d.ts +36 -0
  103. package/dist/output_helpers.d.ts.map +1 -1
  104. package/dist/output_helpers.js +37 -3
  105. package/dist/preflight_checks.d.ts +20 -27
  106. package/dist/preflight_checks.d.ts.map +1 -1
  107. package/dist/preflight_checks.js +37 -126
  108. package/dist/publish_gate.d.ts.map +1 -1
  109. package/dist/publish_steps.d.ts +2 -4
  110. package/dist/publish_steps.d.ts.map +1 -1
  111. package/dist/publish_steps.js +4 -8
  112. package/dist/publishing_event.d.ts +2 -8
  113. package/dist/publishing_event.d.ts.map +1 -1
  114. package/dist/publishing_event.js +20 -17
  115. package/dist/publishing_event_handler.d.ts +10 -8
  116. package/dist/publishing_event_handler.d.ts.map +1 -1
  117. package/dist/publishing_event_handler.js +19 -17
  118. package/dist/publishing_plan.d.ts +16 -1
  119. package/dist/publishing_plan.d.ts.map +1 -1
  120. package/dist/publishing_plan.js +332 -254
  121. package/dist/publishing_plan_helpers.d.ts.map +1 -1
  122. package/dist/publishing_plan_helpers.js +3 -3
  123. package/dist/publishing_plan_logging.d.ts +1 -1
  124. package/dist/publishing_plan_logging.d.ts.map +1 -1
  125. package/dist/publishing_plan_logging.js +22 -15
  126. package/dist/repo.svelte.d.ts +7 -0
  127. package/dist/repo.svelte.d.ts.map +1 -1
  128. package/dist/repo.svelte.js +3 -0
  129. package/dist/repo_readiness.d.ts +210 -0
  130. package/dist/repo_readiness.d.ts.map +1 -0
  131. package/dist/repo_readiness.js +516 -0
  132. package/dist/repos_status.d.ts +3340 -0
  133. package/dist/repos_status.d.ts.map +1 -0
  134. package/dist/repos_status.js +555 -0
  135. package/dist/repos_status_load.d.ts +65 -0
  136. package/dist/repos_status_load.d.ts.map +1 -0
  137. package/dist/repos_status_load.js +131 -0
  138. package/dist/version_utils.js +1 -1
  139. package/package.json +15 -34
  140. package/src/lib/cargo_toml.ts +3 -3
  141. package/src/lib/changeset_generator.ts +19 -19
  142. package/src/lib/changeset_reader.ts +18 -18
  143. package/src/lib/ci_reconcile.ts +12 -16
  144. package/src/lib/dependency_graph.ts +61 -113
  145. package/src/lib/dependency_updater.ts +36 -30
  146. package/src/lib/fetch_repo_data.ts +71 -34
  147. package/src/lib/fs_fetch_value_cache.ts +15 -11
  148. package/src/lib/git_operations.ts +22 -194
  149. package/src/lib/github.ts +33 -21
  150. package/src/lib/github_helpers.ts +9 -16
  151. package/src/lib/gitops_analyze.task.ts +104 -66
  152. package/src/lib/gitops_config.ts +90 -139
  153. package/src/lib/gitops_constants.ts +6 -4
  154. package/src/lib/gitops_plan.task.ts +128 -76
  155. package/src/lib/gitops_publish.task.ts +280 -144
  156. package/src/lib/gitops_run.task.ts +265 -193
  157. package/src/lib/gitops_sync.task.ts +236 -52
  158. package/src/lib/gitops_task_helpers.ts +170 -114
  159. package/src/lib/gitops_validate.task.ts +44 -54
  160. package/src/lib/graph_validation.ts +28 -89
  161. package/src/lib/local_repo.ts +128 -335
  162. package/src/lib/log_helpers.ts +18 -28
  163. package/src/lib/multi_repo_publisher.ts +192 -110
  164. package/src/lib/npm_registry.ts +42 -67
  165. package/src/lib/operations.ts +99 -160
  166. package/src/lib/operations_defaults.ts +157 -201
  167. package/src/lib/output_helpers.ts +58 -6
  168. package/src/lib/preflight_checks.ts +52 -188
  169. package/src/lib/publish_gate.ts +7 -9
  170. package/src/lib/publish_steps.ts +27 -25
  171. package/src/lib/publishing_event.ts +26 -23
  172. package/src/lib/publishing_event_handler.ts +24 -22
  173. package/src/lib/publishing_plan.ts +474 -310
  174. package/src/lib/publishing_plan_helpers.ts +16 -12
  175. package/src/lib/publishing_plan_logging.ts +53 -44
  176. package/src/lib/repo.svelte.ts +16 -8
  177. package/src/lib/repo_readiness.ts +647 -0
  178. package/src/lib/repos_status.ts +671 -0
  179. package/src/lib/repos_status_load.ts +173 -0
  180. package/src/lib/version_utils.ts +3 -3
  181. package/dist/config_reconcile.d.ts +0 -46
  182. package/dist/config_reconcile.d.ts.map +0 -1
  183. package/dist/config_reconcile.js +0 -60
  184. package/dist/paths.d.ts +0 -7
  185. package/dist/paths.d.ts.map +0 -1
  186. package/dist/paths.js +0 -6
  187. package/dist/repo_ops.d.ts +0 -59
  188. package/dist/repo_ops.d.ts.map +0 -1
  189. package/dist/repo_ops.js +0 -170
  190. package/dist/resolved_gitops_config.d.ts +0 -9
  191. package/dist/resolved_gitops_config.d.ts.map +0 -1
  192. package/dist/resolved_gitops_config.js +0 -12
  193. package/src/lib/config_reconcile.ts +0 -94
  194. package/src/lib/paths.ts +0 -6
  195. package/src/lib/repo_ops.ts +0 -216
  196. package/src/lib/resolved_gitops_config.ts +0 -27
@@ -2,16 +2,21 @@ import { TaskError } from '@fuzdev/gro';
2
2
  import { z } from 'zod';
3
3
  import { readFile, writeFile } from 'node:fs/promises';
4
4
  import { format_file } from '@fuzdev/gro/format_file.ts';
5
- import { basename, resolve } from 'node:path';
5
+ import { basename, join, resolve } from 'node:path';
6
6
  import { print_path } from '@fuzdev/gro/paths.ts';
7
7
  import { load_from_env } from '@fuzdev/gro/env.ts';
8
8
  import { package_json_load } from '@fuzdev/gro/package_json.ts';
9
- import { existsSync } from 'node:fs';
9
+ import { existsSync, readFileSync } from 'node:fs';
10
+ import { styleText as st } from 'node:util';
10
11
  import { compactReplacer } from 'svelte-docinfo';
11
12
  import { fetch_repo_data } from './fetch_repo_data.js';
12
13
  import { create_fs_fetch_value_cache } from './fs_fetch_value_cache.js';
13
- import { get_gitops_ready } from './gitops_task_helpers.js';
14
+ import { resolve_gitops_repos } from './gitops_task_helpers.js';
14
15
  import { GITOPS_CONFIG_PATH_DEFAULT } from './gitops_constants.js';
16
+ import { local_repos_load, local_repos_resolve } from './local_repo.js';
17
+ import { load_repos_status, to_repos_command } from './repos_status_load.js';
18
+ import { check_gen_readiness } from './repo_readiness.js';
19
+ import { default_repos_operations } from './operations_defaults.js';
15
20
  // TODO add flag to ignore or invalidate cache -- no-cache? clean?
16
21
  /** @nodocs */
17
22
  export const Args = z.strictObject({
@@ -19,69 +24,72 @@ export const Args = z.strictObject({
19
24
  .string()
20
25
  .meta({ description: 'path to the gitops config file, absolute or relative to the cwd' })
21
26
  .default(GITOPS_CONFIG_PATH_DEFAULT),
22
- dir: z
27
+ registry: z
23
28
  .string()
24
- .meta({ description: 'path containing the repos, defaults to the parent of the config dir' })
29
+ .meta({
30
+ description: 'path to the repos.toml registry, when `repos` would not find it walking up from the cwd'
31
+ })
25
32
  .optional(),
26
33
  outdir: z
27
34
  .string()
28
35
  .meta({ description: 'path to the directory for the generated files, defaults to $routes/' })
29
36
  .optional(),
30
- download: z.boolean().meta({ description: 'download all missing local repos' }).default(false),
31
37
  check: z
32
38
  .boolean()
33
- .meta({ description: 'check repos are ready without fetching remote data' })
39
+ .meta({
40
+ description: 'report whether the repos are ready to generate from, as of the local refs, and exit non-zero if a real run would refuse; fetches nothing, needs no token, and writes nothing'
41
+ })
34
42
  .default(false),
35
43
  allow_dirty: z
36
44
  .boolean()
37
45
  .meta({
38
- description: 'sync (switch branch, pull) tolerating uncommitted changes instead of failing on a dirty workspace',
46
+ description: 'read repos off their registry branch, dirty, or mid-operation as they sit, warning instead of refusing'
39
47
  })
40
- .default(false),
48
+ .default(false)
41
49
  });
42
50
  /**
43
- * This is a task not a `.gen.` file because it makes network calls.
51
+ * Generates the dashboard's site data (`repos.json` and `repos.ts`) from each
52
+ * configured repo's working tree and its GitHub CI status and pull requests.
53
+ * It never moves a repo: see `prepare_gitops_sync` for what it reads and
54
+ * refuses. This is a task not a `.gen.` file because it makes network calls.
44
55
  *
45
56
  * @nodocs
46
57
  */
47
58
  export const task = {
48
59
  Args,
49
- summary: 'syncs local repos and generates UI data from repo metadata',
50
- run: async ({ args, log, svelte_config, invoke_task }) => {
51
- const { config, dir, outdir = svelte_config.routes_path, download, check, allow_dirty } = args;
52
- // `gitops_sync` is the task whose job is to mutate working trees, so it always syncs.
53
- const { local_repos } = await get_gitops_ready({
60
+ summary: 'generates UI data from repo metadata, reading each repo as it sits',
61
+ run: async (ctx) => {
62
+ const { args, log, invoke_task } = ctx;
63
+ // `ctx.svelte_config` is a lazy getter, so it's only read when `outdir` isn't provided
64
+ const { config, registry, outdir = (await ctx.svelte_config).routes_path, check, allow_dirty } = args;
65
+ // The generated `repos.json` is the host project's site data, so a public host
66
+ // must never carry a private repo's metadata: `host` refuses the private repos
67
+ // the registry declares, before any fetch.
68
+ const package_json = await package_json_load();
69
+ const prepared = await prepare_gitops_sync({
54
70
  config,
55
- dir,
56
- download,
57
- sync: true,
71
+ registry,
72
+ host: { name: package_json.name, private: package_json.private === true },
73
+ check,
58
74
  allow_dirty,
59
- log,
75
+ log
60
76
  });
77
+ if (!prepared)
78
+ return;
79
+ const { local_repos, token } = prepared;
61
80
  const outfile_json = resolve(outdir, 'repos.json');
62
81
  const outfile_ts = resolve(outdir, 'repos.ts');
63
- // This searches the parent directory for the env var, so we don't use SvelteKit's $env imports
64
- const token = load_from_env('SECRET_GITHUB_API_TOKEN');
65
- if (!token) {
66
- throw new TaskError('the env var SECRET_GITHUB_API_TOKEN was not found');
67
- }
68
- // Exit early if only checking repo readiness
69
- if (check) {
70
- log.info('repos are ready');
71
- return;
72
- }
73
82
  const cache = await create_fs_fetch_value_cache('repos');
74
83
  log.info('fetching remote repo data');
75
- const repos_json = await fetch_repo_data(local_repos, token, cache.data, log);
84
+ const repos_json = await fetch_repo_data({ local_repos, token, cache: cache.data, log });
76
85
  // TODO should package_json be provided in the Gro task/gen contexts? check if it's always loaded
77
- const package_json = await package_json_load();
78
86
  const repo_specifier = package_json.name === '@fuzdev/fuz_gitops'
79
- ? '$lib/repo.svelte.js'
80
- : '@fuzdev/fuz_gitops/repo.svelte.js';
87
+ ? '$lib/repo.svelte.ts'
88
+ : '@fuzdev/fuz_gitops/repo.svelte.ts';
81
89
  log.info(`generating ${outfile_json} and ${outfile_ts}`);
82
90
  // Generate repos.json with the raw data
83
- const json_contents = await format_file(JSON.stringify(repos_json, compactReplacer), {
84
- filepath: outfile_json,
91
+ const json_contents = format_file(JSON.stringify(repos_json, compactReplacer), {
92
+ lang: 'json'
85
93
  });
86
94
  const existing_json = existsSync(outfile_json) ? await readFile(outfile_json, 'utf8') : '';
87
95
  const json_changed = existing_json !== json_contents;
@@ -107,7 +115,7 @@ export const task = {
107
115
  export const repos_json: Array<RepoJson> = json as unknown as Array<RepoJson>;
108
116
  `;
109
117
  // TODO think about possibly using the `gen` functionality in this task, not sure what the API design could look like
110
- const formatted_ts = await format_file(ts_contents, { filepath: outfile_ts });
118
+ const formatted_ts = format_file(ts_contents, { filepath: outfile_ts });
111
119
  const existing_ts = existsSync(outfile_ts) ? await readFile(outfile_ts, 'utf8') : '';
112
120
  if (existing_ts === formatted_ts) {
113
121
  log.info(`no changes to ${print_path(outfile_ts)}`);
@@ -126,5 +134,123 @@ export const task = {
126
134
  else {
127
135
  log.info('repos cache did not change');
128
136
  }
129
- },
137
+ }
138
+ };
139
+ const default_gitops_sync_deps = {
140
+ repos_ops: default_repos_operations,
141
+ load_repos: local_repos_load,
142
+ // this searches the parent directory for the env var, so we don't use SvelteKit's $env imports
143
+ load_token: () => load_from_env('SECRET_GITHUB_API_TOKEN') || undefined,
144
+ exists: existsSync,
145
+ read_file: (path) => readFileSync(path, 'utf8')
146
+ };
147
+ /**
148
+ * Everything `gitops_sync` does before it fetches from GitHub, in order:
149
+ *
150
+ * 1. resolves the config's repos from `repos status <keys…> --json` (local
151
+ * refs), refusing a private repo when the host package is public
152
+ * 2. checks each repo is ready to generate from (`check_gen_readiness`): on
153
+ * its registry branch, clean, and idle, unless `allow_dirty` — refusing
154
+ * before any network. With `check`, that report is the whole run: its
155
+ * warnings are logged, and it throws when a real run would refuse
156
+ * 3. reads `SECRET_GITHUB_API_TOKEN`
157
+ * 4. fetches the repos from origin (`repos status <keys…> --fetch --json`,
158
+ * which writes remote-tracking refs and nothing else) and checks them
159
+ * again, warning on a followed branch not in sync with origin and a
160
+ * failed fetch
161
+ * 5. warns on each npm repo the library analysis can't fully read: no
162
+ * `node_modules`, or no `.svelte-kit/tsconfig.json` when its tsconfig
163
+ * extends it (external types then read as `any`) — it installs nothing
164
+ * 6. loads each repo's library as it sits
165
+ *
166
+ * @returns the loaded repos and the token, or `null` when `check` passed
167
+ * @throws {TaskError} if resolving fails, a repo isn't ready, or the token is missing
168
+ * @nodocs
169
+ */
170
+ export const prepare_gitops_sync = async (options, deps = {}) => {
171
+ const { config, registry, host, check = false, allow_dirty = false, log } = options;
172
+ const { repos_ops, load_repos, load_token, exists, read_file } = {
173
+ ...default_gitops_sync_deps,
174
+ ...deps
175
+ };
176
+ const repos_command = to_repos_command(registry);
177
+ const { config_path, gitops_config, report } = await resolve_gitops_repos({
178
+ config,
179
+ registry,
180
+ host,
181
+ log,
182
+ repos_ops
183
+ });
184
+ const keys = gitops_config.repos;
185
+ const local = check_gen_readiness({ report, keys, allow_dirty, repos_command });
186
+ if (check) {
187
+ log_gen_warnings(local.warnings, log);
188
+ if (!local.ok)
189
+ throw new TaskError(local.message);
190
+ log.info(st('green', `all ${keys.length} repos are ready to generate the site data from`));
191
+ return null;
192
+ }
193
+ if (!local.ok)
194
+ throw new TaskError(local.message);
195
+ const token = load_token();
196
+ if (!token) {
197
+ throw new TaskError('the env var SECRET_GITHUB_API_TOKEN was not found');
198
+ }
199
+ log.info(`fetching ${keys.length} repos from origin`);
200
+ const fetched = await load_repos_status({ keys, registry, fetch: true, repos_ops });
201
+ if (!fetched.ok) {
202
+ throw new TaskError(`fetching the repos failed: ${fetched.message}`);
203
+ }
204
+ const resolved = local_repos_resolve({ keys, report: fetched.report, host, registry });
205
+ if (!resolved.ok) {
206
+ throw new TaskError(`${config_path}: ${resolved.message}`);
207
+ }
208
+ const checked = check_gen_readiness({
209
+ report: fetched.report,
210
+ keys,
211
+ allow_dirty,
212
+ repos_command
213
+ });
214
+ log_gen_warnings(checked.warnings, log);
215
+ if (!checked.ok)
216
+ throw new TaskError(checked.message);
217
+ const local_repo_paths = resolved.value;
218
+ const gaps = local_repo_paths
219
+ .map((p) => ({ key: p.repo_name, missing: analysis_setup_gaps(p.repo_dir, exists, read_file) }))
220
+ .filter((g) => g.missing.length > 0);
221
+ if (gaps.length > 0) {
222
+ log.warn(st('yellow', "the library analysis reads these repos without their dependencies' types, so external types read as `any` — `npm install` and `gro sync` in each fixes it:"));
223
+ for (const { key, missing } of gaps) {
224
+ log.warn(st('yellow', ` ${key}: no ${missing.join(' or ')}`));
225
+ }
226
+ }
227
+ const local_repos = await load_repos({ local_repo_paths, log });
228
+ return { local_repos, token };
229
+ };
230
+ const log_gen_warnings = (warnings, log) => {
231
+ if (warnings.length === 0)
232
+ return;
233
+ log.warn(st('yellow', "read as they sit, beside origin's CI:"));
234
+ for (const line of warnings)
235
+ log.warn(st('yellow', ` ${line}`));
236
+ };
237
+ /**
238
+ * What an npm repo lacks for the library analysis to resolve its dependencies'
239
+ * types: `node_modules`, and `.svelte-kit/tsconfig.json` when its
240
+ * `tsconfig.json` extends it. Empty for a repo without a `package.json`.
241
+ */
242
+ const analysis_setup_gaps = (repo_dir, exists, read_file) => {
243
+ if (!exists(join(repo_dir, 'package.json')))
244
+ return [];
245
+ const missing = [];
246
+ if (!exists(join(repo_dir, 'node_modules')))
247
+ missing.push('`node_modules`');
248
+ const tsconfig_path = join(repo_dir, 'tsconfig.json');
249
+ const svelte_kit_tsconfig = '.svelte-kit/tsconfig.json';
250
+ if (exists(tsconfig_path) &&
251
+ read_file(tsconfig_path).includes(svelte_kit_tsconfig) &&
252
+ !exists(join(repo_dir, svelte_kit_tsconfig))) {
253
+ missing.push(`\`${svelte_kit_tsconfig}\``);
254
+ }
255
+ return missing;
130
256
  };
@@ -1,83 +1,110 @@
1
1
  /**
2
2
  * Shared initialization logic for all gitops tasks.
3
3
  *
4
- * Provides `get_gitops_ready()` which orchestrates:
5
- * - Config loading and normalization
6
- * - Repo resolution (local path discovery)
7
- * - Branch switching and syncing
8
- * - Dependency installation
4
+ * `resolve_gitops_repos()` loads the config's registry keys, runs
5
+ * `repos status <keys…> --json`, and resolves each key to its checkout.
6
+ * `get_gitops_ready()` then loads each repo's library as its working tree
7
+ * sits. `gate_publish_readiness()` is the read-only gate a real publish runs
8
+ * before its prompt, and `log_readiness_block()` the diagnostics' report of
9
+ * repos not at rest (both over `repo_readiness.ts`).
9
10
  *
10
11
  * Used by: `gitops_sync.task.ts`, `gitops_analyze.task.ts`, `gitops_plan.task.ts`,
11
- * `gitops_publish.task.ts`, and `gitops_validate.task.ts`.
12
+ * `gitops_publish.task.ts`, `gitops_validate.task.ts`, and `gitops_run.task.ts`.
12
13
  *
13
- * Accepts `git_ops` and `npm_ops` parameters to support testing via operations pattern
14
- * (see `operations.ts` for dependency injection details).
14
+ * Accepts `repos_ops` to support testing via the operations pattern (see
15
+ * `operations.ts` for dependency injection details).
15
16
  *
16
17
  * @module
17
18
  */
18
19
  import type { Logger } from '@fuzdev/fuz_util/log.ts';
19
20
  import { type GitopsConfig } from './gitops_config.js';
20
- import { type LocalRepo } from './local_repo.js';
21
- import type { GitOperations, NpmOperations } from './operations.js';
22
- export interface GetGitopsReadyOptions {
21
+ import { type LocalRepo, type LocalRepoPath } from './local_repo.js';
22
+ import type { ReposStatusReport } from './repos_status.js';
23
+ import type { ReposOperations } from './operations.js';
24
+ export interface ResolveGitopsReposOptions {
25
+ /** Path to the gitops config, absolute or relative to the cwd. */
23
26
  config: string;
24
- dir?: string;
25
- download: boolean;
26
- log?: Logger;
27
- git_ops?: GitOperations;
28
- npm_ops?: NpmOperations;
29
- parallel?: boolean;
30
- concurrency?: number;
27
+ /** A `repos.toml` to use instead of the one `repos` finds walking up from the cwd. */
28
+ registry?: string;
31
29
  /**
32
- * Sync each repo's working tree to its configured branch before loading
33
- * (switch branch, pull, install). When `false`, repos load exactly as they
34
- * sit on disk — the safe default for read-only diagnostics. Defaults to `true`.
30
+ * The package whose generated data the run writes; when it's public, a
31
+ * private repo in the config fails the resolve.
35
32
  */
36
- sync?: boolean;
37
- /** When syncing, tolerate uncommitted changes instead of throwing. Defaults to `false`. */
38
- allow_dirty?: boolean;
33
+ host?: {
34
+ name: string;
35
+ private: boolean;
36
+ };
37
+ log?: Logger;
38
+ repos_ops?: ReposOperations;
39
39
  }
40
40
  /**
41
- * Central initialization function for all gitops tasks.
42
- *
43
- * Initialization sequence:
44
- * 1. Loads and normalizes config from `gitops.config.ts`
45
- * 2. Resolves local repo paths (creates missing with `--download`)
46
- * 3. If `sync`, switches branches and pulls latest changes (in parallel by default)
47
- * 4. If `sync`, auto-installs deps if `package.json` changed during pull
41
+ * Resolves the gitops config's repos through `repos status`: loads the
42
+ * config's registry keys, reports on them, and resolves each to its checkout,
43
+ * in config order. Reads nothing but git state and writes nothing.
48
44
  *
49
- * With `sync: false` (the default for read-only diagnostics), steps 3-4 are
50
- * skipped and repos are loaded exactly as checked out — no branch switch, pull,
51
- * install, or clean-workspace check.
52
- *
53
- * Priority for path resolution:
54
- * - `dir` argument (explicit override)
55
- * - Config `repos_dir` setting
56
- * - `DEFAULT_REPOS_DIR` constant
57
- *
58
- * @param options.git_ops - for testing (defaults to real git operations)
59
- * @param options.npm_ops - for testing (defaults to real npm operations)
60
- * @param options.parallel - whether to load repos in parallel (default: true)
61
- * @param options.concurrency - max concurrent repo loads (default: 5)
62
- * @param options.sync - sync working trees before loading (default: true)
63
- * @param options.allow_dirty - when syncing, tolerate uncommitted changes (default: false)
64
- * @returns initialized config and fully loaded repos ready for operations
65
- * @throws {TaskError} if config loading or repo resolution fails
45
+ * @returns the config, the `repos status` report, and each repo's path and entry
46
+ * @throws {TaskError} if the config is missing, invalid, or lists no repos, `repos status` fails, or any configured repo is unknown, a reference, missing, not a repo, unprobed, or private under a public `host`
66
47
  */
67
- export declare const get_gitops_ready: (options: GetGitopsReadyOptions) => Promise<{
48
+ export declare const resolve_gitops_repos: (options: ResolveGitopsReposOptions) => Promise<{
68
49
  config_path: string;
69
- repos_dir: string;
70
50
  gitops_config: GitopsConfig;
51
+ report: ReposStatusReport;
52
+ local_repo_paths: Array<LocalRepoPath>;
53
+ }>;
54
+ /**
55
+ * Central initialization function for the gitops tasks that load libraries:
56
+ * resolves the config's repos through `repos status` (`resolve_gitops_repos`),
57
+ * then loads each repo's library as its working tree sits (`local_repos_load`).
58
+ * Moves no ref; gro caches each library at `.gro/library.json` in its repo, at
59
+ * a clean commit.
60
+ *
61
+ * @returns the loaded repos, in config order
62
+ * @throws {TaskError} if resolving the repos or loading them fails
63
+ */
64
+ export declare const get_gitops_ready: (options: ResolveGitopsReposOptions) => Promise<{
71
65
  local_repos: Array<LocalRepo>;
72
66
  }>;
73
- export interface ResolveGitopsPathsOptions {
74
- config: string;
75
- dir?: string;
76
- config_repos_dir?: string;
67
+ export interface GatePublishReadinessOptions {
68
+ /** The loaded repos; the npm ones are gated. */
69
+ local_repos: ReadonlyArray<LocalRepo>;
70
+ /** A `repos.toml` to use instead of the one `repos` finds walking up from the cwd. */
71
+ registry?: string;
72
+ /**
73
+ * The package names the plan publishes, to say whether a repo's commits ahead
74
+ * of origin go out with its release or stay unpushed.
75
+ */
76
+ publishing?: ReadonlySet<string>;
77
+ log?: Logger;
78
+ repos_ops?: ReposOperations;
77
79
  }
78
- export declare const resolve_gitops_paths: (options: ResolveGitopsPathsOptions) => {
79
- config_path: string;
80
- repos_dir: string;
81
- };
82
- export declare const import_gitops_config: (config_path: string) => Promise<GitopsConfig>;
80
+ /**
81
+ * The readiness gate `gitops_publish --wetrun` runs before its confirmation
82
+ * prompt: fetches every npm repo from origin (`repos status <keys…> --fetch
83
+ * --json`, which writes remote-tracking refs and nothing else) and refuses
84
+ * unless each is ready (`check_publish_readiness`) — on its registry branch,
85
+ * clean, idle, in sync with origin or ahead of it, fetched without error, no
86
+ * other live session in its checkout, and nothing left to a person. Each
87
+ * ready repo ahead of origin is logged, saying whether its release push
88
+ * carries those commits or they stay unpushed.
89
+ *
90
+ * Every npm repo, not just those the plan publishes or rewrites: the plan
91
+ * reads each one's working tree (changesets, versions, dependency ranges), so
92
+ * a repo off its branch or behind origin can hide a changeset and leave the
93
+ * plan wrong about what to publish. Changes nothing.
94
+ *
95
+ * @param options - the loaded repos, the `--registry` if any, the package names the plan publishes, a logger, and the `repos` runner
96
+ * @throws {TaskError} if `repos status` fails or any npm repo isn't ready, naming each problem and its fix
97
+ */
98
+ export declare const gate_publish_readiness: (options: GatePublishReadinessOptions) => Promise<void>;
99
+ /**
100
+ * Logs the diagnostics' readiness block as warnings (stderr, so a `--format
101
+ * json` or `markdown` document on stdout stays clean): each npm repo not at
102
+ * rest, and how. Logs nothing when every one is at rest. Reads the entries
103
+ * `repos status` already reported, from local refs.
104
+ *
105
+ * @param local_repos - the loaded repos; the npm ones are reported
106
+ * @param log - where the warnings go
107
+ * @param now - the current time in unix seconds (defaults to the clock)
108
+ */
109
+ export declare const log_readiness_block: (local_repos: ReadonlyArray<LocalRepo>, log: Logger, now?: number) => void;
83
110
  //# sourceMappingURL=gitops_task_helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"gitops_task_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gitops_task_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,EAAqB,KAAK,YAAY,EAAC,MAAM,oBAAoB,CAAC;AACzE,OAAO,EAAuC,KAAK,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAGrF,OAAO,KAAK,EAAC,aAAa,EAAE,aAAa,EAAC,MAAM,iBAAiB,CAAC;AAElE,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,2FAA2F;IAC3F,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,gBAAgB,GAC5B,SAAS,qBAAqB,KAC5B,OAAO,CAAC;IACV,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,YAAY,CAAC;IAC5B,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;CAC9B,CAwCA,CAAC;AAEF,MAAM,WAAW,yBAAyB;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,eAAO,MAAM,oBAAoB,GAChC,SAAS,yBAAyB,KAChC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAczC,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAU,aAAa,MAAM,KAAG,OAAO,CAAC,YAAY,CAMpF,CAAC"}
1
+ {"version":3,"file":"gitops_task_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/gitops_task_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAGtD,OAAO,EAAsB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAIN,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,MAAM,iBAAiB,CAAC;AAQzB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,MAAM,WAAW,yBAAyB;IACzC,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAC;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAChC,SAAS,yBAAyB,KAChC,OAAO,CAAC;IACV,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,YAAY,CAAC;IAC5B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;CACvC,CA0BA,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,GAC5B,SAAS,yBAAyB,KAChC,OAAO,CAAC;IAAE,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAA;CAAE,CAI3C,CAAC;AAEF,MAAM,WAAW,2BAA2B;IAC3C,gDAAgD;IAChD,WAAW,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACtC,sFAAsF;IACtF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,UAAU,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,sBAAsB,GAClC,SAAS,2BAA2B,KAClC,OAAO,CAAC,IAAI,CAuBd,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAC/B,aAAa,aAAa,CAAC,SAAS,CAAC,EACrC,KAAK,MAAM,EACX,MAAK,MAAsC,KACzC,IAKF,CAAC"}