Skip to content

Commit

Permalink
fix(roc-plugin-repo): Support merge commits in a better way for release
Browse files Browse the repository at this point in the history
  • Loading branch information
dlmr committed Sep 7, 2017
1 parent da54bcd commit 8155828
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 161 deletions.
9 changes: 8 additions & 1 deletion extensions/roc-plugin-repo/src/commands/release.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,12 @@ export default projects => ({
{
title: 'Updating CHANGELOG.md',
task: () =>
updateChangelogs(selectedToBeReleased, !!settings.mono, from),
updateChangelogs(
selectedToBeReleased,
!!settings.mono,
from,
prereleaseTag,
),
},
{
title: 'Prepare GitHub release',
Expand All @@ -314,6 +319,7 @@ export default projects => ({
isMonorepo,
individual,
from,
prereleaseTag,
);

if (!token) {
Expand All @@ -331,6 +337,7 @@ export default projects => ({
isMonorepo,
individual,
from,
prereleaseTag,
);

return Promise.resolve();
Expand Down
13 changes: 11 additions & 2 deletions extensions/roc-plugin-repo/src/semver/createGithubReleaseText.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default async function createGithubReleaseText(
isMonorepo,
individual,
from,
prerelease,
) {
individual = !isMonorepo ? true : individual; // eslint-disable-line no-param-reassign

Expand All @@ -22,7 +23,8 @@ export default async function createGithubReleaseText(
const latest = await getLatestCommitsSinceRelease(
'angular',
from,
!isMonorepo && projects[0].name,
projects,
isMonorepo,
);
const templates = await getTemplates(individual);
const generateReleaseNotesForProject = createGenerateReleaseNotesForProject(
Expand All @@ -32,10 +34,17 @@ export default async function createGithubReleaseText(
projects,
);
const projectTable = individual ? '' : createTable(projects);
const fromRelease = project =>
prerelease && latest[project].prerelease.hash
? latest[project].prerelease.hash
: latest[project].release.hash;

return Promise.all(
projects.map(project =>
generateReleaseNotesForProject(project, from || latest[project.name]),
generateReleaseNotesForProject(
project,
from || fromRelease(project.name),
),
),
).then(
releaseNotes =>
Expand Down
291 changes: 143 additions & 148 deletions extensions/roc-plugin-repo/src/semver/generateStatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,165 +6,160 @@ import {
isBreakingChange,
versions,
incrementToString,
incrementToValue,
getMultiScopes,
getAutoScopes,
getLatestCommitsSinceRelease,
} from './utils';

export default function generateStatus(projects, isMonorepo, from, prerelease) {
return new Promise(resolve => {
const status = {};
export default async function generateStatus(
projects,
isMonorepo,
from,
prerelease,
) {
const status = {};

projects.forEach(project => {
status[project.name] = {
increment: versions.NOTHING,
commits: [],
path: project.path,
newVersion: undefined,
packageJSON: project.packageJSON,
currentVersion: project.packageJSON.version,
currentVersionPrerelease: undefined,
currentPrerelease: undefined,
};
});

conventionalChangelog(
{
preset: 'angular',
append: true,
transform(commit, cb) {
const multiScopes = getMultiScopes(commit, isMonorepo);
const autoScopes = getAutoScopes(commit, isMonorepo, projects);
// We are only interested in commits which scope is one of our projects
if (
isMonorepo &&
upperCase(commit.scope) !== 'ALL' &&
multiScopes.length === 0 &&
autoScopes.length === 0 &&
!projects.find(({ name }) => name === commit.scope)
) {
cb();
return;
}
projects.forEach(project => {
status[project.name] = {
increment: versions.NOTHING,
commits: [],
path: project.path,
newVersion: undefined,
packageJSON: project.packageJSON,
currentVersion: project.packageJSON.version,
currentVersionPrerelease: undefined,
currentPrerelease: undefined,
};
});

// The projects that are effected by the scope
// Will always be the first project in a non monorepo
let affectedProjects = [projects[0].name];
const latest = await getLatestCommitsSinceRelease(
'angular',
from,
projects,
isMonorepo,
);

if (isMonorepo) {
if (upperCase(commit.scope) === 'ALL') {
affectedProjects = Object.keys(status);
} else if (multiScopes.length > 0) {
affectedProjects = multiScopes;
} else if (autoScopes.length > 0) {
affectedProjects = autoScopes;
} else {
affectedProjects = [commit.scope];
}
return Promise.all(
Object.keys(status).map(
project =>
new Promise(resolve => {
if (latest[project].release.subject) {
status[project].currentVersion = latest[project].release.subject;
}

let toPush = null;
if (commit.type === 'fix' || commit.type === 'perf') {
affectedProjects.forEach(p => {
status[p].increment = Math.max(
status[p].increment,
versions.PATCH,
);
});
toPush = commit;
}
if (commit.type === 'feat' || commit.type === 'revert') {
affectedProjects.forEach(p => {
status[p].increment = Math.max(
status[p].increment,
versions.MINOR,
);
});
toPush = commit;
}
if (isBreakingChange(commit)) {
affectedProjects.forEach(p => {
status[p].increment = Math.max(
status[p].increment,
versions.MAJOR,
);
});
toPush = commit;
}
if (toPush) {
affectedProjects.forEach(p => {
status[p].commits.push(commit);
});
if (latest[project].prerelease.subject) {
status[project].currentVersionPrerelease =
latest[project].prerelease.subject;
status[project].currentPrerelease = semver.prerelease(
latest[project].prerelease.subject,
)[0];
}
if (commit.type === 'release') {
status[affectedProjects[0]].increment = versions.NOTHING;
status[affectedProjects[0]].currentVersion = commit.subject;
status[affectedProjects[0]].commits = [];

// If we hit a release we also want to reset the prerelease
status[affectedProjects[0]].currentVersionPrerelease = undefined;
status[affectedProjects[0]].currentPrerelease = undefined;
}
if (commit.type === 'prerelease') {
status[affectedProjects[0]].currentVersionPrerelease =
commit.subject;
status[affectedProjects[0]].currentPrerelease = semver.prerelease(
commit.subject,
)[0];
const fromRelease =
prerelease && latest[project].prerelease.hash
? latest[project].prerelease.hash
: latest[project].release.hash;

if (prerelease) {
status[affectedProjects[0]].commits = [];
}
}
cb();
},
},
{},
{ reverse: true, from },
{
noteKeywords: [
'SCOPE',
'SCOPES',
'BREAKING CHANGE',
'BREAKING CHANGES',
],
},
)
.on('end', () => {
Object.keys(status).forEach(project => {
if (status[project].commits.length === 0) {
delete status[project];
} else if (prerelease && status[project].currentVersionPrerelease) {
// If we have a previous prerelease we want to find out if we have made a larger change
const difference = semver.diff(
status[project].currentVersion,
semver.inc(status[project].currentVersionPrerelease, 'patch'),
);
// If the range has changed we will need to make a new prerelease
if (incrementToString(status[project].increment) !== difference) {
status[project].newVersion = semver.inc(
status[project].currentVersion,
`pre${incrementToString(status[project].increment)}`,
prerelease,
);
} else {
status[project].newVersion = semver.inc(
status[project].currentVersionPrerelease,
'prerelease',
prerelease,
);
}
} else {
status[project].newVersion = semver.inc(
status[project].currentVersion,
prerelease
? `pre${incrementToString(status[project].increment)}`
: incrementToString(status[project].increment),
prerelease,
);
}
});
resolve(status);
})
.resume();
conventionalChangelog(
{
preset: 'angular',
append: true,
transform(commit, cb) {
const multiScopes = getMultiScopes(commit, isMonorepo);
const autoScopes = getAutoScopes(commit, isMonorepo, projects);
// We are only interested in commits which scope is one of our projects
if (
isMonorepo &&
upperCase(commit.scope) !== 'ALL' &&
!multiScopes.includes(project) &&
!autoScopes.includes(project) &&
commit.scope !== project
) {
cb();
return;
}

let toPush = null;
if (commit.type === 'fix' || commit.type === 'perf') {
status[project].increment = Math.max(
status[project].increment,
versions.PATCH,
);
toPush = commit;
}
if (commit.type === 'feat' || commit.type === 'revert') {
status[project].increment = Math.max(
status[project].increment,
versions.MINOR,
);
toPush = commit;
}
if (isBreakingChange(commit)) {
status[project].increment = Math.max(
status[project].increment,
versions.MAJOR,
);
toPush = commit;
}
if (toPush) {
status[project].commits.push(commit);
}
cb();
},
},
{},
{ reverse: true, from: from || fromRelease },
{
noteKeywords: [
'SCOPE',
'SCOPES',
'BREAKING CHANGE',
'BREAKING CHANGES',
],
},
)
.on('end', () => {
resolve();
})
.resume();
}),
),
).then(() => {
Object.keys(status).forEach(project => {
if (status[project].commits.length === 0) {
delete status[project];
} else if (prerelease && status[project].currentVersionPrerelease) {
// If we have a previous prerelease we want to find out if we have made a larger change
const difference = semver.diff(
status[project].currentVersion,
semver.inc(status[project].currentVersionPrerelease, 'patch'),
);
// If the range has changed we will need to make a new prerelease
if (status[project].increment > incrementToValue(difference)) {
status[project].newVersion = semver.inc(
status[project].currentVersion,
`pre${incrementToString(status[project].increment)}`,
prerelease,
);
} else {
status[project].newVersion = semver.inc(
status[project].currentVersionPrerelease,
'prerelease',
prerelease,
);
}
} else {
status[project].newVersion = semver.inc(
status[project].currentVersion,
prerelease
? `pre${incrementToString(status[project].increment)}`
: incrementToString(status[project].increment),
prerelease,
);
}
});

return status;
});
}
Loading

0 comments on commit 8155828

Please sign in to comment.