Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion packages/plugins/git/src/helpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2019-Present Datadog, Inc.

import { getRepositoryData } from '@dd/internal-git-plugin/helpers';
import { getRepositoryData, gitRemote } from '@dd/internal-git-plugin/helpers';
import { addFixtureFiles } from '@dd/tests/_jest/helpers/mocks';

jest.mock('@dd/core/helpers/fs', () => {
Expand Down Expand Up @@ -70,4 +70,17 @@ describe('Git Plugin helpers', () => {
expect(files).toStrictEqual(['src/core/plugins/git/helpers.test.ts']);
});
});

describe('gitRemote', () => {
test('Should reject when no remotes are available', async () => {
const mockGitNoRemotes = {
getConfig: (arg: string) => ({ value: 'origin' }),
getRemotes: (arg: boolean) => [],
};

await expect(gitRemote(mockGitNoRemotes as any)).rejects.toThrow(
'No git remotes available',
);
});
});
});
70 changes: 69 additions & 1 deletion packages/plugins/git/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,20 @@

import type { LogLevel, Options, RepositoryData } from '@dd/core/types';
import { uploadSourcemaps } from '@dd/error-tracking-plugin/sourcemaps/index';
import { getRepositoryData } from '@dd/internal-git-plugin/helpers';
import { getRepositoryData, newSimpleGit } from '@dd/internal-git-plugin/helpers';
import {
defaultPluginOptions,
getRepositoryDataMock,
getSourcemapsConfiguration,
} from '@dd/tests/_jest/helpers/mocks';
import { BUNDLERS, runBundlers } from '@dd/tests/_jest/helpers/runBundlers';
import type { SimpleGit } from 'simple-git';

jest.mock('@dd/internal-git-plugin/helpers', () => {
const originalModule = jest.requireActual('@dd/internal-git-plugin/helpers');
return {
...originalModule,
newSimpleGit: jest.fn(),
getRepositoryData: jest.fn(),
};
});
Expand All @@ -30,6 +32,14 @@ jest.mock('@dd/error-tracking-plugin/sourcemaps/index', () => {

const uploadSourcemapsMocked = jest.mocked(uploadSourcemaps);
const getRepositoryDataMocked = jest.mocked(getRepositoryData);
const newSimpleGitMocked = jest.mocked(newSimpleGit);

const oneRemote = [{ refs: { push: 'git@github.com:user/repository.git' } }];

const createMockSimpleGit = (remotes: Array<{ refs: { push: string } }>): SimpleGit => {
const stub = { getRemotes: () => remotes };
return stub as unknown as SimpleGit;
};

const pluginOptions = {
...defaultPluginOptions,
Expand Down Expand Up @@ -70,6 +80,10 @@ describe('Git Plugin', () => {
return Promise.resolve();
});

newSimpleGitMocked.mockImplementation(() =>
Promise.resolve(createMockSimpleGit(oneRemote)),
);

getRepositoryDataMocked.mockImplementation(() => {
nbCallsToGetRepositoryData += 1;
return Promise.resolve(mockGitData);
Expand Down Expand Up @@ -143,4 +157,58 @@ describe('Git Plugin', () => {
expect(getRepositoryDataMocked).not.toHaveBeenCalled();
});
});

describe('No remotes', () => {
const gitReports: Record<string, RepositoryData | undefined> = {};
const gitHookReports: Record<string, RepositoryData | undefined> = {};
let nbCallsToGetRepositoryData = 0;
let nbGitHookCalls = 0;

beforeAll(async () => {
const pluginConfig: Options = {
...pluginOptions,
errorTracking: {
sourcemaps: getSourcemapsConfiguration(),
},
customPlugins: ({ context }) => {
return [
{
name: 'custom-test-hook-plugin',
git(repoData) {
nbGitHookCalls += 1;
gitHookReports[context.bundler.name] = repoData;
},
},
];
},
};

uploadSourcemapsMocked.mockImplementation((options, context, log) => {
gitReports[context.bundlerName] = context.git;
return Promise.resolve();
});

newSimpleGitMocked.mockImplementation(() => Promise.resolve(createMockSimpleGit([])));

getRepositoryDataMocked.mockImplementation(() => {
nbCallsToGetRepositoryData += 1;
return Promise.resolve(getRepositoryDataMock());
});

await runBundlers(pluginConfig);
});

test('Should not call getRepositoryData when there are no remotes.', () => {
expect(nbCallsToGetRepositoryData).toBe(0);
});

test('Should not fire the git hook.', () => {
expect(nbGitHookCalls).toBe(0);
});

test.each(BUNDLERS)('[$name|$version] Should leave context.git undefined.', ({ name }) => {
expect(gitReports[name]).toBeUndefined();
expect(gitHookReports[name]).toBeUndefined();
});
});
});
15 changes: 12 additions & 3 deletions packages/plugins/git/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,18 @@ export const getGitPlugins: GetInternalPlugins = (arg: GetPluginsArg) => {
const timeGit = log.time('get git information', { start: false });
const processGit = async (gitDir: string) => {
try {
const repositoryData = await getRepositoryData(
await newSimpleGit(path.dirname(gitDir!)),
);
const git = await newSimpleGit(path.dirname(gitDir));
const remotes = await git.getRemotes(true);
if (remotes.length === 0) {
log.warn(
'No git remotes available, skipping git plugin. ' +
'This is expected for a repository that has not been pushed yet.',
);
timeGit.end();
return;
}

const repositoryData = await getRepositoryData(git);
context.git = repositoryData;

timeGit.end();
Expand Down
Loading