Skip to content

Commit

Permalink
feat(versioning): allow independent versioning (#984)
Browse files Browse the repository at this point in the history
* feat(versioning): allow independent versioning

For that to work, pass the `version` hook, and prevent most logic of `prepare`

* more text

* Apply suggestions from code review

Co-authored-by: Sarah Dayan <[email protected]>

Co-authored-by: Sarah Dayan <[email protected]>
  • Loading branch information
Haroenv and sarahdayan committed Nov 22, 2022
1 parent 91a9e95 commit 53f2f0b
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 111 deletions.
10 changes: 9 additions & 1 deletion packages/shipjs/jest.setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,16 @@ import {
import { mockColor } from './tests/util';
jest.mock('shipjs-lib');
jest.mock('./src/color');
jest.mock('./src/util');
jest.mock('./src/helper');
jest.mock('./src/util', () => {
const actual = jest.requireActual('./src/util');
const mock = jest.genMockFromModule('./src/util');

return {
...mock,
arrayify: actual.arrayify,
};
});

beforeEach(() => {
[info, warning, error, slateblue, bold, underline, reset].forEach(mockColor);
Expand Down
109 changes: 62 additions & 47 deletions packages/shipjs/src/flow/prepare.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import validatePreparationConditions from '../step/prepare/validatePreparationCo
import checkGitHubToken from '../step/checkGitHubToken';
import finished from '../step/prepare/finished';

import { print } from '../util';
import { arrayify, print, wrapExecWithDir } from '../util';
import { warning } from '../color';

async function prepare({
Expand All @@ -47,59 +47,74 @@ async function prepare({
checkGitHubToken({ dryRun });
const config = await loadConfig(dir);
const { currentVersion, baseBranch } = validate({ config, dir });
const { remote, forcePushBranches } = config;
pull({ remote, currentBranch: baseBranch, dir, dryRun });
fetchTags({ dir, dryRun });
push({ remote, currentBranch: baseBranch, forcePushBranches, dir, dryRun });
const currentTag = config.getTagName({ version: currentVersion });
const { revisionRange } = await getRevisionRange({
yes,
commitFrom,
currentTag,
dir,
});
let { nextVersion } = getNextVersion({
config,
revisionRange,
currentVersion,
dir,
});
nextVersion = await confirmNextVersion({
yes,
currentVersion,
nextVersion,
dryRun,
});
const releaseType = getReleaseType(nextVersion);
await validatePreparationConditions({
config,
releaseType,
nextVersion,
revisionRange,
dir,
dryRun,
});
const { remote, forcePushBranches, version } = config;

const currentTag = arrayify(
config.getTagName({ version: currentVersion })
)[0];
let nextVersion;
let releaseType;

if (version) {
({ nextVersion } = await version({
exec: wrapExecWithDir(dir),
}));
releaseType = getReleaseType(nextVersion);
} else {
pull({ remote, currentBranch: baseBranch, dir, dryRun });
fetchTags({ dir, dryRun });
push({ remote, currentBranch: baseBranch, forcePushBranches, dir, dryRun });
const { revisionRange } = await getRevisionRange({
yes,
commitFrom,
currentTag,
dir,
});
({ nextVersion } = getNextVersion({
config,
revisionRange,
currentVersion,
dir,
}));
nextVersion = await confirmNextVersion({
yes,
currentVersion,
nextVersion,
dryRun,
});
releaseType = getReleaseType(nextVersion);
await validatePreparationConditions({
config,
releaseType,
nextVersion,
revisionRange,
dir,
dryRun,
});

const updateVersionFn = config.monorepo
? updateVersionMonorepo
: updateVersion;
await updateVersionFn({ config, nextVersion, releaseType, dir, dryRun });
installDependencies({ config, dir, dryRun });
await updateChangelog({
config,
revisionRange,
firstRelease,
nextVersion,
releaseCount,
dir,
dryRun,
});
}

const { stagingBranch } = prepareStagingBranch({
config,
nextVersion,
releaseType,
dir,
});
checkoutToStagingBranch({ stagingBranch, dir, dryRun });
const updateVersionFn = config.monorepo
? updateVersionMonorepo
: updateVersion;
await updateVersionFn({ config, nextVersion, releaseType, dir, dryRun });
installDependencies({ config, dir, dryRun });
await updateChangelog({
config,
revisionRange,
firstRelease,
nextVersion,
releaseCount,
dir,
dryRun,
});
await commitChanges({
nextVersion,
releaseType,
Expand Down
6 changes: 3 additions & 3 deletions packages/shipjs/src/flow/release.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ async function release({ help = false, dir = '.', dryRun = false }) {
await runBeforePublish({ config, dir, dryRun });
runPublish({ isYarn, config, releaseTag, dir, dryRun });
await runAfterPublish({ version, releaseTag, config, dir, dryRun });
const { tagName } = createGitTag({ version, config, dir, dryRun });
gitPush({ tagName, config, dir, dryRun });
const { tagNames } = createGitTag({ version, config, dir, dryRun });
gitPush({ tagNames, config, dir, dryRun });
await createGitHubRelease({ version, config, dir, dryRun });
await notifyReleaseSuccess({
config,
appName,
version,
tagName,
tagNames,
latestCommitHash,
latestCommitUrl,
repoURL,
Expand Down
22 changes: 19 additions & 3 deletions packages/shipjs/src/step/release/__tests__/createGitTag.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { run } from '../../../util';
import createGitTag from '../createGitTag';

describe('createGitTag', () => {
it('works', () => {
const { tagName } = createGitTag({
it('works with one tag', () => {
const { tagNames } = createGitTag({
version: '1.2.3',
config: { getTagName: () => 'v1.2.3' },
dir: '.',
Expand All @@ -15,6 +15,22 @@ describe('createGitTag', () => {
dir: '.',
dryRun: false,
});
expect(tagName).toEqual('v1.2.3');
expect(tagNames).toEqual(['v1.2.3']);
});

it('works with multiple tags', () => {
const { tagNames } = createGitTag({
version: '1.2.3',
config: { getTagName: () => ['[email protected]', 'swag@4'] },
dir: '.',
dryRun: false,
});
expect(run).toHaveBeenCalledTimes(1);
expect(run).toHaveBeenCalledWith({
command: 'git tag [email protected] && git tag swag@4',
dir: '.',
dryRun: false,
});
expect(tagNames).toEqual(['[email protected]', 'swag@4']);
});
});
2 changes: 1 addition & 1 deletion packages/shipjs/src/step/release/__tests__/gitPush.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('gitPush', () => {
it('works', () => {
getCurrentBranch.mockImplementationOnce(() => 'master');
gitPush({
tagName: 'v1.2.3',
tagNames: ['v1.2.3'],
config: {
remote: 'origin',
},
Expand Down
92 changes: 47 additions & 45 deletions packages/shipjs/src/step/release/createGitHubRelease.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import mime from 'mime-types';
import { getRepoInfo } from 'shipjs-lib';
import runStep from '../runStep';
import { getChangelog } from '../../helper';
import { print } from '../../util';
import { arrayify, print } from '../../util';

export default async ({ version, config, dir, dryRun }) =>
await runStep(
Expand All @@ -19,58 +19,60 @@ export default async ({ version, config, dir, dryRun }) =>
getTagName,
releases: { assetsToUpload, extractChangelog } = {},
} = config;
const tagName = getTagName({ version });
const tagNames = arrayify(getTagName({ version }));

// extract matching changelog
const getChangelogFn = extractChangelog || getChangelog;
const changelog = getChangelogFn({ version, dir });
const content = changelog || '';
for await (const tagName of tagNames) {
// extract matching changelog
const getChangelogFn = extractChangelog || getChangelog;
const changelog = getChangelogFn({ version, dir });
const content = changelog || '';

// handle assets
const assetPaths = await getAssetPaths({
assetsToUpload,
dir,
version,
tagName,
});
// handle assets
const assetPaths = await getAssetPaths({
assetsToUpload,
dir,
version,
tagName,
});

if (dryRun) {
print('Creating a release with the following:');
print(` - content: ${content}`);
if (assetPaths.length > 0) {
print(` - assets: ${assetPaths.join(' ')}`);
if (dryRun) {
print('Creating a release with the following:');
print(` - content: ${content}`);
if (assetPaths.length > 0) {
print(` - assets: ${assetPaths.join(' ')}`);
}
return;
}
return;
}

const { owner, name: repo } = getRepoInfo(remote, dir);
const { owner, name: repo } = getRepoInfo(remote, dir);

const octokit = new Octokit({
auth: `token ${process.env.GITHUB_TOKEN}`,
});
const octokit = new Octokit({
auth: `token ${process.env.GITHUB_TOKEN}`,
});

const {
data: { upload_url }, // eslint-disable-line camelcase
} = await octokit.repos.createRelease({
owner,
repo,
tag_name: tagName, // eslint-disable-line camelcase
name: tagName,
body: content,
});
const {
data: { upload_url }, // eslint-disable-line camelcase
} = await octokit.repos.createRelease({
owner,
repo,
tag_name: tagName, // eslint-disable-line camelcase
name: tagName,
body: content,
});

if (assetPaths.length > 0) {
for (const assetPath of assetPaths) {
const file = path.resolve(dir, assetPath);
octokit.repos.uploadReleaseAsset({
file: fs.readFileSync(file),
headers: {
'content-length': fs.statSync(file).size,
'content-type': mime.lookup(file),
},
name: path.basename(file),
url: upload_url, // eslint-disable-line camelcase
});
if (assetPaths.length > 0) {
for (const assetPath of assetPaths) {
const file = path.resolve(dir, assetPath);
octokit.repos.uploadReleaseAsset({
file: fs.readFileSync(file),
headers: {
'content-length': fs.statSync(file).size,
'content-type': mime.lookup(file),
},
name: path.basename(file),
url: upload_url, // eslint-disable-line camelcase
});
}
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions packages/shipjs/src/step/release/createGitTag.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import runStep from '../runStep';
import { run } from '../../util';
import { arrayify, run } from '../../util';

export default ({ version, config, dir, dryRun }) =>
runStep({ title: 'Creating a git tag.' }, () => {
const { getTagName } = config;
const tagName = getTagName({ version });
const command = `git tag ${tagName}`;
const tagNames = arrayify(getTagName({ version }));
const command = tagNames.map((tag) => `git tag ${tag}`).join(' && ');
run({ command, dir, dryRun });
return { tagName };
return { tagNames };
});
4 changes: 2 additions & 2 deletions packages/shipjs/src/step/release/gitPush.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { getCurrentBranch } from 'shipjs-lib';
import runStep from '../runStep';
import { gitPush } from '../../helper';

export default ({ tagName, config, dir, dryRun }) =>
export default ({ tagNames, config, dir, dryRun }) =>
runStep({ title: 'Pushing to the remote.' }, () => {
const currentBranch = getCurrentBranch(dir);
const { remote, forcePushBranches } = config;
gitPush({
remote,
refs: [currentBranch, tagName],
refs: [currentBranch, ...tagNames],
forcePushBranches,
dir,
dryRun,
Expand Down
4 changes: 2 additions & 2 deletions packages/shipjs/src/step/release/notifyReleaseSuccess.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export default async ({
config,
appName,
version,
tagName,
tagNames,
latestCommitHash,
latestCommitUrl,
repoURL,
Expand All @@ -23,7 +23,7 @@ export default async ({
config,
appName,
version,
tagName,
tagNames,
latestCommitHash,
latestCommitUrl,
repoURL,
Expand Down
2 changes: 2 additions & 0 deletions packages/shipjs/src/util/arrayify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const arrayify = (itemOrArray) =>
Array.isArray(itemOrArray) ? itemOrArray : [itemOrArray];
1 change: 1 addition & 0 deletions packages/shipjs/src/util/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { arrayify } from './arrayify';
export { default as detectYarn } from './detectYarn';
export { default as exitProcess } from './exitProcess';
export { default as indentedPrint } from './indentedPrint';
Expand Down
4 changes: 2 additions & 2 deletions packages/shipjs/src/util/slack.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export async function notifyReleaseSuccess({
config,
appName,
version,
tagName,
tagNames,
latestCommitHash,
latestCommitUrl,
repoURL,
Expand All @@ -57,7 +57,7 @@ export async function notifyReleaseSuccess({
? releaseSuccess({
appName,
version,
tagName,
tagName: tagNames.join(', '),
latestCommitHash,
latestCommitUrl,
repoURL,
Expand Down

0 comments on commit 53f2f0b

Please sign in to comment.