@aspruyt/xfg 3.7.2 → 3.7.3

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.
@@ -22,11 +22,11 @@ const PROPERTY_MAPPING = {
22
22
  mergeCommitMessage: "merge_commit_message",
23
23
  webCommitSignoffRequired: "web_commit_signoff_required",
24
24
  defaultBranch: "default_branch",
25
- vulnerabilityAlerts: "_vulnerability_alerts",
26
- automatedSecurityFixes: "_automated_security_fixes",
25
+ vulnerabilityAlerts: "vulnerability_alerts",
26
+ automatedSecurityFixes: "automated_security_fixes",
27
27
  secretScanning: "_secret_scanning",
28
28
  secretScanningPushProtection: "_secret_scanning_push_protection",
29
- privateVulnerabilityReporting: "_private_vulnerability_reporting",
29
+ privateVulnerabilityReporting: "private_vulnerability_reporting",
30
30
  };
31
31
  /**
32
32
  * Gets the current value for a property from GitHub API response.
@@ -91,16 +91,22 @@ export class RepoSettingsProcessor {
91
91
  }
92
92
  async applyChanges(repoInfo, settings, options) {
93
93
  // Extract settings that need separate API calls
94
- const { vulnerabilityAlerts, automatedSecurityFixes, ...mainSettings } = settings;
94
+ const { vulnerabilityAlerts, automatedSecurityFixes, privateVulnerabilityReporting, ...mainSettings } = settings;
95
95
  // Update main settings via PATCH /repos
96
96
  if (Object.keys(mainSettings).length > 0) {
97
97
  await this.strategy.updateSettings(repoInfo, mainSettings, options);
98
98
  }
99
99
  // Handle vulnerability alerts (separate endpoint)
100
+ // Must be done before automated security fixes
100
101
  if (vulnerabilityAlerts !== undefined) {
101
102
  await this.strategy.setVulnerabilityAlerts(repoInfo, vulnerabilityAlerts, options);
102
103
  }
104
+ // Handle private vulnerability reporting (separate endpoint)
105
+ if (privateVulnerabilityReporting !== undefined) {
106
+ await this.strategy.setPrivateVulnerabilityReporting(repoInfo, privateVulnerabilityReporting, options);
107
+ }
103
108
  // Handle automated security fixes (separate endpoint)
109
+ // Done last to ensure vulnerability alerts have been fully processed
104
110
  if (automatedSecurityFixes !== undefined) {
105
111
  await this.strategy.setAutomatedSecurityFixes(repoInfo, automatedSecurityFixes, options);
106
112
  }
@@ -15,6 +15,10 @@ export declare class GitHubRepoSettingsStrategy implements IRepoSettingsStrategy
15
15
  updateSettings(repoInfo: RepoInfo, settings: GitHubRepoSettings, options?: RepoSettingsStrategyOptions): Promise<void>;
16
16
  setVulnerabilityAlerts(repoInfo: RepoInfo, enable: boolean, options?: RepoSettingsStrategyOptions): Promise<void>;
17
17
  setAutomatedSecurityFixes(repoInfo: RepoInfo, enable: boolean, options?: RepoSettingsStrategyOptions): Promise<void>;
18
+ setPrivateVulnerabilityReporting(repoInfo: RepoInfo, enable: boolean, options?: RepoSettingsStrategyOptions): Promise<void>;
19
+ private getVulnerabilityAlerts;
20
+ private getAutomatedSecurityFixes;
21
+ private getPrivateVulnerabilityReporting;
18
22
  private validateGitHub;
19
23
  private ghApi;
20
24
  }
@@ -76,7 +76,14 @@ export class GitHubRepoSettingsStrategy {
76
76
  const github = repoInfo;
77
77
  const endpoint = `/repos/${github.owner}/${github.repo}`;
78
78
  const result = await this.ghApi("GET", endpoint, undefined, options);
79
- return JSON.parse(result);
79
+ const settings = JSON.parse(result);
80
+ // Fetch security settings from separate endpoints
81
+ settings.vulnerability_alerts = await this.getVulnerabilityAlerts(github, options);
82
+ // Pass vulnerability_alerts state - automated security fixes requires it enabled
83
+ settings.automated_security_fixes = await this.getAutomatedSecurityFixes(github, options, settings.vulnerability_alerts);
84
+ settings.private_vulnerability_reporting =
85
+ await this.getPrivateVulnerabilityReporting(github, options);
86
+ return settings;
80
87
  }
81
88
  async updateSettings(repoInfo, settings, options) {
82
89
  this.validateGitHub(repoInfo);
@@ -103,6 +110,54 @@ export class GitHubRepoSettingsStrategy {
103
110
  const method = enable ? "PUT" : "DELETE";
104
111
  await this.ghApi(method, endpoint, undefined, options);
105
112
  }
113
+ async setPrivateVulnerabilityReporting(repoInfo, enable, options) {
114
+ this.validateGitHub(repoInfo);
115
+ const github = repoInfo;
116
+ const endpoint = `/repos/${github.owner}/${github.repo}/private-vulnerability-reporting`;
117
+ const method = enable ? "PUT" : "DELETE";
118
+ await this.ghApi(method, endpoint, undefined, options);
119
+ }
120
+ async getVulnerabilityAlerts(github, options) {
121
+ const endpoint = `/repos/${github.owner}/${github.repo}/vulnerability-alerts`;
122
+ try {
123
+ await this.ghApi("GET", endpoint, undefined, options);
124
+ return true; // 204 = enabled
125
+ }
126
+ catch (error) {
127
+ const message = error instanceof Error ? error.message : String(error);
128
+ if (message.includes("HTTP 404")) {
129
+ return false; // 404 = disabled
130
+ }
131
+ throw error; // Re-throw other errors
132
+ }
133
+ }
134
+ async getAutomatedSecurityFixes(github, options, _vulnerabilityAlertsEnabled) {
135
+ // Note: GitHub returns JSON with {enabled: boolean} for this endpoint
136
+ const endpoint = `/repos/${github.owner}/${github.repo}/automated-security-fixes`;
137
+ try {
138
+ const result = await this.ghApi("GET", endpoint, undefined, options);
139
+ // Parse JSON response - GitHub returns {"enabled": true/false}
140
+ if (result) {
141
+ const data = JSON.parse(result);
142
+ return data.enabled === true;
143
+ }
144
+ // Empty response (204) means enabled
145
+ return true;
146
+ }
147
+ catch (error) {
148
+ const message = error instanceof Error ? error.message : String(error);
149
+ if (message.includes("HTTP 404")) {
150
+ return false;
151
+ }
152
+ throw error;
153
+ }
154
+ }
155
+ async getPrivateVulnerabilityReporting(github, options) {
156
+ const endpoint = `/repos/${github.owner}/${github.repo}/private-vulnerability-reporting`;
157
+ const result = await this.ghApi("GET", endpoint, undefined, options);
158
+ const data = JSON.parse(result);
159
+ return data.enabled === true;
160
+ }
106
161
  validateGitHub(repoInfo) {
107
162
  if (!isGitHubRepo(repoInfo)) {
108
163
  throw new Error(`GitHub Repo Settings strategy requires GitHub repositories. Got: ${repoInfo.type}`);
@@ -39,6 +39,9 @@ export interface CurrentRepoSettings {
39
39
  status: string;
40
40
  };
41
41
  };
42
+ vulnerability_alerts?: boolean;
43
+ automated_security_fixes?: boolean;
44
+ private_vulnerability_reporting?: boolean;
42
45
  }
43
46
  export interface IRepoSettingsStrategy {
44
47
  /**
@@ -57,6 +60,10 @@ export interface IRepoSettingsStrategy {
57
60
  * Enables or disables automated security fixes.
58
61
  */
59
62
  setAutomatedSecurityFixes(repoInfo: RepoInfo, enable: boolean, options?: RepoSettingsStrategyOptions): Promise<void>;
63
+ /**
64
+ * Enables or disables private vulnerability reporting.
65
+ */
66
+ setPrivateVulnerabilityReporting(repoInfo: RepoInfo, enable: boolean, options?: RepoSettingsStrategyOptions): Promise<void>;
60
67
  }
61
68
  /**
62
69
  * Type guard to check if an object implements IRepoSettingsStrategy.
@@ -9,5 +9,6 @@ export function isRepoSettingsStrategy(obj) {
9
9
  return (typeof strategy.getSettings === "function" &&
10
10
  typeof strategy.updateSettings === "function" &&
11
11
  typeof strategy.setVulnerabilityAlerts === "function" &&
12
- typeof strategy.setAutomatedSecurityFixes === "function");
12
+ typeof strategy.setAutomatedSecurityFixes === "function" &&
13
+ typeof strategy.setPrivateVulnerabilityReporting === "function");
13
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aspruyt/xfg",
3
- "version": "3.7.2",
3
+ "version": "3.7.3",
4
4
  "description": "CLI tool for repository-as-code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",