Skip to content

Commit

Permalink
fix: 🐞 release since first commit if no version found (resolve #102)
Browse files Browse the repository at this point in the history
Co-authored-by: Younes Jaaidi <yjaaidi@gmail.com>
  • Loading branch information
edbzn and yjaaidi committed Mar 23, 2021
1 parent c88d711 commit f882009
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 188 deletions.
6 changes: 3 additions & 3 deletions packages/semver/src/builders/version/builder.e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -636,15 +636,15 @@ $`)
function commitChanges() {
execSync(
`
git init;
git init
# These are needed by CI.
git config user.email "bot@jest.io"
git config user.name "Test Bot"
git config commit.gpgsign false
git add .;
git commit -m "🐣";
git add .
git commit -m "🐣"
echo a > packages/a/a.txt
git add .
git commit -m "feat(a): 🚀 new feature"
Expand Down
5 changes: 3 additions & 2 deletions packages/semver/src/builders/version/builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,8 @@ describe('@jscutlery/semver:version', () => {
});

it('should abort when validation hook failed', async () => {
mockValidateA.mockRejectedValue(new Error('Validation failure'));
context.logger.error = jest.fn();
mockValidateA.mockRejectedValue('Validation failure');

const { success } = await runBuilder(
{ ...options, plugins: ['@mock-plugin/A', '@mock-plugin/B'] },
Expand All @@ -372,7 +373,7 @@ describe('@jscutlery/semver:version', () => {
expect(mockPublishA).not.toBeCalled();
expect(mockPublishB).not.toBeCalled();
expect(context.logger.error).toBeCalledWith(
expect.stringContaining('Error: Validation failure')
expect.stringContaining('Validation failure')
);
});

Expand Down
2 changes: 1 addition & 1 deletion packages/semver/src/builders/version/testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function setupTestingWorkspace(

export function createFakeLogger(): logging.LoggerApi {
return {
error: jest.fn(),
error: jest.fn((e) => console.error(e)),
info: jest.fn(),
warn: jest.fn(),
createChild: jest.fn(),
Expand Down

This file was deleted.

58 changes: 0 additions & 58 deletions packages/semver/src/builders/version/utils/get-current-version.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as gitSemverTags from 'git-semver-tags';
import { callbackify } from 'util';

import { getLastVersion } from './get-last-version';

jest.mock('git-semver-tags', () => jest.fn());
jest.mock('./project');

const tagPrefix = 'my-lib-';

describe(getLastVersion.name, () => {
let mockGitSemverTags: jest.Mock;

beforeEach(() => {
mockGitSemverTags = jest.fn();
(gitSemverTags as jest.Mock).mockImplementation(
callbackify(mockGitSemverTags)
);
});

it('should compute current version from previous semver tag', async () => {
mockGitSemverTags.mockResolvedValue(['my-lib-2.1.0', 'my-lib-2.0.0', 'my-lib-1.0.0']);

const tag = await getLastVersion({ tagPrefix }).toPromise();

expect(tag).toEqual('2.1.0');
});

it('should throw error if no tag available', async () => {
mockGitSemverTags.mockResolvedValue([]);

expect(getLastVersion({ tagPrefix }).toPromise()).rejects.toThrow('No semver tag found');
});
});
25 changes: 25 additions & 0 deletions packages/semver/src/builders/version/utils/get-last-version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import * as gitSemverTags from 'git-semver-tags';
import { from, Observable, of, throwError } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import * as semver from 'semver';
import { promisify } from 'util';

export function getLastVersion({
tagPrefix,
}: {
tagPrefix: string;
}): Observable<string> {
return from(promisify(gitSemverTags)({ tagPrefix })).pipe(
switchMap((tags: string[]) => {
const versions = tags.map(tag => tag.substring(tagPrefix.length));
const [version] = versions.sort(semver.rcompare);

if (version == null) {
return throwError(new Error('No semver tag found'));
}

const tag =`${tagPrefix}${version}`;
return of(tag.substring(tagPrefix.length));
})
);
}
32 changes: 1 addition & 31 deletions packages/semver/src/builders/version/utils/git.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
addToStage,
getCommits,
getFirstCommitRef,
getLastTag,
tryPushToGitRemote,
} from './git';

Expand Down Expand Up @@ -175,36 +174,7 @@ describe('git', () => {
});
});

describe('getLastTag', () => {
it('should get last git commit', async () => {
jest
.spyOn(cp, 'execAsync')
.mockReturnValue(of({ stderr: '', stdout: '0.0.0' }));

const tag = await getLastTag().toPromise();

expect(tag).toBe('0.0.0');
expect(cp.execAsync).toBeCalledWith(
'git',
expect.arrayContaining(['describe', '--tags', '--abbrev=0'])
);
});

it('should throw on failure', async () => {
jest
.spyOn(cp, 'execAsync')
.mockReturnValue(of({ stderr: 'error', stdout: '' }));

try {
await getLastTag().toPromise();
fail();
} catch (error) {
expect(error.message).toBe('No tag found');
}
});
});

describe('getFirstCommitRef', () => {
describe('getFirstCommitRef', () => {
it('should get last git commit', async () => {
jest
.spyOn(cp, 'execAsync')
Expand Down
8 changes: 0 additions & 8 deletions packages/semver/src/builders/version/utils/git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,6 @@ export function addToStage({
});
}

export function getLastTag(): Observable<string> {
return execAsync('git', ['describe', '--tags', '--abbrev=0']).pipe(
switchMap(({ stdout }) =>
stdout ? of(stdout) : throwError(new Error('No tag found'))
)
);
}

export function getFirstCommitRef(): Observable<string> {
return execAsync('git', ['rev-list', '--max-parents=0', 'HEAD']).pipe(
/** Remove line breaks. */
Expand Down
20 changes: 10 additions & 10 deletions packages/semver/src/builders/version/utils/try-bump.spec.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { logging } from '@angular-devkit/core';
import * as conventionalRecommendedBump from 'conventional-recommended-bump';
import { of } from 'rxjs';
import { of, throwError } from 'rxjs';
import { callbackify } from 'util';

import { createFakeLogger } from '../testing';
import { getCurrentVersion } from './get-current-version';
import { getLastVersion } from './get-last-version';
import { getCommits, getFirstCommitRef } from './git';
import { tryBump } from './try-bump';

jest.mock('conventional-recommended-bump');
jest.mock('./get-current-version');
jest.mock('./get-last-version');
jest.mock('./git');

describe('tryBump', () => {
const mockConventionalRecommendedBump = conventionalRecommendedBump as jest.MockedFunction<
typeof conventionalRecommendedBump
>;
const mockCurrentVersion = getCurrentVersion as jest.MockedFunction<
typeof getCurrentVersion
const mockGetLastVersion = getLastVersion as jest.MockedFunction<
typeof getLastVersion
>;
const mockGetCommits = getCommits as jest.MockedFunction<typeof getCommits>;
const mockGetFirstCommitRef = getFirstCommitRef as jest.MockedFunction<typeof getFirstCommitRef>;
Expand All @@ -26,19 +26,19 @@ describe('tryBump', () => {

beforeEach(() => {
logger = createFakeLogger();
mockCurrentVersion.mockReturnValue(of('v2.1.0'))
mockGetLastVersion.mockReturnValue(of('2.1.0'))
});

afterEach(() => {
mockCurrentVersion.mockRestore();
mockGetLastVersion.mockRestore();
mockConventionalRecommendedBump.mockRestore();
mockGetCommits.mockRestore();
mockGetFirstCommitRef.mockRestore();
});

afterEach(() => (getCommits as jest.Mock).mockRestore());

it('should compute next version based on current version and changes', async () => {
it('should compute next version based on last version and changes', async () => {
mockGetCommits.mockReturnValue(of(['feat: A', 'feat: B']));
/* Mock bump to return "minor". */
mockConventionalRecommendedBump.mockImplementation(
Expand Down Expand Up @@ -112,7 +112,7 @@ describe('tryBump', () => {
});

it('should call getFirstCommitRef if version is 0.0.0', async () => {
mockCurrentVersion.mockReturnValue(of('0.0.0'));
mockGetLastVersion.mockReturnValue(throwError('No version found'));
mockGetCommits.mockReturnValue(of([]));
mockGetFirstCommitRef.mockReturnValue(of('sha1'));

Expand All @@ -125,7 +125,7 @@ describe('tryBump', () => {
logger,
}).toPromise();


expect(logger.warn).toBeCalledWith(expect.stringContaining('No previous version tag found'))
expect(mockGetCommits).toBeCalledTimes(1);
expect(mockGetCommits).toBeCalledWith({
projectRoot: '/libs/demo',
Expand Down
Loading

0 comments on commit f882009

Please sign in to comment.