From 16a46044974cbb045f3eeab934633babe2e08759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Antonio=20Fern=C3=A1ndez=20de=20Alba?= Date: Fri, 9 Aug 2024 14:16:07 +0200 Subject: [PATCH] [test visibility] Add check to determine whether git is available (#4588) --- .../exporters/git/git_metadata.js | 6 ++++- packages/dd-trace/src/plugins/util/git.js | 15 +++++++++++- .../exporters/git/git_metadata.spec.js | 9 ++++--- .../dd-trace/test/plugins/util/git.spec.js | 24 ++++++++++++++++++- 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js b/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js index b1a78c92313..1585a94166f 100644 --- a/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +++ b/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js @@ -11,7 +11,8 @@ const { generatePackFilesForCommits, getCommitsRevList, isShallowRepository, - unshallowRepository + unshallowRepository, + isGitAvailable } = require('../../../plugins/util/git') const { @@ -242,6 +243,9 @@ function generateAndUploadPackFiles ({ * This function uploads git metadata to CI Visibility's backend. */ function sendGitMetadata (url, { isEvpProxy, evpProxyPrefix }, configRepositoryUrl, callback) { + if (!isGitAvailable()) { + return callback(new Error('Git is not available')) + } let repositoryUrl = configRepositoryUrl if (!repositoryUrl) { repositoryUrl = getRepositoryUrl() diff --git a/packages/dd-trace/src/plugins/util/git.js b/packages/dd-trace/src/plugins/util/git.js index 3e2a3ef9726..06b9521817f 100644 --- a/packages/dd-trace/src/plugins/util/git.js +++ b/packages/dd-trace/src/plugins/util/git.js @@ -77,6 +77,18 @@ function isDirectory (path) { } } +function isGitAvailable () { + const isWindows = os.platform() === 'win32' + const command = isWindows ? 'where' : 'which' + try { + cp.execFileSync(command, ['git'], { stdio: 'pipe' }) + return true + } catch (e) { + incrementCountMetric(TELEMETRY_GIT_COMMAND_ERRORS, { command: 'check_git', exitCode: 'missing' }) + return false + } +} + function isShallowRepository () { return sanitizedExec( 'git', @@ -342,5 +354,6 @@ module.exports = { getCommitsRevList, GIT_REV_LIST_MAX_BUFFER, isShallowRepository, - unshallowRepository + unshallowRepository, + isGitAvailable } diff --git a/packages/dd-trace/test/ci-visibility/exporters/git/git_metadata.spec.js b/packages/dd-trace/test/ci-visibility/exporters/git/git_metadata.spec.js index 497fc51372e..b4d0acb747d 100644 --- a/packages/dd-trace/test/ci-visibility/exporters/git/git_metadata.spec.js +++ b/packages/dd-trace/test/ci-visibility/exporters/git/git_metadata.spec.js @@ -325,17 +325,20 @@ describe('git_metadata', () => { }) it('should not crash if git is missing', (done) => { + const oldPath = process.env.PATH + // git will not be found + process.env.PATH = '' + const scope = nock('https://api.test.com') .post('/api/v2/git/repository/search_commits') .reply(200, JSON.stringify({ data: [] })) .post('/api/v2/git/repository/packfile') .reply(204) - getRepositoryUrlStub.returns('') - gitMetadata.sendGitMetadata(new URL('https://api.test.com'), { isEvpProxy: false }, '', (err) => { - expect(err.message).to.contain('Repository URL is empty') + expect(err.message).to.contain('Git is not available') expect(scope.isDone()).to.be.false + process.env.PATH = oldPath done() }) }) diff --git a/packages/dd-trace/test/plugins/util/git.spec.js b/packages/dd-trace/test/plugins/util/git.spec.js index f74a8530515..9c971701f89 100644 --- a/packages/dd-trace/test/plugins/util/git.spec.js +++ b/packages/dd-trace/test/plugins/util/git.spec.js @@ -7,7 +7,7 @@ const os = require('os') const fs = require('fs') const path = require('path') -const { GIT_REV_LIST_MAX_BUFFER } = require('../../../src/plugins/util/git') +const { GIT_REV_LIST_MAX_BUFFER, isGitAvailable } = require('../../../src/plugins/util/git') const proxyquire = require('proxyquire') const execFileSyncStub = sinon.stub().returns('') @@ -378,3 +378,25 @@ describe('user credentials', () => { .to.equal('ssh://host.xz:port/path/to/repo.git/') }) }) + +describe('isGitAvailable', () => { + let originalPath + + beforeEach(() => { + originalPath = process.env.PATH + }) + + afterEach(() => { + process.env.PATH = originalPath + }) + + it('returns true if git is available', () => { + expect(isGitAvailable()).to.be.true + }) + + it('returns false if git is not available', () => { + process.env.PATH = '' + + expect(isGitAvailable()).to.be.false + }) +})