@aspruyt/xfg 3.9.6 → 3.9.9
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/settings-command.js +2 -0
- package/dist/settings/repo-settings/github-repo-settings-strategy.js +16 -4
- package/dist/settings/repo-settings/processor.d.ts +5 -0
- package/dist/settings/repo-settings/processor.js +38 -0
- package/dist/settings/repo-settings/types.d.ts +1 -0
- package/package.json +1 -1
|
@@ -167,6 +167,7 @@ async function processRulesets(repos, config, options, processor, repoProcessor,
|
|
|
167
167
|
}
|
|
168
168
|
else {
|
|
169
169
|
logger.error(i + 1, repoName, result.message);
|
|
170
|
+
collector.appendError(repoName, result.message);
|
|
170
171
|
}
|
|
171
172
|
results.push({
|
|
172
173
|
repoName,
|
|
@@ -240,6 +241,7 @@ async function processRepoSettings(repos, config, options, processorFactory, res
|
|
|
240
241
|
}
|
|
241
242
|
else {
|
|
242
243
|
logger.error(current, repoName, result.message);
|
|
244
|
+
collector.appendError(repoName, result.message);
|
|
243
245
|
}
|
|
244
246
|
if (!result.skipped) {
|
|
245
247
|
const existing = results.find((r) => r.repoName === repoName);
|
|
@@ -78,7 +78,10 @@ export class GitHubRepoSettingsStrategy {
|
|
|
78
78
|
const github = repoInfo;
|
|
79
79
|
const endpoint = `/repos/${github.owner}/${github.repo}`;
|
|
80
80
|
const result = await this.ghApi("GET", endpoint, undefined, options);
|
|
81
|
-
const
|
|
81
|
+
const parsed = JSON.parse(result);
|
|
82
|
+
const settings = parsed;
|
|
83
|
+
// Extract owner type from nested API response
|
|
84
|
+
settings.owner_type = parsed.owner?.type;
|
|
82
85
|
// Fetch security settings from separate endpoints
|
|
83
86
|
settings.vulnerability_alerts = await this.getVulnerabilityAlerts(github, options);
|
|
84
87
|
// Pass vulnerability_alerts state - automated security fixes requires it enabled
|
|
@@ -156,9 +159,18 @@ export class GitHubRepoSettingsStrategy {
|
|
|
156
159
|
}
|
|
157
160
|
async getPrivateVulnerabilityReporting(github, options) {
|
|
158
161
|
const endpoint = `/repos/${github.owner}/${github.repo}/private-vulnerability-reporting`;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
try {
|
|
163
|
+
const result = await this.ghApi("GET", endpoint, undefined, options);
|
|
164
|
+
const data = JSON.parse(result);
|
|
165
|
+
return data.enabled === true;
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
169
|
+
if (message.includes("HTTP 404")) {
|
|
170
|
+
return false; // 404 = not available (e.g. private repos)
|
|
171
|
+
}
|
|
172
|
+
throw error; // Re-throw other errors
|
|
173
|
+
}
|
|
162
174
|
}
|
|
163
175
|
validateGitHub(repoInfo) {
|
|
164
176
|
if (!isGitHubRepo(repoInfo)) {
|
|
@@ -28,6 +28,11 @@ export declare class RepoSettingsProcessor implements IRepoSettingsProcessor {
|
|
|
28
28
|
constructor(strategy?: IRepoSettingsStrategy);
|
|
29
29
|
process(repoConfig: RepoConfig, repoInfo: RepoInfo, options: RepoSettingsProcessorOptions): Promise<RepoSettingsProcessorResult>;
|
|
30
30
|
private applyChanges;
|
|
31
|
+
/**
|
|
32
|
+
* Validates that desired security settings are compatible with the repo's
|
|
33
|
+
* visibility and owner type. Returns error messages for incompatible settings.
|
|
34
|
+
*/
|
|
35
|
+
private validateSecuritySettings;
|
|
31
36
|
/**
|
|
32
37
|
* Resolves a GitHub App installation token for the given repo.
|
|
33
38
|
* Returns undefined if no token manager or token resolution fails.
|
|
@@ -45,6 +45,15 @@ export class RepoSettingsProcessor {
|
|
|
45
45
|
const strategyOptions = { token: effectiveToken, host: githubRepo.host };
|
|
46
46
|
// Fetch current settings
|
|
47
47
|
const currentSettings = await this.strategy.getSettings(githubRepo, strategyOptions);
|
|
48
|
+
// Validate security settings compatibility
|
|
49
|
+
const securityErrors = this.validateSecuritySettings(desiredSettings, currentSettings);
|
|
50
|
+
if (securityErrors.length > 0) {
|
|
51
|
+
return {
|
|
52
|
+
success: false,
|
|
53
|
+
repoName,
|
|
54
|
+
message: `Failed: ${securityErrors.join("; ")}`,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
48
57
|
// Compute diff
|
|
49
58
|
const changes = diffRepoSettings(currentSettings, desiredSettings);
|
|
50
59
|
if (!hasChanges(changes)) {
|
|
@@ -117,6 +126,35 @@ export class RepoSettingsProcessor {
|
|
|
117
126
|
await this.strategy.setAutomatedSecurityFixes(repoInfo, automatedSecurityFixes, options);
|
|
118
127
|
}
|
|
119
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Validates that desired security settings are compatible with the repo's
|
|
131
|
+
* visibility and owner type. Returns error messages for incompatible settings.
|
|
132
|
+
*/
|
|
133
|
+
validateSecuritySettings(desiredSettings, currentSettings) {
|
|
134
|
+
const errors = [];
|
|
135
|
+
const isPublic = currentSettings.visibility === "public";
|
|
136
|
+
// privateVulnerabilityReporting is only available on public repos
|
|
137
|
+
if (desiredSettings.privateVulnerabilityReporting === true && !isPublic) {
|
|
138
|
+
errors.push("privateVulnerabilityReporting is only available for public repositories");
|
|
139
|
+
}
|
|
140
|
+
// secretScanning and secretScanningPushProtection:
|
|
141
|
+
// - Available on public repos (free)
|
|
142
|
+
// - Available on org private/internal repos with GHAS (security_and_analysis is populated)
|
|
143
|
+
// - NOT available on user private repos or org private/internal repos without GHAS
|
|
144
|
+
if (!isPublic) {
|
|
145
|
+
const isUserOwned = currentSettings.owner_type === "User";
|
|
146
|
+
const hasGHAS = currentSettings.security_and_analysis != null;
|
|
147
|
+
if (desiredSettings.secretScanning === true &&
|
|
148
|
+
(isUserOwned || !hasGHAS)) {
|
|
149
|
+
errors.push("secretScanning requires GitHub Advanced Security (not available for this repository)");
|
|
150
|
+
}
|
|
151
|
+
if (desiredSettings.secretScanningPushProtection === true &&
|
|
152
|
+
(isUserOwned || !hasGHAS)) {
|
|
153
|
+
errors.push("secretScanningPushProtection requires GitHub Advanced Security (not available for this repository)");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return errors;
|
|
157
|
+
}
|
|
120
158
|
/**
|
|
121
159
|
* Resolves a GitHub App installation token for the given repo.
|
|
122
160
|
* Returns undefined if no token manager or token resolution fails.
|
package/package.json
CHANGED