@aspruyt/xfg 5.7.0 → 6.0.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/dist/cli/sync-command.js +35 -37
- package/dist/cli/types.d.ts +12 -11
- package/dist/{output → cli}/unified-summary.d.ts +3 -3
- package/dist/{output → cli}/unified-summary.js +4 -4
- package/dist/config/file-reference-resolver.js +24 -56
- package/dist/config/normalizer.js +29 -40
- package/dist/config/validator.js +94 -102
- package/dist/lifecycle/ado-migration-source.d.ts +1 -1
- package/dist/lifecycle/ado-migration-source.js +1 -1
- package/dist/lifecycle/github-lifecycle-provider.d.ts +5 -6
- package/dist/lifecycle/github-lifecycle-provider.js +51 -20
- package/dist/lifecycle/lifecycle-formatter.d.ts +2 -1
- package/dist/lifecycle/lifecycle-formatter.js +1 -1
- package/dist/lifecycle/lifecycle-helpers.d.ts +1 -1
- package/dist/lifecycle/repo-lifecycle-manager.d.ts +1 -1
- package/dist/lifecycle/repo-lifecycle-manager.js +16 -6
- package/dist/lifecycle/types.d.ts +30 -8
- package/dist/output/lifecycle-report.d.ts +4 -2
- package/dist/output/settings-report.d.ts +4 -4
- package/dist/repo/detector.d.ts +8 -0
- package/dist/{shared/repo-detector.js → repo/detector.js} +1 -4
- package/dist/repo/index.d.ts +4 -0
- package/dist/repo/index.js +3 -0
- package/dist/{shared/repo-metadata-provider.d.ts → repo/metadata-provider.d.ts} +3 -3
- package/dist/{shared/repo-metadata-provider.js → repo/metadata-provider.js} +3 -3
- package/dist/{shared/repo-detector.d.ts → repo/types.d.ts} +1 -7
- package/dist/repo/types.js +1 -0
- package/dist/{shared/repo-info-utils.d.ts → repo/utils.d.ts} +1 -1
- package/dist/{shared/repo-info-utils.js → repo/utils.js} +1 -1
- package/dist/settings/base-processor.d.ts +1 -1
- package/dist/settings/base-processor.js +1 -1
- package/dist/settings/code-scanning/github-code-scanning-strategy.d.ts +1 -1
- package/dist/settings/code-scanning/github-code-scanning-strategy.js +1 -1
- package/dist/settings/code-scanning/processor.d.ts +2 -2
- package/dist/settings/code-scanning/types.d.ts +1 -1
- package/dist/settings/index.d.ts +1 -1
- package/dist/settings/labels/formatter.js +16 -11
- package/dist/settings/labels/github-labels-strategy.d.ts +1 -1
- package/dist/settings/labels/github-labels-strategy.js +1 -1
- package/dist/settings/labels/processor.d.ts +1 -1
- package/dist/settings/labels/types.d.ts +1 -1
- package/dist/settings/repo-settings/diff.d.ts +1 -1
- package/dist/settings/repo-settings/diff.js +1 -1
- package/dist/settings/repo-settings/formatter.js +2 -4
- package/dist/settings/repo-settings/github-repo-settings-strategy.d.ts +4 -4
- package/dist/settings/repo-settings/github-repo-settings-strategy.js +4 -4
- package/dist/settings/repo-settings/processor.d.ts +2 -2
- package/dist/settings/repo-settings/processor.js +5 -5
- package/dist/settings/repo-settings/types.d.ts +4 -4
- package/dist/settings/rulesets/diff-algorithm.js +1 -1
- package/dist/settings/rulesets/formatter.js +0 -3
- package/dist/settings/rulesets/github-ruleset-strategy.d.ts +1 -1
- package/dist/settings/rulesets/github-ruleset-strategy.js +1 -1
- package/dist/settings/rulesets/processor.d.ts +1 -1
- package/dist/settings/rulesets/types.d.ts +1 -1
- package/dist/shared/command-executor.js +3 -3
- package/dist/shared/gh-api-utils.d.ts +7 -4
- package/dist/shared/gh-api-utils.js +2 -2
- package/dist/shared/retry-utils.js +1 -1
- package/dist/shared/xfg-template.d.ts +22 -2
- package/dist/sync/auth-options-builder.d.ts +1 -1
- package/dist/sync/auth-options-builder.js +1 -1
- package/dist/sync/branch-manager.d.ts +1 -1
- package/dist/sync/commit-push-manager.d.ts +2 -2
- package/dist/sync/commit-push-manager.js +5 -3
- package/dist/sync/file-sync-orchestrator.d.ts +1 -1
- package/dist/sync/file-sync-strategy.d.ts +1 -1
- package/dist/sync/file-writer.js +44 -10
- package/dist/sync/repository-processor.d.ts +1 -1
- package/dist/sync/repository-session.d.ts +1 -1
- package/dist/sync/sync-workflow.d.ts +1 -1
- package/dist/sync/sync-workflow.js +2 -1
- package/dist/sync/types.d.ts +7 -4
- package/dist/vcs/{azure-pr-strategy.d.ts → ado-pr-strategy.d.ts} +2 -2
- package/dist/vcs/{azure-pr-strategy.js → ado-pr-strategy.js} +4 -4
- package/dist/vcs/authenticated-git-ops.d.ts +2 -0
- package/dist/vcs/authenticated-git-ops.js +6 -0
- package/dist/vcs/commit-strategy-selector.d.ts +2 -2
- package/dist/vcs/commit-strategy-selector.js +2 -2
- package/dist/vcs/file-mode-fixup-commit-strategy.d.ts +8 -6
- package/dist/vcs/file-mode-fixup-commit-strategy.js +79 -30
- package/dist/vcs/git-ops.d.ts +15 -3
- package/dist/vcs/git-ops.js +57 -24
- package/dist/vcs/github-app-token-manager.d.ts +3 -3
- package/dist/vcs/github-app-token-manager.js +4 -4
- package/dist/vcs/github-pr-strategy.d.ts +1 -1
- package/dist/vcs/github-pr-strategy.js +4 -4
- package/dist/vcs/gitlab-pr-strategy.d.ts +1 -1
- package/dist/vcs/gitlab-pr-strategy.js +4 -4
- package/dist/vcs/graphql-commit-strategy.js +8 -3
- package/dist/vcs/index.d.ts +1 -1
- package/dist/vcs/pr-creator.d.ts +1 -1
- package/dist/vcs/pr-strategy-factory.d.ts +1 -1
- package/dist/vcs/pr-strategy-factory.js +3 -3
- package/dist/vcs/pr-strategy.d.ts +1 -1
- package/dist/vcs/pr-strategy.js +1 -1
- package/dist/vcs/types.d.ts +10 -3
- package/package.json +2 -2
- /package/dist/{shared → vcs}/sanitize-utils.d.ts +0 -0
- /package/dist/{shared → vcs}/sanitize-utils.js +0 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RepoInfo } from "./types.js";
|
|
2
|
+
export type RepoPlatform = "github" | "azure-devops" | "gitlab";
|
|
3
|
+
interface RepoDetectorContext {
|
|
4
|
+
githubHosts?: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare function detectRepoType(gitUrl: string, context?: RepoDetectorContext): RepoPlatform;
|
|
7
|
+
export declare function parseGitUrl(gitUrl: string, context?: RepoDetectorContext): RepoInfo;
|
|
8
|
+
export {};
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import { ValidationError } from "
|
|
2
|
-
// Type guards, assertions, and display helpers live in repo-info-utils.ts.
|
|
3
|
-
// Re-exported here for backward compatibility.
|
|
4
|
-
export { isGitHubRepo, isAzureDevOpsRepo, isGitLabRepo, assertGitHubRepo, assertAzureDevOpsRepo, assertGitLabRepo, getRepoDisplayName, } from "./repo-info-utils.js";
|
|
1
|
+
import { ValidationError } from "../shared/errors.js";
|
|
5
2
|
function extractHostFromUrl(gitUrl) {
|
|
6
3
|
// SSH: git@hostname:path
|
|
7
4
|
const sshMatch = gitUrl.match(/^git@([^:]+):/);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export type { RepoInfo, GitHubRepoInfo, AzureDevOpsRepoInfo, GitLabRepoInfo, } from "./types.js";
|
|
2
|
+
export { isGitHubRepo, isAzureDevOpsRepo, isGitLabRepo, assertGitHubRepo, assertAzureDevOpsRepo, assertGitLabRepo, getRepoDisplayName, } from "./utils.js";
|
|
3
|
+
export { detectRepoType, parseGitUrl, type RepoPlatform } from "./detector.js";
|
|
4
|
+
export { GitHubRepoMetadataProvider, type IRepoMetadataProvider, type RepoMetadata, } from "./metadata-provider.js";
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { isGitHubRepo, isAzureDevOpsRepo, isGitLabRepo, assertGitHubRepo, assertAzureDevOpsRepo, assertGitLabRepo, getRepoDisplayName, } from "./utils.js";
|
|
2
|
+
export { detectRepoType, parseGitUrl } from "./detector.js";
|
|
3
|
+
export { GitHubRepoMetadataProvider, } from "./metadata-provider.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ICommandExecutor } from "
|
|
2
|
-
import {
|
|
3
|
-
import { type GhApiOptions } from "
|
|
1
|
+
import type { ICommandExecutor } from "../shared/command-executor.js";
|
|
2
|
+
import type { RepoInfo } from "./types.js";
|
|
3
|
+
import { type GhApiOptions } from "../shared/gh-api-utils.js";
|
|
4
4
|
import type { RepoVisibility } from "../config/index.js";
|
|
5
5
|
export interface RepoMetadata {
|
|
6
6
|
visibility: RepoVisibility;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { assertGitHubRepo } from "./
|
|
2
|
-
import { GhApiClient } from "
|
|
3
|
-
import { parseApiJson } from "
|
|
1
|
+
import { assertGitHubRepo } from "./utils.js";
|
|
2
|
+
import { GhApiClient } from "../shared/gh-api-utils.js";
|
|
3
|
+
import { parseApiJson } from "../shared/json-utils.js";
|
|
4
4
|
export class GitHubRepoMetadataProvider {
|
|
5
5
|
api;
|
|
6
6
|
constructor(executor, options) {
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
type RepoType = "github" | "azure-devops" | "gitlab";
|
|
2
|
-
interface RepoDetectorContext {
|
|
3
|
-
githubHosts?: string[];
|
|
4
|
-
}
|
|
5
1
|
interface BaseRepoInfo {
|
|
6
2
|
gitUrl: string;
|
|
7
3
|
repo: string;
|
|
@@ -24,6 +20,4 @@ export interface GitLabRepoInfo extends BaseRepoInfo {
|
|
|
24
20
|
host: string;
|
|
25
21
|
}
|
|
26
22
|
export type RepoInfo = GitHubRepoInfo | AzureDevOpsRepoInfo | GitLabRepoInfo;
|
|
27
|
-
export {
|
|
28
|
-
export declare function detectRepoType(gitUrl: string, context?: RepoDetectorContext): RepoType;
|
|
29
|
-
export declare function parseGitUrl(gitUrl: string, context?: RepoDetectorContext): RepoInfo;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RepoInfo, GitHubRepoInfo, AzureDevOpsRepoInfo, GitLabRepoInfo } from "./
|
|
1
|
+
import type { RepoInfo, GitHubRepoInfo, AzureDevOpsRepoInfo, GitLabRepoInfo } from "./types.js";
|
|
2
2
|
export declare function isGitHubRepo(info: RepoInfo): info is GitHubRepoInfo;
|
|
3
3
|
export declare function isAzureDevOpsRepo(info: RepoInfo): info is AzureDevOpsRepoInfo;
|
|
4
4
|
export declare function isGitLabRepo(info: RepoInfo): info is GitLabRepoInfo;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RepoConfig } from "../config/index.js";
|
|
2
|
-
import type { RepoInfo, GitHubRepoInfo } from "../
|
|
2
|
+
import type { RepoInfo, GitHubRepoInfo } from "../repo/index.js";
|
|
3
3
|
export interface BaseProcessorOptions {
|
|
4
4
|
dryRun?: boolean;
|
|
5
5
|
/** Pre-resolved auth token. Callers (e.g. sync-command) must resolve via resolveGitHubToken before passing. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isGitHubRepo, getRepoDisplayName } from "../
|
|
1
|
+
import { isGitHubRepo, getRepoDisplayName } from "../repo/index.js";
|
|
2
2
|
import { toErrorMessage } from "../shared/type-guards.js";
|
|
3
3
|
/**
|
|
4
4
|
* Build a base result that satisfies TResult for guard early-returns.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ICommandExecutor } from "../../shared/command-executor.js";
|
|
2
|
-
import { type RepoInfo } from "../../
|
|
2
|
+
import { type RepoInfo } from "../../repo/index.js";
|
|
3
3
|
import { type GhApiOptions } from "../../shared/gh-api-utils.js";
|
|
4
4
|
import type { ICodeScanningStrategy, CurrentCodeScanningSettings } from "./types.js";
|
|
5
5
|
interface GitHubCodeScanningStrategyOptions {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assertGitHubRepo } from "../../
|
|
1
|
+
import { assertGitHubRepo } from "../../repo/index.js";
|
|
2
2
|
import { GhApiClient } from "../../shared/gh-api-utils.js";
|
|
3
3
|
import { parseApiJson } from "../../shared/json-utils.js";
|
|
4
4
|
export class GitHubCodeScanningStrategy {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RepoConfig } from "../../config/index.js";
|
|
2
|
-
import type { RepoInfo } from "../../
|
|
2
|
+
import type { RepoInfo } from "../../repo/index.js";
|
|
3
3
|
import type { ICodeScanningStrategy } from "./types.js";
|
|
4
|
-
import type { IRepoMetadataProvider } from "../../
|
|
4
|
+
import type { IRepoMetadataProvider } from "../../repo/index.js";
|
|
5
5
|
import { type CodeScanningPlanResult } from "./formatter.js";
|
|
6
6
|
import { type BaseProcessorOptions, type BaseProcessorResult, type ISettingsProcessor, type ChangeCounts } from "../base-processor.js";
|
|
7
7
|
export type ICodeScanningProcessor = ISettingsProcessor<CodeScanningProcessorOptions, CodeScanningProcessorResult>;
|
package/dist/settings/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { type BaseProcessorResult, type ISettingsProcessor, countActions, isActiveAction, } from "./base-processor.js";
|
|
1
|
+
export { type BaseProcessorResult, type ISettingsProcessor, type SettingsAction, type ActiveAction, countActions, isActiveAction, } from "./base-processor.js";
|
|
2
2
|
export { type PropertyDiff, type RulesetPlanEntry, RulesetProcessor, type IRulesetProcessor, GitHubRulesetStrategy, } from "./rulesets/index.js";
|
|
3
3
|
export { RepoSettingsProcessor, type IRepoSettingsProcessor, type RepoSettingsPlanEntry, GitHubRepoSettingsStrategy, } from "./repo-settings/index.js";
|
|
4
4
|
export { type LabelsPlanEntry, LabelsProcessor, type ILabelsProcessor, GitHubLabelsStrategy, } from "./labels/index.js";
|
|
@@ -7,14 +7,19 @@ export function formatLabelsPlan(changes) {
|
|
|
7
7
|
const lines = [];
|
|
8
8
|
const entries = [];
|
|
9
9
|
const { create: creates, update: updates, delete: deletes, unchanged, } = countActions(changes);
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
const grouped = {
|
|
11
|
+
create: [],
|
|
12
|
+
update: [],
|
|
13
|
+
delete: [],
|
|
14
|
+
unchanged: [],
|
|
15
|
+
};
|
|
16
|
+
for (const c of changes) {
|
|
17
|
+
grouped[c.action].push(c);
|
|
18
|
+
}
|
|
14
19
|
// Format creates
|
|
15
|
-
if (
|
|
20
|
+
if (grouped.create.length > 0) {
|
|
16
21
|
lines.push(chalk.bold(" Create:"));
|
|
17
|
-
for (const change of
|
|
22
|
+
for (const change of grouped.create) {
|
|
18
23
|
lines.push(chalk.green(` + label "${change.name}"`));
|
|
19
24
|
if (change.desired) {
|
|
20
25
|
lines.push(chalk.green(` color: "${change.desired.color}"`));
|
|
@@ -31,9 +36,9 @@ export function formatLabelsPlan(changes) {
|
|
|
31
36
|
}
|
|
32
37
|
}
|
|
33
38
|
// Format updates
|
|
34
|
-
if (
|
|
39
|
+
if (grouped.update.length > 0) {
|
|
35
40
|
lines.push(chalk.bold(" Update:"));
|
|
36
|
-
for (const change of
|
|
41
|
+
for (const change of grouped.update) {
|
|
37
42
|
if (change.newName) {
|
|
38
43
|
lines.push(chalk.yellow(` ~ label "${change.name}" \u2192 "${change.newName}"`));
|
|
39
44
|
}
|
|
@@ -62,16 +67,16 @@ export function formatLabelsPlan(changes) {
|
|
|
62
67
|
}
|
|
63
68
|
}
|
|
64
69
|
// Format deletes
|
|
65
|
-
if (
|
|
70
|
+
if (grouped.delete.length > 0) {
|
|
66
71
|
lines.push(chalk.bold(" Delete:"));
|
|
67
|
-
for (const change of
|
|
72
|
+
for (const change of grouped.delete) {
|
|
68
73
|
lines.push(chalk.red(` - label "${change.name}"`));
|
|
69
74
|
entries.push({ name: change.name, action: "delete" });
|
|
70
75
|
}
|
|
71
76
|
lines.push("");
|
|
72
77
|
}
|
|
73
78
|
// Unchanged (entries only, no output lines)
|
|
74
|
-
for (const change of
|
|
79
|
+
for (const change of grouped.unchanged) {
|
|
75
80
|
entries.push({ name: change.name, action: "unchanged" });
|
|
76
81
|
}
|
|
77
82
|
// Summary line
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ICommandExecutor } from "../../shared/command-executor.js";
|
|
2
|
-
import { type RepoInfo } from "../../
|
|
2
|
+
import { type RepoInfo } from "../../repo/index.js";
|
|
3
3
|
import { type GhApiOptions } from "../../shared/gh-api-utils.js";
|
|
4
4
|
import type { ILabelsStrategy, GitHubLabel } from "./types.js";
|
|
5
5
|
interface GitHubLabelsStrategyOptions {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assertGitHubRepo } from "../../
|
|
1
|
+
import { assertGitHubRepo } from "../../repo/index.js";
|
|
2
2
|
import { GhApiClient } from "../../shared/gh-api-utils.js";
|
|
3
3
|
import { parseApiJson } from "../../shared/json-utils.js";
|
|
4
4
|
export class GitHubLabelsStrategy {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RepoConfig } from "../../config/index.js";
|
|
2
|
-
import type { RepoInfo } from "../../
|
|
2
|
+
import type { RepoInfo } from "../../repo/index.js";
|
|
3
3
|
import { type LabelsPlanResult } from "./formatter.js";
|
|
4
4
|
import type { ILabelsStrategy } from "./types.js";
|
|
5
5
|
import { type BaseProcessorOptions, type BaseProcessorResult, type ISettingsProcessor, type ChangeCounts } from "../base-processor.js";
|
|
@@ -16,4 +16,4 @@ export declare function diffRepoSettings(current: CurrentRepoSettings, desired:
|
|
|
16
16
|
/**
|
|
17
17
|
* Checks if there are any changes to apply.
|
|
18
18
|
*/
|
|
19
|
-
export declare function
|
|
19
|
+
export declare function hasRepoSettingsChanges(changes: RepoSettingsChange[]): boolean;
|
|
@@ -82,6 +82,6 @@ export function diffRepoSettings(current, desired) {
|
|
|
82
82
|
/**
|
|
83
83
|
* Checks if there are any changes to apply.
|
|
84
84
|
*/
|
|
85
|
-
export function
|
|
85
|
+
export function hasRepoSettingsChanges(changes) {
|
|
86
86
|
return changes.some((c) => c.action !== "unchanged");
|
|
87
87
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { formatScalarValue } from "../../shared/string-utils.js";
|
|
3
|
+
import { countActions } from "../base-processor.js";
|
|
3
4
|
/**
|
|
4
5
|
* Format a value for display.
|
|
5
6
|
*/
|
|
@@ -33,8 +34,7 @@ function getWarning(change) {
|
|
|
33
34
|
export function formatRepoSettingsPlan(changes) {
|
|
34
35
|
const lines = [];
|
|
35
36
|
const warnings = [];
|
|
36
|
-
|
|
37
|
-
let updates = 0;
|
|
37
|
+
const { create: creates, update: updates } = countActions(changes);
|
|
38
38
|
const entries = [];
|
|
39
39
|
if (changes.length === 0) {
|
|
40
40
|
return { lines, creates, updates, warnings, entries };
|
|
@@ -46,7 +46,6 @@ export function formatRepoSettingsPlan(changes) {
|
|
|
46
46
|
}
|
|
47
47
|
if (change.action === "create") {
|
|
48
48
|
lines.push(chalk.green(` + ${change.property}: ${formatValue(change.newValue)}`));
|
|
49
|
-
creates++;
|
|
50
49
|
entries.push({
|
|
51
50
|
property: change.property,
|
|
52
51
|
action: "create",
|
|
@@ -55,7 +54,6 @@ export function formatRepoSettingsPlan(changes) {
|
|
|
55
54
|
}
|
|
56
55
|
else if (change.action === "update") {
|
|
57
56
|
lines.push(chalk.yellow(` ~ ${change.property}: ${formatValue(change.oldValue)} → ${formatValue(change.newValue)}`));
|
|
58
|
-
updates++;
|
|
59
57
|
entries.push({
|
|
60
58
|
property: change.property,
|
|
61
59
|
action: "update",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ICommandExecutor } from "../../shared/command-executor.js";
|
|
2
|
-
import { type RepoInfo } from "../../
|
|
2
|
+
import { type RepoInfo } from "../../repo/index.js";
|
|
3
3
|
import { type GhApiOptions } from "../../shared/gh-api-utils.js";
|
|
4
4
|
import type { GitHubRepoSettings } from "../../config/index.js";
|
|
5
5
|
import type { IRepoSettingsStrategy, CurrentRepoSettings } from "./types.js";
|
|
@@ -10,9 +10,9 @@ interface GitHubRepoSettingsStrategyOptions {
|
|
|
10
10
|
export declare class GitHubRepoSettingsStrategy implements IRepoSettingsStrategy {
|
|
11
11
|
private api;
|
|
12
12
|
constructor(executor: ICommandExecutor, options: GitHubRepoSettingsStrategyOptions);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
get(repoInfo: RepoInfo, options?: GhApiOptions): Promise<CurrentRepoSettings>;
|
|
14
|
+
update(repoInfo: RepoInfo, settings: GitHubRepoSettings, options?: GhApiOptions): Promise<void>;
|
|
15
|
+
updateVulnerabilityAlerts(repoInfo: RepoInfo, enable: boolean, options?: GhApiOptions): Promise<void>;
|
|
16
16
|
setAutomatedSecurityFixes(repoInfo: RepoInfo, enable: boolean, options?: GhApiOptions): Promise<void>;
|
|
17
17
|
setPrivateVulnerabilityReporting(repoInfo: RepoInfo, enable: boolean, options?: GhApiOptions): Promise<void>;
|
|
18
18
|
branchExists(repoInfo: RepoInfo, branch: string, options?: GhApiOptions): Promise<boolean>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assertGitHubRepo, } from "../../
|
|
1
|
+
import { assertGitHubRepo, } from "../../repo/index.js";
|
|
2
2
|
import { GhApiClient, isHttp404Error, } from "../../shared/gh-api-utils.js";
|
|
3
3
|
import { parseApiJson } from "../../shared/json-utils.js";
|
|
4
4
|
import { camelToSnake } from "../../shared/string-utils.js";
|
|
@@ -61,7 +61,7 @@ export class GitHubRepoSettingsStrategy {
|
|
|
61
61
|
constructor(executor, options) {
|
|
62
62
|
this.api = new GhApiClient(executor, options.retries ?? 3, options.cwd);
|
|
63
63
|
}
|
|
64
|
-
async
|
|
64
|
+
async get(repoInfo, options) {
|
|
65
65
|
assertGitHubRepo(repoInfo, "GitHub Repo Settings strategy");
|
|
66
66
|
const endpoint = `/repos/${repoInfo.owner}/${repoInfo.repo}`;
|
|
67
67
|
const result = await this.api.call("GET", endpoint, { options });
|
|
@@ -76,7 +76,7 @@ export class GitHubRepoSettingsStrategy {
|
|
|
76
76
|
await this.getPrivateVulnerabilityReporting(repoInfo, options);
|
|
77
77
|
return settings;
|
|
78
78
|
}
|
|
79
|
-
async
|
|
79
|
+
async update(repoInfo, settings, options) {
|
|
80
80
|
assertGitHubRepo(repoInfo, "GitHub Repo Settings strategy");
|
|
81
81
|
const payload = configToGitHubPayload(settings);
|
|
82
82
|
// Skip if no settings to update
|
|
@@ -86,7 +86,7 @@ export class GitHubRepoSettingsStrategy {
|
|
|
86
86
|
const endpoint = `/repos/${repoInfo.owner}/${repoInfo.repo}`;
|
|
87
87
|
await this.api.call("PATCH", endpoint, { payload, options });
|
|
88
88
|
}
|
|
89
|
-
async
|
|
89
|
+
async updateVulnerabilityAlerts(repoInfo, enable, options) {
|
|
90
90
|
assertGitHubRepo(repoInfo, "GitHub Repo Settings strategy");
|
|
91
91
|
const endpoint = `/repos/${repoInfo.owner}/${repoInfo.repo}/vulnerability-alerts`;
|
|
92
92
|
const method = enable ? "PUT" : "DELETE";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { RepoConfig } from "../../config/index.js";
|
|
2
|
-
import type { RepoInfo } from "../../
|
|
2
|
+
import type { RepoInfo } from "../../repo/index.js";
|
|
3
3
|
import type { IRepoSettingsStrategy } from "./types.js";
|
|
4
|
-
import type { IRepoMetadataProvider } from "../../
|
|
4
|
+
import type { IRepoMetadataProvider } from "../../repo/index.js";
|
|
5
5
|
import { type RepoSettingsPlanResult } from "./formatter.js";
|
|
6
6
|
import { type BaseProcessorOptions, type BaseProcessorResult, type ISettingsProcessor, type ChangeCounts } from "../base-processor.js";
|
|
7
7
|
export type IRepoSettingsProcessor = ISettingsProcessor<RepoSettingsProcessorOptions, RepoSettingsProcessorResult>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { diffRepoSettings,
|
|
1
|
+
import { diffRepoSettings, hasRepoSettingsChanges } from "./diff.js";
|
|
2
2
|
import { formatRepoSettingsPlan, } from "./formatter.js";
|
|
3
3
|
import { withGitHubGuards, buildDryRunResult, buildApplyResult, } from "../base-processor.js";
|
|
4
4
|
export class RepoSettingsProcessor {
|
|
@@ -24,7 +24,7 @@ export class RepoSettingsProcessor {
|
|
|
24
24
|
const strategyOptions = { token: effectiveToken, host: githubRepo.host };
|
|
25
25
|
// Fetch current settings and metadata in parallel
|
|
26
26
|
const [currentSettings, metadata] = await Promise.all([
|
|
27
|
-
this.strategy.
|
|
27
|
+
this.strategy.get(githubRepo, strategyOptions),
|
|
28
28
|
this.metadataProvider.getMetadata(githubRepo, strategyOptions),
|
|
29
29
|
]);
|
|
30
30
|
// Validate security settings compatibility
|
|
@@ -38,7 +38,7 @@ export class RepoSettingsProcessor {
|
|
|
38
38
|
}
|
|
39
39
|
// Compute diff
|
|
40
40
|
const changes = diffRepoSettings(currentSettings, desiredSettings);
|
|
41
|
-
if (!
|
|
41
|
+
if (!hasRepoSettingsChanges(changes)) {
|
|
42
42
|
const unchangedCount = changes.filter((c) => c.action === "unchanged").length;
|
|
43
43
|
return {
|
|
44
44
|
success: true,
|
|
@@ -97,12 +97,12 @@ export class RepoSettingsProcessor {
|
|
|
97
97
|
const { vulnerabilityAlerts, automatedSecurityFixes, privateVulnerabilityReporting, ...mainSettings } = settings;
|
|
98
98
|
// Update main settings via PATCH /repos
|
|
99
99
|
if (Object.keys(mainSettings).length > 0) {
|
|
100
|
-
await this.strategy.
|
|
100
|
+
await this.strategy.update(repoInfo, mainSettings, options);
|
|
101
101
|
}
|
|
102
102
|
// Handle vulnerability alerts (separate endpoint)
|
|
103
103
|
// Must be done before automated security fixes
|
|
104
104
|
if (vulnerabilityAlerts !== undefined) {
|
|
105
|
-
await this.strategy.
|
|
105
|
+
await this.strategy.updateVulnerabilityAlerts(repoInfo, vulnerabilityAlerts, options);
|
|
106
106
|
}
|
|
107
107
|
// Handle private vulnerability reporting (separate endpoint)
|
|
108
108
|
if (privateVulnerabilityReporting !== undefined) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RepoInfo } from "../../
|
|
1
|
+
import type { RepoInfo } from "../../repo/index.js";
|
|
2
2
|
import type { GitHubRepoSettings, RepoVisibility, SquashMergeCommitTitle, SquashMergeCommitMessage, MergeCommitTitle, MergeCommitMessage } from "../../config/index.js";
|
|
3
3
|
import type { GhApiOptions } from "../../shared/gh-api-utils.js";
|
|
4
4
|
/**
|
|
@@ -46,15 +46,15 @@ export interface IRepoSettingsStrategy {
|
|
|
46
46
|
/**
|
|
47
47
|
* Gets current repository settings.
|
|
48
48
|
*/
|
|
49
|
-
|
|
49
|
+
get(repoInfo: RepoInfo, options?: GhApiOptions): Promise<CurrentRepoSettings>;
|
|
50
50
|
/**
|
|
51
51
|
* Updates repository settings.
|
|
52
52
|
*/
|
|
53
|
-
|
|
53
|
+
update(repoInfo: RepoInfo, settings: GitHubRepoSettings, options?: GhApiOptions): Promise<void>;
|
|
54
54
|
/**
|
|
55
55
|
* Enables or disables vulnerability alerts.
|
|
56
56
|
*/
|
|
57
|
-
|
|
57
|
+
updateVulnerabilityAlerts(repoInfo: RepoInfo, enable: boolean, options?: GhApiOptions): Promise<void>;
|
|
58
58
|
/**
|
|
59
59
|
* Enables or disables automated security fixes.
|
|
60
60
|
*/
|
|
@@ -116,9 +116,6 @@ function getActionStyle(action) {
|
|
|
116
116
|
return { symbol: "~", color: chalk.yellow };
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
|
-
/**
|
|
120
|
-
* Render a leaf tree node (no children) with its value.
|
|
121
|
-
*/
|
|
122
119
|
function hasComplexValue(value) {
|
|
123
120
|
return (isPlainObject(value) ||
|
|
124
121
|
(Array.isArray(value) && value.some((v) => isPlainObject(v))));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ICommandExecutor } from "../../shared/command-executor.js";
|
|
2
|
-
import { type RepoInfo } from "../../
|
|
2
|
+
import { type RepoInfo } from "../../repo/index.js";
|
|
3
3
|
import { type GhApiOptions } from "../../shared/gh-api-utils.js";
|
|
4
4
|
import type { Ruleset } from "../../config/index.js";
|
|
5
5
|
import type { IRulesetStrategy, GitHubRuleset, GitHubBypassActor, GitHubRulesetConditions, GitHubRule, RulesetUpdateParams } from "./types.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { assertGitHubRepo } from "../../
|
|
1
|
+
import { assertGitHubRepo } from "../../repo/index.js";
|
|
2
2
|
import { camelToSnake } from "../../shared/string-utils.js";
|
|
3
3
|
import { GhApiClient } from "../../shared/gh-api-utils.js";
|
|
4
4
|
import { parseApiJson } from "../../shared/json-utils.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RepoConfig } from "../../config/index.js";
|
|
2
|
-
import type { RepoInfo } from "../../
|
|
2
|
+
import type { RepoInfo } from "../../repo/index.js";
|
|
3
3
|
import type { IRulesetStrategy } from "./types.js";
|
|
4
4
|
import { type RulesetPlanResult } from "./formatter.js";
|
|
5
5
|
import { type BaseProcessorOptions, type BaseProcessorResult, type ISettingsProcessor, type ChangeCounts } from "../base-processor.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { sanitizeCredentials } from "
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
import { sanitizeCredentials } from "../vcs/sanitize-utils.js";
|
|
3
3
|
export class ShellCommandExecutor {
|
|
4
4
|
baseEnv;
|
|
5
5
|
constructor(baseEnv) {
|
|
@@ -7,7 +7,7 @@ export class ShellCommandExecutor {
|
|
|
7
7
|
}
|
|
8
8
|
async exec(command, cwd, options) {
|
|
9
9
|
try {
|
|
10
|
-
return
|
|
10
|
+
return execFileSync("sh", ["-c", command], {
|
|
11
11
|
cwd,
|
|
12
12
|
encoding: "utf-8",
|
|
13
13
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { ICommandExecutor } from "./command-executor.js";
|
|
2
|
-
import type { GitHubRepoInfo } from "./repo-detector.js";
|
|
3
2
|
import type { DebugWarnLog } from "./logger.js";
|
|
3
|
+
export interface GitHubApiTarget {
|
|
4
|
+
host: string;
|
|
5
|
+
owner: string;
|
|
6
|
+
}
|
|
4
7
|
interface ITokenManager {
|
|
5
|
-
getTokenForRepo(repoInfo:
|
|
8
|
+
getTokenForRepo(repoInfo: GitHubApiTarget): Promise<string | null>;
|
|
6
9
|
}
|
|
7
10
|
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
8
11
|
export interface GhApiOptions {
|
|
@@ -20,7 +23,7 @@ interface GhApiCallParams {
|
|
|
20
23
|
* Get the hostname flag for gh commands.
|
|
21
24
|
* Returns "--hostname HOST" for GHE, empty string for github.com.
|
|
22
25
|
*/
|
|
23
|
-
export declare function getHostnameFlag(repoInfo:
|
|
26
|
+
export declare function getHostnameFlag(repoInfo: Pick<GitHubApiTarget, "host">): string;
|
|
24
27
|
export declare function buildTokenEnv(token?: string): Record<string, string> | undefined;
|
|
25
28
|
/**
|
|
26
29
|
* Strips HTTP response headers from `gh api --include` output.
|
|
@@ -57,7 +60,7 @@ export declare class GhApiClient {
|
|
|
57
60
|
call(method: HttpMethod, endpoint: string, params?: GhApiCallParams): Promise<string>;
|
|
58
61
|
}
|
|
59
62
|
interface ResolveGitHubTokenOptions {
|
|
60
|
-
repoInfo:
|
|
63
|
+
repoInfo: GitHubApiTarget;
|
|
61
64
|
tokenManager: ITokenManager | null;
|
|
62
65
|
context: string;
|
|
63
66
|
log?: DebugWarnLog;
|
|
@@ -130,9 +130,9 @@ async function ghApiCall(method, endpoint, opts) {
|
|
|
130
130
|
(method === "POST" || method === "PUT" || method === "PATCH")) {
|
|
131
131
|
const payloadJson = JSON.stringify(payload);
|
|
132
132
|
const command = `echo ${escapeShellArg(payloadJson)} | ${baseCommand} --input -`;
|
|
133
|
-
return
|
|
133
|
+
return withRetry(() => execAndParse(command), retryOpts);
|
|
134
134
|
}
|
|
135
|
-
return
|
|
135
|
+
return withRetry(() => execAndParse(baseCommand), retryOpts);
|
|
136
136
|
}
|
|
137
137
|
/**
|
|
138
138
|
* Encapsulates executor + retries for GitHub API calls.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pRetry, { AbortError } from "p-retry";
|
|
2
|
-
import { sanitizeCredentials } from "
|
|
2
|
+
import { sanitizeCredentials } from "../vcs/sanitize-utils.js";
|
|
3
3
|
import { ValidationError } from "./errors.js";
|
|
4
4
|
/**
|
|
5
5
|
* Core permanent error patterns shared across all strategies (API, GraphQL, CLI).
|
|
@@ -3,11 +3,31 @@
|
|
|
3
3
|
* Supports ${xfg:variable} syntax for repo-specific content.
|
|
4
4
|
* Use $${xfg:variable} to escape and output literal ${xfg:variable}.
|
|
5
5
|
*/
|
|
6
|
-
import type { RepoInfo } from "./repo-detector.js";
|
|
7
6
|
type TemplateContent = Record<string, unknown> | string | string[];
|
|
7
|
+
export type RepoDisplayInfo = {
|
|
8
|
+
type: "github";
|
|
9
|
+
gitUrl: string;
|
|
10
|
+
repo: string;
|
|
11
|
+
owner: string;
|
|
12
|
+
host: string;
|
|
13
|
+
} | {
|
|
14
|
+
type: "azure-devops";
|
|
15
|
+
gitUrl: string;
|
|
16
|
+
repo: string;
|
|
17
|
+
owner: string;
|
|
18
|
+
organization: string;
|
|
19
|
+
project: string;
|
|
20
|
+
} | {
|
|
21
|
+
type: "gitlab";
|
|
22
|
+
gitUrl: string;
|
|
23
|
+
repo: string;
|
|
24
|
+
owner: string;
|
|
25
|
+
namespace: string;
|
|
26
|
+
host: string;
|
|
27
|
+
};
|
|
8
28
|
export interface XfgTemplateContext {
|
|
9
29
|
/** Repository information from URL parsing */
|
|
10
|
-
repoInfo:
|
|
30
|
+
repoInfo: RepoDisplayInfo;
|
|
11
31
|
/** Current file being processed */
|
|
12
32
|
fileName: string;
|
|
13
33
|
/** Custom variables defined in config */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type RepoInfo } from "../
|
|
1
|
+
import { type RepoInfo } from "../repo/index.js";
|
|
2
2
|
import type { GitHubAppTokenManager } from "../vcs/index.js";
|
|
3
3
|
import type { AuthResult, IAuthOptionsBuilder } from "./types.js";
|
|
4
4
|
import type { ILogger } from "../shared/logger.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IPRStrategy } from "../vcs/index.js";
|
|
2
|
-
import type { RepoInfo } from "../
|
|
2
|
+
import type { RepoInfo } from "../repo/index.js";
|
|
3
3
|
import type { ICommandExecutor } from "../shared/command-executor.js";
|
|
4
4
|
import type { DebugInfoWarnLog } from "../shared/logger.js";
|
|
5
5
|
import type { IBranchManager, BranchSetupOptions } from "./types.js";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ICommitStrategy } from "../vcs/index.js";
|
|
2
|
-
import type { RepoInfo } from "../
|
|
2
|
+
import type { RepoInfo } from "../repo/index.js";
|
|
3
3
|
import type { ICommandExecutor } from "../shared/command-executor.js";
|
|
4
4
|
import type { CommitPushOptions, CommitPushResult, ICommitPushManager } from "./types.js";
|
|
5
5
|
import type { DebugInfoLog } from "../shared/logger.js";
|
|
@@ -9,6 +9,6 @@ export declare class CommitPushManager implements ICommitPushManager {
|
|
|
9
9
|
private readonly commitStrategyFactory;
|
|
10
10
|
constructor(log: DebugInfoLog, commitStrategyFactory?: CommitStrategyFactory);
|
|
11
11
|
commitAndPush(options: CommitPushOptions): Promise<CommitPushResult>;
|
|
12
|
-
private
|
|
12
|
+
private classifyCommitError;
|
|
13
13
|
}
|
|
14
14
|
export {};
|