Skip to content

Commit 0fc92f1

Browse files
osho-20claude
andcommitted
fix(ci-info): detect GitHub Actions before presence-only CI providers [SDK-7081]
getCiInfo() checked Jenkins first on mere presence of JENKINS_URL/ JENKINS_HOME, so a self-hosted GitHub Actions runner with leftover Jenkins env vars was classified as Jenkins with build_url undefined. obs-api force-disables the TRA Re-run control for builds without a CI build_url, greying the button. Move the explicit GITHUB_ACTIONS check ahead of the presence-only providers. Also return after resolve({}) in getGitMetaData when no git directory is found, instead of falling through. Adds getCiInfo unit coverage: GHA detection, the Jenkins-shadowing regression, pure Jenkins, and no-CI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent b889f91 commit 0fc92f1

2 files changed

Lines changed: 70 additions & 10 deletions

File tree

bin/helpers/helper.js

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ exports.getGitMetaData = () => {
102102
if(!info.commonGitDir) {
103103
logger.debug(`Unable to find a Git directory`);
104104
exports.debug(`Unable to find a Git directory`);
105-
resolve({});
105+
return resolve({});
106106
}
107107
if(!info.author && exports.findGitConfig(process.cwd())) {
108108
/* commit objects are packed */
@@ -196,6 +196,16 @@ exports.getHostInfo = () => {
196196
exports.getCiInfo = () => {
197197
var env = process.env;
198198

199+
// GitHub Actions — checked before the presence-only providers (Jenkins,
200+
// Bitbucket) so leftover env vars on self-hosted runners can't shadow it
201+
if (env.GITHUB_ACTIONS === "true" || (env.CI === "true" && env.GITHUB_RUN_ID)) {
202+
return {
203+
name: "GitHub Actions",
204+
build_url: `${env.GITHUB_SERVER_URL || 'https://github.com'}/${env.GITHUB_REPOSITORY}/actions/runs/${env.GITHUB_RUN_ID}`,
205+
job_name: env.GITHUB_WORKFLOW || env.GITHUB_JOB,
206+
build_number: env.GITHUB_RUN_ID
207+
};
208+
}
199209
// Jenkins
200210
if ((typeof env.JENKINS_URL === "string" && env.JENKINS_URL.length > 0) || (typeof env.JENKINS_HOME === "string" && env.JENKINS_HOME.length > 0)) {
201211
return {
@@ -268,15 +278,6 @@ exports.getCiInfo = () => {
268278
build_number: env.CI_JOB_ID
269279
};
270280
}
271-
// GitHub Actions
272-
if (env.GITHUB_ACTIONS === "true" || env.CI === "true" && env.GITHUB_RUN_ID) {
273-
return {
274-
name: "GitHub Actions",
275-
build_url: `${env.GITHUB_SERVER_URL || 'https://github.com'}/${env.GITHUB_REPOSITORY}/actions/runs/${env.GITHUB_RUN_ID}`,
276-
job_name: env.GITHUB_WORKFLOW || env.GITHUB_JOB,
277-
build_number: env.GITHUB_RUN_ID
278-
};
279-
}
280281
// Buildkite
281282
if (env.CI === "true" && env.BUILDKITE === "true") {
282283
return {

test/unit/bin/helpers/helper.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,63 @@ describe('helper', () => {
3838
expect(helper.getSizeOfJsonObjectInBytes(truncatedVCSInfo)).to.be.lessThanOrEqual(64 * 1024);
3939
});
4040
});
41+
42+
describe('getCiInfo', () => {
43+
const CI_VARS = ['CI', 'GITHUB_ACTIONS', 'GITHUB_SERVER_URL', 'GITHUB_REPOSITORY', 'GITHUB_RUN_ID', 'GITHUB_RUN_NUMBER', 'GITHUB_WORKFLOW', 'GITHUB_JOB', 'JENKINS_URL', 'JENKINS_HOME', 'BUILD_URL', 'JOB_NAME', 'BUILD_NUMBER'];
44+
let savedEnv = {};
45+
46+
beforeEach(() => {
47+
CI_VARS.forEach((k) => {
48+
savedEnv[k] = process.env[k];
49+
delete process.env[k];
50+
});
51+
});
52+
53+
afterEach(() => {
54+
CI_VARS.forEach((k) => {
55+
if (savedEnv[k] === undefined) delete process.env[k];
56+
else process.env[k] = savedEnv[k];
57+
});
58+
savedEnv = {};
59+
});
60+
61+
const setGithubActionsEnv = () => {
62+
process.env.CI = 'true';
63+
process.env.GITHUB_ACTIONS = 'true';
64+
process.env.GITHUB_SERVER_URL = 'https://github.com';
65+
process.env.GITHUB_REPOSITORY = 'org/repo';
66+
process.env.GITHUB_RUN_ID = '27412345678';
67+
process.env.GITHUB_WORKFLOW = 'CI Workflow';
68+
};
69+
70+
it('detects GitHub Actions with build_url and run-id build_number', () => {
71+
setGithubActionsEnv();
72+
const ciInfo = helper.getCiInfo();
73+
expect(ciInfo.name).to.eq('GitHub Actions');
74+
expect(ciInfo.build_url).to.eq('https://github.com/org/repo/actions/runs/27412345678');
75+
expect(ciInfo.build_number).to.eq('27412345678');
76+
});
77+
78+
it('prefers GitHub Actions over leaked Jenkins env vars on self-hosted runners', () => {
79+
setGithubActionsEnv();
80+
process.env.JENKINS_HOME = '/var/lib/jenkins';
81+
const ciInfo = helper.getCiInfo();
82+
expect(ciInfo.name).to.eq('GitHub Actions');
83+
expect(ciInfo.build_url).to.eq('https://github.com/org/repo/actions/runs/27412345678');
84+
});
85+
86+
it('detects Jenkins when no explicit CI marker is set', () => {
87+
process.env.JENKINS_URL = 'https://ci.internal/job/x';
88+
process.env.BUILD_URL = 'https://ci.internal/job/x/42/';
89+
process.env.JOB_NAME = 'x';
90+
process.env.BUILD_NUMBER = '42';
91+
const ciInfo = helper.getCiInfo();
92+
expect(ciInfo.name).to.eq('Jenkins');
93+
expect(ciInfo.build_url).to.eq('https://ci.internal/job/x/42/');
94+
});
95+
96+
it('returns null when no CI is detected', () => {
97+
expect(helper.getCiInfo()).to.be.null;
98+
});
99+
});
41100
});

0 commit comments

Comments
 (0)