@fuzdev/fuz_gitops 0.78.1 → 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.
- package/README.md +78 -24
- package/dist/ModulesDetail.svelte +15 -22
- package/dist/ModulesDetail.svelte.d.ts.map +1 -1
- package/dist/ModulesNav.svelte +4 -1
- package/dist/ModulesPage.svelte +1 -3
- package/dist/ModulesPage.svelte.d.ts.map +1 -1
- package/dist/PageHeader.svelte +2 -2
- package/dist/PageHeader.svelte.d.ts +0 -3
- package/dist/PageHeader.svelte.d.ts.map +1 -1
- package/dist/PullRequestsDetail.svelte +10 -9
- package/dist/PullRequestsDetail.svelte.d.ts.map +1 -1
- package/dist/PullRequestsPage.svelte +1 -3
- package/dist/PullRequestsPage.svelte.d.ts.map +1 -1
- package/dist/ReposTable.svelte +27 -48
- package/dist/ReposTable.svelte.d.ts.map +1 -1
- package/dist/ReposTree.svelte +5 -19
- package/dist/ReposTree.svelte.d.ts.map +1 -1
- package/dist/ReposTreeNav.svelte +5 -7
- package/dist/ReposTreeNav.svelte.d.ts.map +1 -1
- package/dist/TablePage.svelte +1 -3
- package/dist/TablePage.svelte.d.ts.map +1 -1
- package/dist/TreeItemPage.svelte +1 -3
- package/dist/TreeItemPage.svelte.d.ts.map +1 -1
- package/dist/TreePage.svelte +1 -3
- package/dist/TreePage.svelte.d.ts.map +1 -1
- package/dist/ci_reconcile.d.ts +6 -10
- package/dist/ci_reconcile.d.ts.map +1 -1
- package/dist/ci_reconcile.js +6 -8
- package/dist/dependency_graph.d.ts +26 -49
- package/dist/dependency_graph.d.ts.map +1 -1
- package/dist/dependency_graph.js +37 -80
- package/dist/dependency_updater.d.ts +1 -1
- package/dist/dependency_updater.d.ts.map +1 -1
- package/dist/dependency_updater.js +6 -1
- package/dist/fetch_repo_data.d.ts +34 -8
- package/dist/fetch_repo_data.d.ts.map +1 -1
- package/dist/fetch_repo_data.js +44 -22
- package/dist/fs_fetch_value_cache.d.ts +1 -1
- package/dist/fs_fetch_value_cache.js +1 -1
- package/dist/git_operations.d.ts +6 -49
- package/dist/git_operations.d.ts.map +1 -1
- package/dist/git_operations.js +13 -126
- package/dist/github.d.ts +17 -2
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +15 -6
- package/dist/github_helpers.d.ts.map +1 -1
- package/dist/github_helpers.js +3 -11
- package/dist/gitops_analyze.task.d.ts +24 -2
- package/dist/gitops_analyze.task.d.ts.map +1 -1
- package/dist/gitops_analyze.task.js +43 -30
- package/dist/gitops_config.d.ts +34 -79
- package/dist/gitops_config.d.ts.map +1 -1
- package/dist/gitops_config.js +76 -53
- package/dist/gitops_constants.d.ts +6 -4
- package/dist/gitops_constants.d.ts.map +1 -1
- package/dist/gitops_constants.js +6 -4
- package/dist/gitops_plan.task.d.ts +29 -3
- package/dist/gitops_plan.task.d.ts.map +1 -1
- package/dist/gitops_plan.task.js +80 -58
- package/dist/gitops_publish.task.d.ts +62 -2
- package/dist/gitops_publish.task.d.ts.map +1 -1
- package/dist/gitops_publish.task.js +187 -102
- package/dist/gitops_run.task.d.ts +74 -0
- package/dist/gitops_run.task.d.ts.map +1 -1
- package/dist/gitops_run.task.js +174 -160
- package/dist/gitops_sync.task.d.ts +65 -3
- package/dist/gitops_sync.task.d.ts.map +1 -1
- package/dist/gitops_sync.task.js +154 -30
- package/dist/gitops_task_helpers.d.ts +86 -59
- package/dist/gitops_task_helpers.d.ts.map +1 -1
- package/dist/gitops_task_helpers.js +120 -79
- package/dist/gitops_validate.task.d.ts +1 -2
- package/dist/gitops_validate.task.d.ts.map +1 -1
- package/dist/gitops_validate.task.js +15 -22
- package/dist/graph_validation.d.ts +16 -27
- package/dist/graph_validation.d.ts.map +1 -1
- package/dist/graph_validation.js +23 -64
- package/dist/local_repo.d.ts +50 -62
- package/dist/local_repo.d.ts.map +1 -1
- package/dist/local_repo.js +80 -193
- package/dist/log_helpers.d.ts +8 -8
- package/dist/log_helpers.d.ts.map +1 -1
- package/dist/multi_repo_publisher.d.ts +10 -0
- package/dist/multi_repo_publisher.d.ts.map +1 -1
- package/dist/multi_repo_publisher.js +115 -51
- package/dist/npm_registry.d.ts +23 -19
- package/dist/npm_registry.d.ts.map +1 -1
- package/dist/npm_registry.js +20 -47
- package/dist/operations.d.ts +75 -180
- package/dist/operations.d.ts.map +1 -1
- package/dist/operations.js +15 -7
- package/dist/operations_defaults.d.ts +17 -2
- package/dist/operations_defaults.d.ts.map +1 -1
- package/dist/operations_defaults.js +104 -121
- package/dist/output_helpers.d.ts +36 -0
- package/dist/output_helpers.d.ts.map +1 -1
- package/dist/output_helpers.js +37 -3
- package/dist/preflight_checks.d.ts +20 -27
- package/dist/preflight_checks.d.ts.map +1 -1
- package/dist/preflight_checks.js +37 -126
- package/dist/publish_steps.d.ts +2 -4
- package/dist/publish_steps.d.ts.map +1 -1
- package/dist/publish_steps.js +2 -6
- package/dist/publishing_event.d.ts +2 -8
- package/dist/publishing_event.d.ts.map +1 -1
- package/dist/publishing_event.js +5 -4
- package/dist/publishing_event_handler.d.ts +10 -8
- package/dist/publishing_event_handler.d.ts.map +1 -1
- package/dist/publishing_event_handler.js +14 -12
- package/dist/publishing_plan.d.ts +16 -1
- package/dist/publishing_plan.d.ts.map +1 -1
- package/dist/publishing_plan.js +328 -250
- 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 +21 -14
- package/dist/repo.svelte.d.ts +7 -0
- package/dist/repo.svelte.d.ts.map +1 -1
- package/dist/repo.svelte.js +3 -0
- package/dist/repo_readiness.d.ts +210 -0
- package/dist/repo_readiness.d.ts.map +1 -0
- package/dist/repo_readiness.js +516 -0
- package/dist/repos_status.d.ts +3340 -0
- package/dist/repos_status.d.ts.map +1 -0
- package/dist/repos_status.js +555 -0
- package/dist/repos_status_load.d.ts +65 -0
- package/dist/repos_status_load.d.ts.map +1 -0
- package/dist/repos_status_load.js +131 -0
- package/package.json +7 -27
- package/src/lib/ci_reconcile.ts +7 -11
- package/src/lib/dependency_graph.ts +45 -97
- package/src/lib/dependency_updater.ts +7 -1
- package/src/lib/fetch_repo_data.ts +66 -29
- package/src/lib/fs_fetch_value_cache.ts +1 -1
- package/src/lib/git_operations.ts +15 -187
- package/src/lib/github.ts +20 -8
- package/src/lib/github_helpers.ts +5 -12
- package/src/lib/gitops_analyze.task.ts +79 -41
- package/src/lib/gitops_config.ts +88 -137
- package/src/lib/gitops_constants.ts +6 -4
- package/src/lib/gitops_plan.task.ts +113 -61
- package/src/lib/gitops_publish.task.ts +255 -122
- package/src/lib/gitops_run.task.ts +250 -178
- package/src/lib/gitops_sync.task.ts +208 -33
- package/src/lib/gitops_task_helpers.ts +166 -110
- package/src/lib/gitops_validate.task.ts +17 -27
- package/src/lib/graph_validation.ts +25 -86
- package/src/lib/local_repo.ts +109 -316
- package/src/lib/log_helpers.ts +8 -18
- package/src/lib/multi_repo_publisher.ts +138 -53
- package/src/lib/npm_registry.ts +37 -62
- package/src/lib/operations.ts +78 -150
- package/src/lib/operations_defaults.ts +108 -154
- package/src/lib/output_helpers.ts +55 -3
- package/src/lib/preflight_checks.ts +47 -183
- package/src/lib/publish_steps.ts +15 -13
- package/src/lib/publishing_event.ts +5 -4
- package/src/lib/publishing_event_handler.ts +18 -16
- package/src/lib/publishing_plan.ts +451 -287
- package/src/lib/publishing_plan_logging.ts +32 -23
- package/src/lib/repo.svelte.ts +8 -0
- package/src/lib/repo_readiness.ts +647 -0
- package/src/lib/repos_status.ts +671 -0
- package/src/lib/repos_status_load.ts +173 -0
- package/dist/config_reconcile.d.ts +0 -46
- package/dist/config_reconcile.d.ts.map +0 -1
- package/dist/config_reconcile.js +0 -64
- package/dist/paths.d.ts +0 -7
- package/dist/paths.d.ts.map +0 -1
- package/dist/paths.js +0 -6
- package/dist/repo_ops.d.ts +0 -59
- package/dist/repo_ops.d.ts.map +0 -1
- package/dist/repo_ops.js +0 -170
- package/dist/resolved_gitops_config.d.ts +0 -9
- package/dist/resolved_gitops_config.d.ts.map +0 -1
- package/dist/resolved_gitops_config.js +0 -12
- package/src/lib/config_reconcile.ts +0 -98
- package/src/lib/paths.ts +0 -6
- package/src/lib/repo_ops.ts +0 -216
- package/src/lib/resolved_gitops_config.ts +0 -27
package/dist/ci_reconcile.d.ts
CHANGED
|
@@ -2,14 +2,12 @@
|
|
|
2
2
|
* Reconciles each repo's declared `ci` flag against whether it actually has
|
|
3
3
|
* GitHub Actions workflow files on disk.
|
|
4
4
|
*
|
|
5
|
-
* The
|
|
6
|
-
* private) with per-repo overrides; this check catches drift between
|
|
7
|
-
* declaration and reality —
|
|
5
|
+
* The registry (`repos.toml`) derives `ci` from visibility (on for public repos,
|
|
6
|
+
* off for private) with per-repo overrides; this check catches drift between
|
|
7
|
+
* that declaration and reality —
|
|
8
8
|
* a repo that claims CI but ships no workflow, or one that disclaims CI yet
|
|
9
|
-
* still carries one.
|
|
10
|
-
*
|
|
11
|
-
* frozen on their host, so their CI state is intentionally left alone and they're
|
|
12
|
-
* skipped too.
|
|
9
|
+
* still carries one. Archived repos are frozen on their host, so their CI state
|
|
10
|
+
* is intentionally left alone and they're skipped.
|
|
13
11
|
*
|
|
14
12
|
* @module
|
|
15
13
|
*/
|
|
@@ -28,12 +26,10 @@ export interface CiDrift {
|
|
|
28
26
|
}
|
|
29
27
|
export interface CiReconcileInput {
|
|
30
28
|
repo_url: string;
|
|
31
|
-
/** The declared/derived `ci` value from the
|
|
29
|
+
/** The declared/derived `ci` value from the registry. */
|
|
32
30
|
ci: boolean;
|
|
33
31
|
/** Whether the repo has at least one workflow file on disk. */
|
|
34
32
|
has_workflows: boolean;
|
|
35
|
-
/** Whether the repo is checked out locally; uncheckable repos are skipped. */
|
|
36
|
-
checkable: boolean;
|
|
37
33
|
/** Whether the repo is archived (frozen) on its host; archived repos are skipped. */
|
|
38
34
|
archived: boolean;
|
|
39
35
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci_reconcile.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/ci_reconcile.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ci_reconcile.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/ci_reconcile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,2EAA2E;AAC3E,MAAM,MAAM,WAAW;AACtB,yDAAyD;AACvD,YAAY;AACd,uDAAuD;GACrD,UAAU,CAAC;AAEd,MAAM,WAAW,OAAO;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,EAAE,EAAE,OAAO,CAAC;IACZ,aAAa,EAAE,OAAO,CAAC;IACvB,IAAI,EAAE,WAAW,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,EAAE,EAAE,OAAO,CAAC;IACZ,+DAA+D;IAC/D,aAAa,EAAE,OAAO,CAAC;IACvB,qFAAqF;IACrF,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,KAAK,CAAC,gBAAgB,CAAC,KAAG,KAAK,CAAC,OAAO,CAY1E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,KAAG,OAIrD,CAAC"}
|
package/dist/ci_reconcile.js
CHANGED
|
@@ -2,14 +2,12 @@
|
|
|
2
2
|
* Reconciles each repo's declared `ci` flag against whether it actually has
|
|
3
3
|
* GitHub Actions workflow files on disk.
|
|
4
4
|
*
|
|
5
|
-
* The
|
|
6
|
-
* private) with per-repo overrides; this check catches drift between
|
|
7
|
-
* declaration and reality —
|
|
5
|
+
* The registry (`repos.toml`) derives `ci` from visibility (on for public repos,
|
|
6
|
+
* off for private) with per-repo overrides; this check catches drift between
|
|
7
|
+
* that declaration and reality —
|
|
8
8
|
* a repo that claims CI but ships no workflow, or one that disclaims CI yet
|
|
9
|
-
* still carries one.
|
|
10
|
-
*
|
|
11
|
-
* frozen on their host, so their CI state is intentionally left alone and they're
|
|
12
|
-
* skipped too.
|
|
9
|
+
* still carries one. Archived repos are frozen on their host, so their CI state
|
|
10
|
+
* is intentionally left alone and they're skipped.
|
|
13
11
|
*
|
|
14
12
|
* @module
|
|
15
13
|
*/
|
|
@@ -22,7 +20,7 @@ import { join } from 'node:path';
|
|
|
22
20
|
export const reconcile_ci = (repos) => {
|
|
23
21
|
const drift = [];
|
|
24
22
|
for (const repo of repos) {
|
|
25
|
-
if (
|
|
23
|
+
if (repo.archived)
|
|
26
24
|
continue;
|
|
27
25
|
const { repo_url, ci, has_workflows } = repo;
|
|
28
26
|
if (ci && !has_workflows) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dependency graph data structure and algorithms for multi-repo publishing.
|
|
3
3
|
*
|
|
4
|
-
* Provides `DependencyGraph` class with topological sort
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Provides the `DependencyGraph` class, built from local repos, with topological sort
|
|
5
|
+
* (via `@fuzdev/fuz_util/sort.ts`), cycle detection by dependency type, and
|
|
6
|
+
* wildcard-range analysis.
|
|
7
|
+
* For the publishing order and the analysis workflow, see `graph_validation.ts`.
|
|
7
8
|
*
|
|
8
9
|
* @module
|
|
9
10
|
*/
|
|
@@ -17,7 +18,6 @@ export type DependencyType = (typeof DEPENDENCY_TYPE)[keyof typeof DEPENDENCY_TY
|
|
|
17
18
|
export interface DependencySpec {
|
|
18
19
|
type: DependencyType;
|
|
19
20
|
version: string;
|
|
20
|
-
resolved?: string;
|
|
21
21
|
}
|
|
22
22
|
export interface DependencyGraphJson {
|
|
23
23
|
nodes: Array<{
|
|
@@ -28,7 +28,6 @@ export interface DependencyGraphJson {
|
|
|
28
28
|
spec: DependencySpec;
|
|
29
29
|
}>;
|
|
30
30
|
dependents: Array<string>;
|
|
31
|
-
publishable: boolean;
|
|
32
31
|
}>;
|
|
33
32
|
edges: Array<{
|
|
34
33
|
from: string;
|
|
@@ -38,20 +37,32 @@ export interface DependencyGraphJson {
|
|
|
38
37
|
export interface DependencyNode {
|
|
39
38
|
name: string;
|
|
40
39
|
version: string;
|
|
41
|
-
repo?: LocalRepo;
|
|
42
40
|
dependencies: Map<string, DependencySpec>;
|
|
43
41
|
dependents: Set<string>;
|
|
44
|
-
|
|
42
|
+
}
|
|
43
|
+
/** Cycles and wildcard dependencies found by `DependencyGraph.analyze`. */
|
|
44
|
+
export interface DependencyAnalysis {
|
|
45
|
+
production_cycles: Array<Array<string>>;
|
|
46
|
+
dev_cycles: Array<Array<string>>;
|
|
47
|
+
wildcard_deps: Array<{
|
|
48
|
+
pkg: string;
|
|
49
|
+
dep: string;
|
|
50
|
+
version: string;
|
|
51
|
+
}>;
|
|
45
52
|
}
|
|
46
53
|
export declare class DependencyGraph {
|
|
47
54
|
#private;
|
|
48
55
|
nodes: Map<string, DependencyNode>;
|
|
49
56
|
edges: Map<string, Set<string>>;
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Builds the graph from local repos.
|
|
59
|
+
*
|
|
60
|
+
* Two passes: first creates nodes, then builds edges (dependents).
|
|
61
|
+
* Prioritizes prod/peer deps over dev deps when the same package appears in
|
|
62
|
+
* multiple dependency types (the stronger constraint wins).
|
|
63
|
+
*/
|
|
64
|
+
constructor(repos: Array<LocalRepo>);
|
|
52
65
|
get_node(name: string): DependencyNode | undefined;
|
|
53
|
-
get_dependents(name: string): Set<string>;
|
|
54
|
-
get_dependencies(name: string): Map<string, DependencySpec>;
|
|
55
66
|
/**
|
|
56
67
|
* Computes topological sort order for dependency graph.
|
|
57
68
|
*
|
|
@@ -79,45 +90,11 @@ export declare class DependencyGraph {
|
|
|
79
90
|
production_cycles: Array<Array<string>>;
|
|
80
91
|
dev_cycles: Array<Array<string>>;
|
|
81
92
|
};
|
|
82
|
-
toJSON(): DependencyGraphJson;
|
|
83
|
-
}
|
|
84
|
-
/**
|
|
85
|
-
* Builder for creating and analyzing dependency graphs.
|
|
86
|
-
*/
|
|
87
|
-
export declare class DependencyGraphBuilder {
|
|
88
|
-
/**
|
|
89
|
-
* Constructs dependency graph from local repos.
|
|
90
|
-
*
|
|
91
|
-
* Two-pass algorithm: first creates nodes, then builds edges (dependents).
|
|
92
|
-
* Prioritizes prod/peer deps over dev deps when same package appears in
|
|
93
|
-
* multiple dependency types (stronger constraint wins).
|
|
94
|
-
*
|
|
95
|
-
* @returns fully initialized dependency graph with all nodes and edges
|
|
96
|
-
*/
|
|
97
|
-
build_from_repos(repos: Array<LocalRepo>): DependencyGraph;
|
|
98
93
|
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
* Excludes dev dependencies to break circular dev dependency cycles while
|
|
102
|
-
* preserving production/peer dependency ordering. This allows patterns like
|
|
103
|
-
* shared test utilities that depend on each other for development.
|
|
104
|
-
*
|
|
105
|
-
* @returns package names in safe publishing order (dependencies before dependents)
|
|
106
|
-
* @throws {Error} if production/peer cycles detected (cannot be resolved by exclusion)
|
|
94
|
+
* Reports cycles by type and wildcard (`*`) dependency ranges.
|
|
95
|
+
* Tolerates cycles: it reports them rather than throwing.
|
|
107
96
|
*/
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
production_cycles: Array<Array<string>>;
|
|
111
|
-
dev_cycles: Array<Array<string>>;
|
|
112
|
-
wildcard_deps: Array<{
|
|
113
|
-
pkg: string;
|
|
114
|
-
dep: string;
|
|
115
|
-
version: string;
|
|
116
|
-
}>;
|
|
117
|
-
missing_peers: Array<{
|
|
118
|
-
pkg: string;
|
|
119
|
-
dep: string;
|
|
120
|
-
}>;
|
|
121
|
-
};
|
|
97
|
+
analyze(): DependencyAnalysis;
|
|
98
|
+
toJSON(): DependencyGraphJson;
|
|
122
99
|
}
|
|
123
100
|
//# sourceMappingURL=dependency_graph.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency_graph.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/dependency_graph.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"dependency_graph.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/dependency_graph.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,eAAO,MAAM,eAAe;;;;CAIlB,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC;AAEpF,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,cAAc,CAAA;SAAE,CAAC,CAAC;QAC5D,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;KAC1B,CAAC,CAAC;IACH,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACxB;AAED,2EAA2E;AAC3E,MAAM,WAAW,kBAAkB;IAClC,iBAAiB,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACxC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;IACjC,aAAa,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpE;AAED,qBAAa,eAAe;;IAC3B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAa;IAC/C,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAa;IAE5C;;;;;;OAMG;gBACS,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IA4CnC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAIlD;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,WAAW,UAAQ,GAAG,KAAK,CAAC,MAAM,CAAC;IAiBpD;;;;;;;;;;OAUG;IACH,qBAAqB,IAAI;QACxB,iBAAiB,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACxC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;KACjC;IAMD;;;OAGG;IACH,OAAO,IAAI,kBAAkB;IAyD7B,MAAM,IAAI,mBAAmB;CAoB7B"}
|
package/dist/dependency_graph.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dependency graph data structure and algorithms for multi-repo publishing.
|
|
3
3
|
*
|
|
4
|
-
* Provides `DependencyGraph` class with topological sort
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Provides the `DependencyGraph` class, built from local repos, with topological sort
|
|
5
|
+
* (via `@fuzdev/fuz_util/sort.ts`), cycle detection by dependency type, and
|
|
6
|
+
* wildcard-range analysis.
|
|
7
|
+
* For the publishing order and the analysis workflow, see `graph_validation.ts`.
|
|
7
8
|
*
|
|
8
9
|
* @module
|
|
9
10
|
*/
|
|
@@ -15,30 +16,28 @@ export const DEPENDENCY_TYPE = {
|
|
|
15
16
|
DEV: 'dev'
|
|
16
17
|
};
|
|
17
18
|
export class DependencyGraph {
|
|
18
|
-
nodes;
|
|
19
|
-
edges; // pkg -> dependents
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
nodes = new Map();
|
|
20
|
+
edges = new Map(); // pkg -> dependents
|
|
21
|
+
/**
|
|
22
|
+
* Builds the graph from local repos.
|
|
23
|
+
*
|
|
24
|
+
* Two passes: first creates nodes, then builds edges (dependents).
|
|
25
|
+
* Prioritizes prod/peer deps over dev deps when the same package appears in
|
|
26
|
+
* multiple dependency types (the stronger constraint wins).
|
|
27
|
+
*/
|
|
28
|
+
constructor(repos) {
|
|
29
|
+
// first pass: create nodes
|
|
26
30
|
for (const repo of repos) {
|
|
27
31
|
const { library, package_json } = repo;
|
|
28
32
|
const node = {
|
|
29
33
|
name: library.name,
|
|
30
34
|
version: package_json.version || '0.0.0',
|
|
31
|
-
repo,
|
|
32
35
|
dependencies: new Map(),
|
|
33
|
-
dependents: new Set()
|
|
34
|
-
publishable: !package_json.private
|
|
36
|
+
dependents: new Set()
|
|
35
37
|
};
|
|
36
|
-
// Extract dependencies
|
|
37
38
|
const deps = package_json.dependencies || EMPTY_OBJECT;
|
|
38
39
|
const dev_deps = package_json.devDependencies || EMPTY_OBJECT;
|
|
39
40
|
const peer_deps = package_json.peerDependencies || EMPTY_OBJECT;
|
|
40
|
-
// Add dependencies, prioritizing prod/peer over dev
|
|
41
|
-
// (if a package appears in multiple dep types, use the stronger constraint)
|
|
42
41
|
for (const [name, version] of Object.entries(deps)) {
|
|
43
42
|
node.dependencies.set(name, { type: DEPENDENCY_TYPE.PROD, version });
|
|
44
43
|
}
|
|
@@ -46,7 +45,7 @@ export class DependencyGraph {
|
|
|
46
45
|
node.dependencies.set(name, { type: DEPENDENCY_TYPE.PEER, version });
|
|
47
46
|
}
|
|
48
47
|
for (const [name, version] of Object.entries(dev_deps)) {
|
|
49
|
-
//
|
|
48
|
+
// only add dev deps if not already present as prod/peer
|
|
50
49
|
if (!node.dependencies.has(name)) {
|
|
51
50
|
node.dependencies.set(name, { type: DEPENDENCY_TYPE.DEV, version });
|
|
52
51
|
}
|
|
@@ -54,12 +53,11 @@ export class DependencyGraph {
|
|
|
54
53
|
this.nodes.set(library.name, node);
|
|
55
54
|
this.edges.set(library.name, new Set());
|
|
56
55
|
}
|
|
57
|
-
//
|
|
56
|
+
// second pass: build edges (dependents) for internal dependencies
|
|
58
57
|
for (const node of this.nodes.values()) {
|
|
59
58
|
for (const [dep_name] of node.dependencies) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const dep_node = this.nodes.get(dep_name);
|
|
59
|
+
const dep_node = this.nodes.get(dep_name);
|
|
60
|
+
if (dep_node) {
|
|
63
61
|
dep_node.dependents.add(node.name);
|
|
64
62
|
this.edges.get(dep_name).add(node.name);
|
|
65
63
|
}
|
|
@@ -69,13 +67,6 @@ export class DependencyGraph {
|
|
|
69
67
|
get_node(name) {
|
|
70
68
|
return this.nodes.get(name);
|
|
71
69
|
}
|
|
72
|
-
get_dependents(name) {
|
|
73
|
-
return this.edges.get(name) || new Set();
|
|
74
|
-
}
|
|
75
|
-
get_dependencies(name) {
|
|
76
|
-
const node = this.nodes.get(name);
|
|
77
|
-
return node ? node.dependencies : new Map();
|
|
78
|
-
}
|
|
79
70
|
/**
|
|
80
71
|
* Computes topological sort order for dependency graph.
|
|
81
72
|
*
|
|
@@ -120,6 +111,22 @@ export class DependencyGraph {
|
|
|
120
111
|
const dev_cycles = this.#find_cycles((spec) => spec.type === DEPENDENCY_TYPE.DEV);
|
|
121
112
|
return { production_cycles, dev_cycles };
|
|
122
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Reports cycles by type and wildcard (`*`) dependency ranges.
|
|
116
|
+
* Tolerates cycles: it reports them rather than throwing.
|
|
117
|
+
*/
|
|
118
|
+
analyze() {
|
|
119
|
+
const { production_cycles, dev_cycles } = this.detect_cycles_by_type();
|
|
120
|
+
const wildcard_deps = [];
|
|
121
|
+
for (const node of this.nodes.values()) {
|
|
122
|
+
for (const [dep_name, spec] of node.dependencies) {
|
|
123
|
+
if (spec.version === '*') {
|
|
124
|
+
wildcard_deps.push({ pkg: node.name, dep: dep_name, version: spec.version });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return { production_cycles, dev_cycles, wildcard_deps };
|
|
129
|
+
}
|
|
123
130
|
/** DFS cycle detection following only edges that match the filter. */
|
|
124
131
|
#find_cycles(include) {
|
|
125
132
|
const cycles = [];
|
|
@@ -167,8 +174,7 @@ export class DependencyGraph {
|
|
|
167
174
|
name,
|
|
168
175
|
spec
|
|
169
176
|
})),
|
|
170
|
-
dependents: Array.from(node.dependents)
|
|
171
|
-
publishable: node.publishable
|
|
177
|
+
dependents: Array.from(node.dependents)
|
|
172
178
|
}));
|
|
173
179
|
const edges = [];
|
|
174
180
|
for (const [from, tos] of this.edges) {
|
|
@@ -179,52 +185,3 @@ export class DependencyGraph {
|
|
|
179
185
|
return { nodes, edges };
|
|
180
186
|
}
|
|
181
187
|
}
|
|
182
|
-
/**
|
|
183
|
-
* Builder for creating and analyzing dependency graphs.
|
|
184
|
-
*/
|
|
185
|
-
export class DependencyGraphBuilder {
|
|
186
|
-
/**
|
|
187
|
-
* Constructs dependency graph from local repos.
|
|
188
|
-
*
|
|
189
|
-
* Two-pass algorithm: first creates nodes, then builds edges (dependents).
|
|
190
|
-
* Prioritizes prod/peer deps over dev deps when same package appears in
|
|
191
|
-
* multiple dependency types (stronger constraint wins).
|
|
192
|
-
*
|
|
193
|
-
* @returns fully initialized dependency graph with all nodes and edges
|
|
194
|
-
*/
|
|
195
|
-
build_from_repos(repos) {
|
|
196
|
-
const graph = new DependencyGraph();
|
|
197
|
-
graph.init_from_repos(repos);
|
|
198
|
-
return graph;
|
|
199
|
-
}
|
|
200
|
-
/**
|
|
201
|
-
* Computes publishing order using topological sort with dev deps excluded.
|
|
202
|
-
*
|
|
203
|
-
* Excludes dev dependencies to break circular dev dependency cycles while
|
|
204
|
-
* preserving production/peer dependency ordering. This allows patterns like
|
|
205
|
-
* shared test utilities that depend on each other for development.
|
|
206
|
-
*
|
|
207
|
-
* @returns package names in safe publishing order (dependencies before dependents)
|
|
208
|
-
* @throws {Error} if production/peer cycles detected (cannot be resolved by exclusion)
|
|
209
|
-
*/
|
|
210
|
-
compute_publishing_order(graph) {
|
|
211
|
-
return graph.topological_sort(true); // Exclude dev dependencies
|
|
212
|
-
}
|
|
213
|
-
analyze(graph) {
|
|
214
|
-
const { production_cycles, dev_cycles } = graph.detect_cycles_by_type();
|
|
215
|
-
const wildcard_deps = [];
|
|
216
|
-
const missing_peers = [];
|
|
217
|
-
for (const node of graph.nodes.values()) {
|
|
218
|
-
for (const [dep_name, spec] of node.dependencies) {
|
|
219
|
-
if (spec.version === '*') {
|
|
220
|
-
wildcard_deps.push({ pkg: node.name, dep: dep_name, version: spec.version });
|
|
221
|
-
}
|
|
222
|
-
if (spec.type === DEPENDENCY_TYPE.PEER && !graph.nodes.has(dep_name)) {
|
|
223
|
-
// External peer dependency
|
|
224
|
-
missing_peers.push({ pkg: node.name, dep: dep_name });
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
return { production_cycles, dev_cycles, wildcard_deps, missing_peers };
|
|
229
|
-
}
|
|
230
|
-
}
|
|
@@ -19,7 +19,7 @@ export interface UpdatePackageJsonOptions {
|
|
|
19
19
|
* 3. Creates auto-changeset if `published_versions` provided (for transitive updates)
|
|
20
20
|
* 4. Commits both `package.json` and changeset with standard message
|
|
21
21
|
*
|
|
22
|
-
* Uses version strategy to determine prefix (exact, caret, tilde) while preserving
|
|
22
|
+
* Uses version strategy to determine prefix (exact, caret, tilde, gte) while preserving
|
|
23
23
|
* existing prefixes when possible.
|
|
24
24
|
*
|
|
25
25
|
* @throws {Error} if file operations or git operations fail
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency_updater.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/dependency_updater.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAGtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAMlE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGnE,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC;AAElE,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,MAAM,CAAC,EAAE,YAAY,CAAC;CACtB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,SAAS,EACf,SAAS,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,UAAS,wBAA6B,KACpC,OAAO,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"dependency_updater.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/dependency_updater.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAGtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAMlE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGnE,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,KAAK,CAAC;AAElE,MAAM,WAAW,wBAAwB;IACxC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,MAAM,CAAC,EAAE,YAAY,CAAC;CACtB;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM,SAAS,EACf,SAAS,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,UAAS,wBAA6B,KACpC,OAAO,CAAC,IAAI,CAwId,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,MAAM,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,eAAO,MAAM,gBAAgB,GAC5B,OAAO,KAAK,CAAC,SAAS,CAAC,EACvB,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,UAAS,qBAA0B,KACjC,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC,CAAA;CAAE,CAuD5E,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAC/B,MAAM,SAAS,EACf,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,KAC5B,GAAG,CACL,MAAM,EACN;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,cAAc,GAAG,iBAAiB,GAAG,kBAAkB,CAAA;CAAE,CAkD/F,CAAC"}
|
|
@@ -11,7 +11,7 @@ import { default_git_operations, default_fs_operations } from './operations_defa
|
|
|
11
11
|
* 3. Creates auto-changeset if `published_versions` provided (for transitive updates)
|
|
12
12
|
* 4. Commits both `package.json` and changeset with standard message
|
|
13
13
|
*
|
|
14
|
-
* Uses version strategy to determine prefix (exact, caret, tilde) while preserving
|
|
14
|
+
* Uses version strategy to determine prefix (exact, caret, tilde, gte) while preserving
|
|
15
15
|
* existing prefixes when possible.
|
|
16
16
|
*
|
|
17
17
|
* @throws {Error} if file operations or git operations fail
|
|
@@ -73,6 +73,7 @@ export const update_package_json = async (repo, updates, options = {}) => {
|
|
|
73
73
|
if (!write_result.ok) {
|
|
74
74
|
throw new Error(`Failed to write package.json: ${write_result.message}`);
|
|
75
75
|
}
|
|
76
|
+
const staged = [];
|
|
76
77
|
// Create changeset if we have published version info
|
|
77
78
|
if (published_versions && published_versions.size > 0) {
|
|
78
79
|
// Build dependency updates info for changeset
|
|
@@ -107,6 +108,7 @@ export const update_package_json = async (repo, updates, options = {}) => {
|
|
|
107
108
|
if (!add_result.ok) {
|
|
108
109
|
throw new Error(`Failed to stage changeset: ${add_result.message}`);
|
|
109
110
|
}
|
|
111
|
+
staged.push(changeset_path);
|
|
110
112
|
}
|
|
111
113
|
}
|
|
112
114
|
// Commit the changes (including both package.json and changeset)
|
|
@@ -114,8 +116,11 @@ export const update_package_json = async (repo, updates, options = {}) => {
|
|
|
114
116
|
if (!add_pkg_result.ok) {
|
|
115
117
|
throw new Error(`Failed to stage package.json: ${add_pkg_result.message}`);
|
|
116
118
|
}
|
|
119
|
+
staged.push('package.json');
|
|
120
|
+
// commit only what this staged, so nothing else in the index rides along
|
|
117
121
|
const commit_result = await git_ops.commit({
|
|
118
122
|
message: `update dependencies after publishing`,
|
|
123
|
+
files: staged,
|
|
119
124
|
cwd: repo.repo_dir
|
|
120
125
|
});
|
|
121
126
|
if (!commit_result.ok) {
|
|
@@ -2,18 +2,44 @@ import type { Logger } from '@fuzdev/fuz_util/log.ts';
|
|
|
2
2
|
import type { FetchValueCache } from '@fuzdev/fuz_util/fetch.ts';
|
|
3
3
|
import type { RepoJson } from './repo.svelte.js';
|
|
4
4
|
import type { LocalRepo } from './local_repo.js';
|
|
5
|
+
/**
|
|
6
|
+
* Options for `fetch_repo_data`.
|
|
7
|
+
*/
|
|
8
|
+
export interface FetchRepoDataOptions {
|
|
9
|
+
/** The repos to fetch GitHub metadata for, in order. */
|
|
10
|
+
local_repos: Array<LocalRepo>;
|
|
11
|
+
/** GitHub API token, sent with each request. */
|
|
12
|
+
token?: string;
|
|
13
|
+
/** Response memoization, from `fuz_util`'s `fetch.ts`. */
|
|
14
|
+
cache?: FetchValueCache;
|
|
15
|
+
log?: Logger;
|
|
16
|
+
/** Milliseconds to wait before each API request. Defaults to `33`. */
|
|
17
|
+
delay?: number;
|
|
18
|
+
/** Sent as the `x-github-api-version` header when set. */
|
|
19
|
+
github_api_version?: string;
|
|
20
|
+
/** The `fetch` the API requests go through. Defaults to `globalThis.fetch`. */
|
|
21
|
+
fetch?: typeof globalThis.fetch;
|
|
22
|
+
}
|
|
5
23
|
/**
|
|
6
24
|
* Fetches GitHub metadata (CI status, PRs) for all repos.
|
|
7
25
|
*
|
|
8
|
-
* Fetches sequentially with delay
|
|
9
|
-
* Uses `await_in_loop` intentionally to avoid parallel requests
|
|
26
|
+
* Fetches sequentially with a delay before each request to respect GitHub API
|
|
27
|
+
* rate limits. Uses `await_in_loop` intentionally to avoid parallel requests
|
|
28
|
+
* overwhelming the API. CI status is read for the branch each repo's registry
|
|
29
|
+
* entry follows (`main` when it names none), and that branch is written to
|
|
30
|
+
* `RepoJson.branch`.
|
|
10
31
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
32
|
+
* A repo whose registry entry declares no CI (`ci: false`) isn't asked for
|
|
33
|
+
* check runs, and one with none on its branch isn't a failure: both leave
|
|
34
|
+
* `check_runs` `null` without logging. A failed fetch is logged as an error
|
|
35
|
+
* and leaves `null` for that repo's `check_runs` or `pull_requests`, and the
|
|
36
|
+
* remaining repos still fetch — except a 401 response or a repo URL without a
|
|
37
|
+
* GitHub owner, which throw.
|
|
13
38
|
*
|
|
14
|
-
* @param
|
|
15
|
-
* @
|
|
16
|
-
* @
|
|
39
|
+
* @param options - the repos, credentials, cache, and pacing
|
|
40
|
+
* @returns a `RepoJson` for each repo, in the order given
|
|
41
|
+
* @throws {Error} on a 401 response (check `SECRET_GITHUB_API_TOKEN`) or a
|
|
42
|
+
* repo whose URL has no GitHub owner
|
|
17
43
|
*/
|
|
18
|
-
export declare const fetch_repo_data: (
|
|
44
|
+
export declare const fetch_repo_data: (options: FetchRepoDataOptions) => Promise<Array<RepoJson>>;
|
|
19
45
|
//# sourceMappingURL=fetch_repo_data.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch_repo_data.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/fetch_repo_data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"fetch_repo_data.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/fetch_repo_data.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAEtD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAOjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACpC,wDAAwD;IACxD,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9B,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,+EAA+E;IAC/E,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;CAChC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,eAAe,GAAU,SAAS,oBAAoB,KAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CA+C5F,CAAC"}
|
package/dist/fetch_repo_data.js
CHANGED
|
@@ -3,44 +3,66 @@ import { fetch_github_check_runs, fetch_github_pull_requests } from './github.js
|
|
|
3
3
|
/**
|
|
4
4
|
* Fetches GitHub metadata (CI status, PRs) for all repos.
|
|
5
5
|
*
|
|
6
|
-
* Fetches sequentially with delay
|
|
7
|
-
* Uses `await_in_loop` intentionally to avoid parallel requests
|
|
6
|
+
* Fetches sequentially with a delay before each request to respect GitHub API
|
|
7
|
+
* rate limits. Uses `await_in_loop` intentionally to avoid parallel requests
|
|
8
|
+
* overwhelming the API. CI status is read for the branch each repo's registry
|
|
9
|
+
* entry follows (`main` when it names none), and that branch is written to
|
|
10
|
+
* `RepoJson.branch`.
|
|
8
11
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
12
|
+
* A repo whose registry entry declares no CI (`ci: false`) isn't asked for
|
|
13
|
+
* check runs, and one with none on its branch isn't a failure: both leave
|
|
14
|
+
* `check_runs` `null` without logging. A failed fetch is logged as an error
|
|
15
|
+
* and leaves `null` for that repo's `check_runs` or `pull_requests`, and the
|
|
16
|
+
* remaining repos still fetch — except a 401 response or a repo URL without a
|
|
17
|
+
* GitHub owner, which throw.
|
|
11
18
|
*
|
|
12
|
-
* @param
|
|
13
|
-
* @
|
|
14
|
-
* @
|
|
19
|
+
* @param options - the repos, credentials, cache, and pacing
|
|
20
|
+
* @returns a `RepoJson` for each repo, in the order given
|
|
21
|
+
* @throws {Error} on a 401 response (check `SECRET_GITHUB_API_TOKEN`) or a
|
|
22
|
+
* repo whose URL has no GitHub owner
|
|
15
23
|
*/
|
|
16
|
-
export const fetch_repo_data = async (
|
|
24
|
+
export const fetch_repo_data = async (options) => {
|
|
25
|
+
const { local_repos, token, cache, log, delay = 33, github_api_version, fetch } = options;
|
|
17
26
|
const repos = [];
|
|
18
|
-
for (const { library, package_json,
|
|
27
|
+
for (const { library, package_json, entry } of local_repos) {
|
|
19
28
|
const repo_url = library.repo_url;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const branch = entry.branch ?? 'main';
|
|
30
|
+
// CI status, for repos the registry says run CI
|
|
31
|
+
let check_runs = null;
|
|
32
|
+
if (entry.ci) {
|
|
33
|
+
await wait(delay);
|
|
34
|
+
const fetched = await fetch_github_check_runs(library, {
|
|
35
|
+
cache,
|
|
36
|
+
log,
|
|
37
|
+
token,
|
|
38
|
+
api_version: github_api_version,
|
|
39
|
+
ref: branch,
|
|
40
|
+
fetch
|
|
41
|
+
});
|
|
42
|
+
if (fetched.ok) {
|
|
43
|
+
check_runs = fetched.value;
|
|
44
|
+
if (!check_runs)
|
|
45
|
+
log?.debug(`no check runs on \`${branch}\`: ${repo_url}`);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
log?.error(`failed to fetch CI status (${fetched.status}): ${repo_url}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
31
51
|
// pull requests
|
|
32
52
|
await wait(delay);
|
|
33
53
|
const pull_requests = await fetch_github_pull_requests(library, {
|
|
34
54
|
cache,
|
|
35
55
|
log,
|
|
36
56
|
token,
|
|
37
|
-
api_version: github_api_version
|
|
57
|
+
api_version: github_api_version,
|
|
58
|
+
fetch
|
|
38
59
|
});
|
|
39
60
|
if (!pull_requests)
|
|
40
|
-
log?.error('failed to fetch
|
|
61
|
+
log?.error('failed to fetch pull requests: ' + repo_url);
|
|
41
62
|
repos.push({
|
|
42
63
|
library_json: library.library_json,
|
|
43
64
|
package_json,
|
|
65
|
+
branch,
|
|
44
66
|
check_runs,
|
|
45
67
|
pull_requests
|
|
46
68
|
});
|
|
@@ -14,7 +14,7 @@ export interface FetchCache {
|
|
|
14
14
|
* cache is cleared (delete file) and starts fresh. This handles format changes.
|
|
15
15
|
*
|
|
16
16
|
* Uses `structuredClone` to track changes - only writes to disk if data modified.
|
|
17
|
-
* Formatted with
|
|
17
|
+
* Formatted with gro's `format_file` before writing for version control friendliness.
|
|
18
18
|
*
|
|
19
19
|
* @param name - cache filename (without .json extension)
|
|
20
20
|
* @param dir - cache directory (defaults to `.gro/build/fetch/`)
|
|
@@ -11,7 +11,7 @@ import { existsSync } from 'node:fs';
|
|
|
11
11
|
* cache is cleared (delete file) and starts fresh. This handles format changes.
|
|
12
12
|
*
|
|
13
13
|
* Uses `structuredClone` to track changes - only writes to disk if data modified.
|
|
14
|
-
* Formatted with
|
|
14
|
+
* Formatted with gro's `format_file` before writing for version control friendliness.
|
|
15
15
|
*
|
|
16
16
|
* @param name - cache filename (without .json extension)
|
|
17
17
|
* @param dir - cache directory (defaults to `.gro/build/fetch/`)
|