Skip to content

Commit d814d84

Browse files
authored
Fix Github Enterprise base url (#300)
* feat(ghes): add ghe-base-url input and honor baseUrl for Octokit when uploading SARIF * Revert "feat(ghes): add ghe-base-url input and honor baseUrl for Octokit when uploading SARIF" This reverts commit e62277a. * feat(ghes): add ghe-base-url input and honor baseUrl for SARIF uploads --------- Co-authored-by: p4r53c <[email protected]>
1 parent 751c204 commit d814d84

File tree

4 files changed

+96
-20
lines changed

4 files changed

+96
-20
lines changed

lib/job-summary.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3838
exports.JobSummary = void 0;
3939
const core = __importStar(require("@actions/core"));
4040
const semver_1 = require("semver");
41-
const core_1 = require("@octokit/core");
4241
const github = __importStar(require("@actions/github"));
4342
const util_1 = require("util");
4443
const zlib_1 = require("zlib");
@@ -107,24 +106,30 @@ class JobSummary {
107106
});
108107
}
109108
/**
110-
* Uploads the code scanning SARIF content to the code-scanning GitHub API.
111-
* @param encodedSarif - The final compressed and encoded sarif content.
112-
* @param token - GitHub token to use for the request. Has to have 'security-events: write' permission.
113-
* @private
109+
* Uploads a SARIF (Static Analysis Results Interchange Format) file to GitHub's code scanning API.
110+
* This method handles the communication with GitHub's REST API to populate the code scanning tab with security analysis results.
111+
* Supports both GitHub.com and GitHub Enterprise Server installations.
112+
* @param encodedSarif - The SARIF content that has been compressed using gzip and encoded to base64 format.
113+
* This encoding is required by GitHub's code-scanning/sarifs API endpoint.
114+
* @param token - GitHub authentication token with appropriate permissions to upload SARIF files.
115+
* Must have 'security_events: write' and 'contents: read' permissions.
116+
* @throws Will throw an error if the HTTP response status is not in the 2xx range or if authentication fails.
114117
*/
115118
static uploadCodeScanningSarif(encodedSarif, token) {
116119
return __awaiter(this, void 0, void 0, function* () {
117-
const octokit = new core_1.Octokit({ auth: token });
118-
let response;
119-
response = yield octokit.request('POST /repos/{owner}/{repo}/code-scanning/sarifs', {
120+
var _a, _b, _c;
121+
const inputBaseUrl = core.getInput('ghe-base-url', { required: false }) || core.getInput('ghe_base_url', { required: false }) || '';
122+
const octokit = inputBaseUrl ? github.getOctokit(token, { baseUrl: inputBaseUrl }) : github.getOctokit(token);
123+
const response = yield octokit.request('POST /repos/{owner}/{repo}/code-scanning/sarifs', {
120124
owner: github.context.repo.owner,
121125
repo: github.context.repo.repo,
122126
commit_sha: github.context.sha,
123127
ref: github.context.ref,
124128
sarif: encodedSarif,
125129
});
126130
if (response.status < 200 || response.status >= 300) {
127-
throw new Error(`Failed to upload SARIF file: ` + JSON.stringify(response));
131+
const usedBaseUrl = ((_c = (_b = (_a = octokit.request) === null || _a === void 0 ? void 0 : _a.endpoint) === null || _b === void 0 ? void 0 : _b.DEFAULTS) === null || _c === void 0 ? void 0 : _c.baseUrl) || 'unknown';
132+
throw new Error(`Failed to upload SARIF file (status ${response.status}). baseUrl=${usedBaseUrl}; response=` + JSON.stringify(response));
128133
}
129134
core.info('SARIF file uploaded successfully');
130135
});

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/job-summary.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,23 @@ export class JobSummary {
103103
core.warning(`Failed populating code scanning sarif: ${error}`);
104104
}
105105
}
106-
106+
107107
/**
108-
* Uploads the code scanning SARIF content to the code-scanning GitHub API.
109-
* @param encodedSarif - The final compressed and encoded sarif content.
110-
* @param token - GitHub token to use for the request. Has to have 'security-events: write' permission.
111-
* @private
108+
* Uploads a SARIF (Static Analysis Results Interchange Format) file to GitHub's code scanning API.
109+
* This method handles the communication with GitHub's REST API to populate the code scanning tab with security analysis results.
110+
* Supports both GitHub.com and GitHub Enterprise Server installations.
111+
* @param encodedSarif - The SARIF content that has been compressed using gzip and encoded to base64 format.
112+
* This encoding is required by GitHub's code-scanning/sarifs API endpoint.
113+
* @param token - GitHub authentication token with appropriate permissions to upload SARIF files.
114+
* Must have 'security_events: write' and 'contents: read' permissions.
115+
* @throws Will throw an error if the HTTP response status is not in the 2xx range or if authentication fails.
112116
*/
113117
private static async uploadCodeScanningSarif(encodedSarif: string, token: string) {
114-
const octokit: Octokit = new Octokit({ auth: token });
115-
let response: OctokitResponse<any> | undefined;
116-
response = await octokit.request('POST /repos/{owner}/{repo}/code-scanning/sarifs', {
118+
const inputBaseUrl = core.getInput('ghe-base-url', { required: false }) || core.getInput('ghe_base_url', { required: false }) || '';
119+
120+
const octokit = inputBaseUrl ? github.getOctokit(token, { baseUrl: inputBaseUrl }) : github.getOctokit(token);
121+
122+
const response = await octokit.request('POST /repos/{owner}/{repo}/code-scanning/sarifs', {
117123
owner: github.context.repo.owner,
118124
repo: github.context.repo.repo,
119125
commit_sha: github.context.sha,
@@ -122,7 +128,8 @@ export class JobSummary {
122128
});
123129

124130
if (response.status < 200 || response.status >= 300) {
125-
throw new Error(`Failed to upload SARIF file: ` + JSON.stringify(response));
131+
const usedBaseUrl = (octokit as any).request?.endpoint?.DEFAULTS?.baseUrl || 'unknown';
132+
throw new Error(`Failed to upload SARIF file (status ${response.status}). baseUrl=${usedBaseUrl}; response=` + JSON.stringify(response));
126133
}
127134

128135
core.info('SARIF file uploaded successfully');
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* test/job-summary.sarif.baseurl.spec.ts
3+
* Checking baseUrl selection when loading SARIF on GHES.
4+
*/
5+
6+
import * as core from '@actions/core';
7+
8+
jest.mock('@actions/github', () => {
9+
const actual = jest.requireActual('@actions/github');
10+
return {
11+
...actual,
12+
getOctokit: jest.fn((token: string, opts?: { baseUrl?: string }) => {
13+
const usedBaseUrl = (opts && opts.baseUrl) || process.env.__AUTO_BASE_URL__ || 'https://api.github.com';
14+
15+
const req = jest.fn(async (_route: string, _params: any) => {
16+
(global as any).__USED_BASE_URL__ = usedBaseUrl;
17+
return { status: 201, data: {} };
18+
}) as unknown as any;
19+
20+
req.endpoint = { DEFAULTS: { baseUrl: usedBaseUrl } };
21+
22+
return { request: req } as any;
23+
}),
24+
context: {
25+
repo: { owner: 'o', repo: 'r' },
26+
sha: 'deadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
27+
ref: 'refs/heads/main',
28+
},
29+
};
30+
});
31+
32+
import { JobSummary } from '../src/job-summary';
33+
34+
describe('uploadCodeScanningSarif baseUrl selection (GHES)', () => {
35+
beforeEach(() => {
36+
jest.resetModules();
37+
jest.clearAllMocks();
38+
39+
jest.spyOn(core, 'getInput').mockImplementation((_name: string) => '');
40+
41+
delete process.env.__AUTO_BASE_URL__;
42+
delete (global as any).__USED_BASE_URL__;
43+
});
44+
45+
it('Should use explicit input ghe-base-url if given', async () => {
46+
(core.getInput as jest.Mock).mockImplementation((name: string) => {
47+
if (name === 'ghe-base-url') return 'https://github.enterprise.local/api/v3';
48+
if (name === 'ghe_base_url') return '';
49+
return '';
50+
});
51+
52+
await (JobSummary as any).uploadCodeScanningSarif('eJx4YWJj', 'ghs_token');
53+
54+
expect((global as any).__USED_BASE_URL__).toBe('https://github.enterprise.local/api/v3');
55+
});
56+
57+
it('Should falls back to auto GHES baseUrl via @actions/github if input is not specified', async () => {
58+
process.env.__AUTO_BASE_URL__ = 'https://ghe.corp.local/api/v3';
59+
60+
await (JobSummary as any).uploadCodeScanningSarif('eJx4YWJj', 'ghs_token');
61+
62+
expect((global as any).__USED_BASE_URL__).toBe('https://ghe.corp.local/api/v3');
63+
});
64+
});

0 commit comments

Comments
 (0)