Skip to content

Commit

Permalink
feat(cli): include commit info in report.json
Browse files Browse the repository at this point in the history
  • Loading branch information
matejchalk committed Mar 6, 2024
1 parent 66949c2 commit 5965900
Show file tree
Hide file tree
Showing 25 changed files with 235 additions and 173 deletions.
7 changes: 3 additions & 4 deletions e2e/cli-e2e/tests/collect.e2e.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ describe('CLI collect', () => {
duration,
version,
...report
}: Report | PluginReport) => report;
/* eslint-enable @typescript-eslint/no-unused-vars */

const omitVariableReportData = (report: Report) =>
}: Omit<Report, 'commit'> | PluginReport) => report;
const omitVariableReportData = ({ commit, ...report }: Report) =>
omitVariableData({
...report,
plugins: report.plugins.map(omitVariableData) as PluginReport[],
});
/* eslint-enable @typescript-eslint/no-unused-vars */

beforeEach(async () => {
await cleanTestFolder('tmp/e2e');
Expand Down
6 changes: 1 addition & 5 deletions packages/cli/src/lib/autorun/autorun-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
collectAndPersistReports,
upload,
} from '@code-pushup/core';
import { getLatestCommit, validateCommitData } from '@code-pushup/utils';
import { CLI_NAME } from '../constants';
import {
collectSuccessfulLog,
Expand Down Expand Up @@ -50,10 +49,7 @@ export function yargsAutorunCommandObject() {

if (options.upload) {
const { url } = await upload(options);
const commitData = await getLatestCommit();
if (validateCommitData(commitData, { throwError: true })) {
uploadSuccessfulLog(url);
}
uploadSuccessfulLog(url);
} else {
ui().logger.warning('Upload skipped because configuration is not set.');
renderIntegratePortalHint();
Expand Down
7 changes: 1 addition & 6 deletions packages/cli/src/lib/upload/upload-command.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import chalk from 'chalk';
import { ArgumentsCamelCase, CommandModule } from 'yargs';
import { UploadOptions, upload } from '@code-pushup/core';
import { getLatestCommit, validateCommitData } from '@code-pushup/utils';
import { CLI_NAME } from '../constants';
import {
renderIntegratePortalHint,
Expand All @@ -24,11 +23,7 @@ export function yargsUploadCommandObject() {
throw new Error('Upload configuration not set');
}
const { url } = await upload(options);

const commitData = await getLatestCommit();
if (validateCommitData(commitData, { throwError: true })) {
uploadSuccessfulLog(url);
}
uploadSuccessfulLog(url);
},
} satisfies CommandModule;
}
16 changes: 12 additions & 4 deletions packages/core/src/lib/collect-and-persist.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import {
MINIMAL_CONFIG_MOCK,
MINIMAL_REPORT_MOCK,
} from '@code-pushup/test-utils';
import { collectAndPersistReports } from './collect-and-persist';
import {
CollectAndPersistReportsOptions,
collectAndPersistReports,
} from './collect-and-persist';
import { collect } from './implementation/collect';
import { logPersistedResults, persistReport } from './implementation/persist';

Expand All @@ -19,7 +22,8 @@ vi.mock('./implementation/persist', () => ({

describe('collectAndPersistReports', () => {
it('should call collect and persistReport with correct parameters in non-verbose mode', async () => {
const nonVerboseConfig = {
const nonVerboseConfig: CollectAndPersistReportsOptions = {
categories: [],
...MINIMAL_CONFIG_MOCK,
persist: {
outputDir: 'output',
Expand All @@ -33,12 +37,15 @@ describe('collectAndPersistReports', () => {

expect(collect).toHaveBeenCalledWith(nonVerboseConfig);

expect(persistReport).toHaveBeenCalledWith(
expect(persistReport).toHaveBeenCalledWith<
Parameters<typeof persistReport>
>(
{
packageName: '@code-pushup/core',
version: '0.0.1',
date: expect.stringMatching(ISO_STRING_REGEXP),
duration: 666,
commit: expect.any(Object),
categories: expect.any(Array),
plugins: expect.any(Array),
},
Expand All @@ -53,7 +60,8 @@ describe('collectAndPersistReports', () => {
});

it('should call collect and persistReport with correct parameters in verbose mode', async () => {
const verboseConfig = {
const verboseConfig: CollectAndPersistReportsOptions = {
categories: [],
...MINIMAL_CONFIG_MOCK,
persist: {
outputDir: 'output',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { vol } from 'memfs';
import { describe, expect, it } from 'vitest';
import { commitSchema } from '@code-pushup/models';
import { MEMFS_VOLUME, MINIMAL_CONFIG_MOCK } from '@code-pushup/test-utils';
import { collect } from './collect';

describe('collect', () => {
it('should execute with valid options', async () => {
vol.fromJSON({}, MEMFS_VOLUME);
const report = await collect({
categories: [],
...MINIMAL_CONFIG_MOCK,
verbose: true,
progress: false,
Expand All @@ -27,5 +29,7 @@ describe('collect', () => {
},
}),
);

expect(() => commitSchema.parse(report.commit)).not.toThrow();
});
});
4 changes: 3 additions & 1 deletion packages/core/src/lib/implementation/collect.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CoreConfig, Report } from '@code-pushup/models';
import { calcDuration } from '@code-pushup/utils';
import { calcDuration, getLatestCommit } from '@code-pushup/utils';
import { name, version } from '../../../package.json';
import { GlobalOptions } from '../types';
import { executePlugins } from './execute-plugin';
Expand All @@ -17,8 +17,10 @@ export async function collect(options: CollectOptions): Promise<Report> {
const { plugins, categories } = options;
const date = new Date().toISOString();
const start = performance.now();
const commit = await getLatestCommit();
const pluginOutputs = await executePlugins(plugins, options);
return {
commit,
packageName: name,
version,
date,
Expand Down
34 changes: 14 additions & 20 deletions packages/core/src/lib/implementation/persist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import {
directoryExists,
generateMdReport,
generateStdoutSummary,
getLatestCommit,
logMultipleFileResults,
scoreReport,
sortReport,
validateCommitData,
} from '@code-pushup/utils';

export class PersistDirError extends Error {
Expand All @@ -35,24 +33,20 @@ export async function persistReport(
console.info(generateStdoutSummary(sortedScoredReport));

// collect physical format outputs
const results = await Promise.all(
format.map(async reportType => {
switch (reportType) {
case 'json':
return {
format: 'json',
content: JSON.stringify(report, null, 2),
};
case 'md':
const commitData = await getLatestCommit();
validateCommitData(commitData);
return {
format: 'md',
content: generateMdReport(sortedScoredReport, commitData),
};
}
}),
);
const results = format.map(reportType => {
switch (reportType) {
case 'json':
return {
format: 'json',
content: JSON.stringify(report, null, 2),
};
case 'md':
return {
format: 'md',
content: generateMdReport(sortedScoredReport),
};
}
});

if (!(await directoryExists(outputDir))) {
try {
Expand Down
9 changes: 4 additions & 5 deletions packages/core/src/lib/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
uploadToPortal,
} from '@code-pushup/portal-client';
import { PersistConfig, Report, UploadConfig } from '@code-pushup/models';
import { getLatestCommit, loadReport } from '@code-pushup/utils';
import { loadReport } from '@code-pushup/utils';
import { reportToGQL } from './implementation/report-to-gql';
import { GlobalOptions } from './types';

Expand All @@ -27,15 +27,14 @@ export async function upload(
...options.persist,
format: 'json',
});
const commitData = await getLatestCommit();
if (!commitData) {
throw new Error('no commit data available');
if (!report.commit) {
throw new Error('Commit must be linked in order to upload report');
}

const data: SaveReportMutationVariables = {
organization,
project,
commit: commitData.hash,
commit: report.commit.hash,
...reportToGQL(report),
};

Expand Down
32 changes: 24 additions & 8 deletions packages/models/docs/models-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,21 @@ _Object containing the following properties:_

_(\*) Required._

## Commit

Git commit

_Object containing the following properties:_

| Property | Description | Type |
| :----------------- | :------------------------------------- | :------------------------------------ |
| **`hash`** (\*) | Commit SHA (full) | `string` (_regex: `/^[\da-f]{40}$/`_) |
| **`message`** (\*) | Commit message | `string` |
| **`date`** (\*) | Date and time when commit was authored | `Date` (_nullable_) |
| **`author`** (\*) | Commit author name | `string` |

_(\*) Required._

## CoreConfig

_Object containing the following properties:_
Expand Down Expand Up @@ -1095,14 +1110,15 @@ _(\*) Required._

_Object containing the following properties:_

| Property | Description | Type |
| :--------------------- | :------------------------------------- | :-------------------------------------------------------- |
| **`packageName`** (\*) | NPM package name | `string` |
| **`version`** (\*) | NPM version of the CLI | `string` |
| **`date`** (\*) | Start date and time of the collect run | `string` |
| **`duration`** (\*) | Duration of the collect run in ms | `number` |
| **`categories`** (\*) | | _Array of [CategoryConfig](#categoryconfig) items_ |
| **`plugins`** (\*) | | _Array of at least 1 [PluginReport](#pluginreport) items_ |
| Property | Description | Type |
| :--------------------- | :---------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`packageName`** (\*) | NPM package name | `string` |
| **`version`** (\*) | NPM version of the CLI | `string` |
| **`date`** (\*) | Start date and time of the collect run | `string` |
| **`duration`** (\*) | Duration of the collect run in ms | `number` |
| **`categories`** (\*) | | _Array of [CategoryConfig](#categoryconfig) items_ |
| **`plugins`** (\*) | | _Array of at least 1 [PluginReport](#pluginreport) items_ |
| **`commit`** (\*) | Git commit for which report was collected | _Object with properties:_<ul><li>`hash`: `string` (_regex: `/^[\da-f]{40}$/`_) - Commit SHA (full)</li><li>`message`: `string` - Commit message</li><li>`date`: `Date` (_nullable_) - Date and time when commit was authored</li><li>`author`: `string` - Commit author name</li></ul> (_nullable_) |

_(\*) Required._

Expand Down
1 change: 1 addition & 0 deletions packages/models/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export {
categoryConfigSchema,
categoryRefSchema,
} from './lib/category-config';
export { Commit, commitSchema } from './lib/commit';
export { CoreConfig, coreConfigSchema } from './lib/core-config';
export { Group, GroupRef, groupRefSchema, groupSchema } from './lib/group';
export {
Expand Down
24 changes: 24 additions & 0 deletions packages/models/src/lib/commit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { z } from 'zod';

export const commitSchema = z.object(
{
hash: z
.string({ description: 'Commit SHA (full)' })
.regex(
/^[\da-f]{40}$/,
'Commit SHA should be a 40-character hexadecimal string',
),
message: z.string({ description: 'Commit message' }),
date: z.coerce.date({
description: 'Date and time when commit was authored',
}),
author: z
.string({
description: 'Commit author name',
})
.trim(),
},
{ description: 'Git commit' },
);

export type Commit = z.infer<typeof commitSchema>;
41 changes: 41 additions & 0 deletions packages/models/src/lib/commit.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { type Commit, commitSchema } from './commit';

describe('commitSchema', () => {
it('should accept valid git commit data', () => {
expect(() =>
commitSchema.parse({
hash: 'abcdef0123456789abcdef0123456789abcdef01',
message: 'Minor fixes',
author: 'John Doe',
date: new Date(),
} satisfies Commit),
).not.toThrow();
});

it('should coerce date string into Date object', () => {
expect(
commitSchema.parse({
hash: 'abcdef0123456789abcdef0123456789abcdef01',
message: 'Minor fixes',
author: 'John Doe',
date: '2024-03-06T17:30:12+01:00',
}),
).toEqual<Commit>({
hash: 'abcdef0123456789abcdef0123456789abcdef01',
message: 'Minor fixes',
author: 'John Doe',
date: new Date('2024-03-06T17:30:12+01:00'),
});
});

it('should throw for invalid hash', () => {
expect(() =>
commitSchema.parse({
hash: '12345678', // too short
message: 'Minor fixes',
author: 'John Doe',
date: new Date(),
} satisfies Commit),
).toThrow('Commit SHA should be a 40-character hexadecimal string');
});
});
4 changes: 4 additions & 0 deletions packages/models/src/lib/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { z } from 'zod';
import { auditSchema } from './audit';
import { auditOutputSchema } from './audit-output';
import { categoryConfigSchema } from './category-config';
import { commitSchema } from './commit';
import { Group, groupSchema } from './group';
import {
executionMetaSchema,
Expand Down Expand Up @@ -76,6 +77,9 @@ export const reportSchema = packageVersionSchema({
{
categories: z.array(categoryConfigSchema),
plugins: z.array(pluginReportSchema).min(1),
commit: commitSchema
.describe('Git commit for which report was collected')
.nullable(),
},
{ description: 'Collect output data' },
),
Expand Down
7 changes: 7 additions & 0 deletions packages/models/src/lib/report.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ describe('reportSchema', () => {
title: 'Bug prevention',
},
],
commit: {
hash: 'abcdef0123456789abcdef0123456789abcdef01',
message: 'Minor fixes',
author: 'John Doe',
date: new Date('2024-01-07T09:15:00.000Z'),
},
date: '2024-01-07T09:30:00.000Z',
duration: 600,
plugins: [
Expand Down Expand Up @@ -235,6 +241,7 @@ describe('reportSchema', () => {
title: 'Bug prevention',
},
],
commit: null,
date: '2024-01-07T09:30:00.000Z',
duration: 600,
plugins: [
Expand Down
1 change: 0 additions & 1 deletion packages/utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ export {
getGitRoot,
getLatestCommit,
toGitPath,
validateCommitData,
} from './lib/git';
export { groupByStatus } from './lib/group-by-status';
export {
Expand Down
Loading

0 comments on commit 5965900

Please sign in to comment.