Skip to content

Commit

Permalink
feat(manifest): add support for releasing root module (googleapis#833)
Browse files Browse the repository at this point in the history
  • Loading branch information
bcoe committed Mar 24, 2021
1 parent f06894c commit 7ec1037
Show file tree
Hide file tree
Showing 6 changed files with 324 additions and 4 deletions.
145 changes: 145 additions & 0 deletions __snapshots__/manifest.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,148 @@
exports['Manifest pullRequest allows root module to be published, via special "." path: changes'] = `
filename: node/pkg1/CHANGELOG.md
# Changelog
## [4.0.0](https://www.github.com/fake/repo/compare/pkg1-v3.2.1...pkg1-v4.0.0) (1983-10-10)
### ⚠ BREAKING CHANGES
* **@node/pkg1:** major new feature
### Features
* **@node/pkg1:** major new feature ([e3ab0ab](https://www.github.com/fake/repo/commit/e3ab0abfd66e66324f685ceeececf35c))
filename: node/pkg1/package.json
{
"name": "@node/pkg1",
"version": "4.0.0"
}
filename: node/pkg2/CHANGELOG.md
# Changelog
## [2.0.0](https://www.github.com/fake/repo/compare/pkg2-v1.2.3...pkg2-v2.0.0) (1983-10-10)
### ⚠ BREAKING CHANGES
* **@node/pkg2:** major new feature
### Features
* **@node/pkg2:** major new feature ([72f962d](https://www.github.com/fake/repo/commit/72f962d44ba0bcee15594ea6bdc67d8b))
filename: node/pkg2/package.json
{
"name": "@node/pkg2",
"version": "2.0.0"
}
filename: CHANGELOG.md
# Changelog
## [3.0.0](https://www.github.com/fake/repo/compare/googleapis-v2.0.0...googleapis-v3.0.0) (1983-10-10)
### ⚠ BREAKING CHANGES
* **@node/pkg1:** major new feature
* **@node/pkg2:** major new feature
### Features
* **@node/pkg1:** major new feature ([e3ab0ab](https://www.github.com/fake/repo/commit/e3ab0abfd66e66324f685ceeececf35c))
* **@node/pkg2:** major new feature ([72f962d](https://www.github.com/fake/repo/commit/72f962d44ba0bcee15594ea6bdc67d8b))
### Bug Fixes
* **root:** root only change ([8b55db3](https://www.github.com/fake/repo/commit/8b55db3f6115306cc9c132bec0bb1447))
filename: package.json
{
"name": "googleapis",
"version": "3.0.0"
}
filename: .release-please-manifest.json
{
".": "3.0.0",
"node/pkg1": "4.0.0",
"node/pkg2": "2.0.0"
}
`

exports['Manifest pullRequest allows root module to be published, via special "." path: options'] = `
upstreamOwner: fake
upstreamRepo: repo
title: chore: release
branch: release-please/branches/main
description: :robot: I have created a release \\*beep\\* \\*boop\\*
---
@node/pkg1: 4.0.0
## [4.0.0](https://www.github.com/fake/repo/compare/pkg1-v3.2.1...pkg1-v4.0.0) (1983-10-10)
### ⚠ BREAKING CHANGES
* **@node/pkg1:** major new feature
### Features
* **@node/pkg1:** major new feature ([e3ab0ab](https://www.github.com/fake/repo/commit/e3ab0abfd66e66324f685ceeececf35c))
---
---
@node/pkg2: 2.0.0
## [2.0.0](https://www.github.com/fake/repo/compare/pkg2-v1.2.3...pkg2-v2.0.0) (1983-10-10)
### ⚠ BREAKING CHANGES
* **@node/pkg2:** major new feature
### Features
* **@node/pkg2:** major new feature ([72f962d](https://www.github.com/fake/repo/commit/72f962d44ba0bcee15594ea6bdc67d8b))
---
---
googleapis: 3.0.0
## [3.0.0](https://www.github.com/fake/repo/compare/googleapis-v2.0.0...googleapis-v3.0.0) (1983-10-10)
### ⚠ BREAKING CHANGES
* **@node/pkg1:** major new feature
* **@node/pkg2:** major new feature
### Features
* **@node/pkg1:** major new feature ([e3ab0ab](https://www.github.com/fake/repo/commit/e3ab0abfd66e66324f685ceeececf35c))
* **@node/pkg2:** major new feature ([72f962d](https://www.github.com/fake/repo/commit/72f962d44ba0bcee15594ea6bdc67d8b))
### Bug Fixes
* **root:** root only change ([8b55db3](https://www.github.com/fake/repo/commit/8b55db3f6115306cc9c132bec0bb1447))
---
This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please).
primary: main
force: true
fork: false
message: chore: release
`

exports['Manifest pullRequest boostraps from HEAD manifest if first PR: changes'] = `
filename: node/pkg1/CHANGELOG.md
Expand Down
12 changes: 12 additions & 0 deletions docs/manifest-releaser.md
Original file line number Diff line number Diff line change
Expand Up @@ -233,3 +233,15 @@ PRs merge w/out running it). If successful it will remove the
`"autorelease: pending"` label and adds the `"autorelease: tagged"` label.
Creating all the releases is not transactional. If any fail to create the
command can be re-run safely to finish creating releases.

### Releasing Root Path of Library (".")

One use-case that arose for [googleapis](https://github.com/googleapis/google-api-nodejs-client), was the need to publish individual libraries along
with a combined version of the library, i.e.,

* an individual library for `@googleapis/youtube`, `@googleapis/sheets`, etc.
* a root library that combined all these API surfaces.

This functionality can be achieved by using the special `"."` path.
`"."` indicates a release should be created when any changes are made to the
codebase.
8 changes: 5 additions & 3 deletions src/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ export class Manifest {
}

protected async getPackagesToRelease(
commits: Commit[],
allCommits: Commit[],
sha?: string
): Promise<PackageReleaseData[]> {
const packages = (await this.getConfigJson()).parsedPackages;
Expand All @@ -288,12 +288,14 @@ export class Manifest {
includeEmpty: true,
packagePaths: packages.map(p => p.path),
});
const commitsPerPath = cs.split(commits);
const commitsPerPath = cs.split(allCommits);
const packagesToRelease: Record<string, PackageReleaseData> = {};
const missingVersionPaths = [];
const defaultBranch = await this.gh.getDefaultBranch();
for (const pkg of packages) {
const commits = commitsPerPath[pkg.path];
// The special path of '.' indicates the root module is being released
// in this case, use the entire list of commits:
const commits = pkg.path === '.' ? allCommits : commitsPerPath[pkg.path];
if (!commits || commits.length === 0) {
continue;
}
Expand Down
4 changes: 3 additions & 1 deletion src/release-pr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ export class ReleasePR {
constructor(options: ReleasePRConstructorOptions) {
this.bumpMinorPreMajor = options.bumpMinorPreMajor || false;
this.labels = options.labels ?? DEFAULT_LABELS;
this.path = options.path;
// undefined represents the root path of the library, if the special
// '.' path is provided, simply ignore it:
this.path = options.path !== '.' ? options.path : undefined;
this.packageName = options.packageName || '';
this.monorepoTags = options.monorepoTags || false;
this.releaseAs = options.releaseAs;
Expand Down
4 changes: 4 additions & 0 deletions test/fixtures/manifest/repo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "googleapis",
"version": "3.3.3"
}
155 changes: 155 additions & 0 deletions test/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ describe('Manifest', () => {
'node/pkg2/CHANGELOG.md',
'python/CHANGELOG.md',
'python/HISTORY.md',
'package-lock.json',
'samples/package.json',
'CHANGELOG.md',
];
for (const notFound of expectedNotFound) {
mock
Expand Down Expand Up @@ -283,6 +286,78 @@ describe('Manifest', () => {
]);
});

it('allows root module to be published, via special "." path', async function () {
const manifest = JSON.stringify({
'node/pkg1': '3.2.1',
'node/pkg2': '1.2.3',
'.': '2.0.0',
});
const config = JSON.stringify({
packages: {
'node/pkg1': {},
'node/pkg2': {},
'.': {},
},
});
const commits = [
buildMockCommit('feat(@node/pkg1)!: major new feature', [
'node/pkg1/src/foo.ts',
]),
buildMockCommit('feat(@node/pkg2)!: major new feature', [
'node/pkg2/src/bar.ts',
]),
buildMockCommit('fix(root): root only change', ['src/foo.ts']),
];

const github = new GitHub({
owner: 'fake',
repo: 'repo',
defaultBranch,
});
const mock = mockGithub(github);
expectManifest(mock, {manifest, lastReleaseSha});
expectPR(mock, {lastReleaseSha});
expectCommitsSinceSha(mock, {commits, lastReleaseSha});
expectGetFiles(mock, {
fixtureFiles: [
'node/pkg1/package.json',
'node/pkg2/package.json',
'package.json',
],
inlineFiles: [
['release-please-config.json', config],
['.release-please-manifest.json', manifest],
],
});
expectLabelAndComment(mock, {addLabel});
stubSuggesterWithSnapshot(sandbox, this.test!.fullTitle());
const logs: [string, CheckpointType][] = [];
const checkpoint = (msg: string, type: CheckpointType) =>
logs.push([msg, type]);

const pr = await new Manifest({github, checkpoint}).pullRequest();

mock.verify();
expect(pr).to.equal(22);
expect(logs).to.eql([
[
'Found version 3.2.1 for node/pkg1 in .release-please-manifest.json at abc123 of main',
CheckpointType.Success,
],
[
'Found version 1.2.3 for node/pkg2 in .release-please-manifest.json at abc123 of main',
CheckpointType.Success,
],
[
'Found version 2.0.0 for . in .release-please-manifest.json at abc123 of main',
CheckpointType.Success,
],
['Processing package: Node(@node/pkg1)', CheckpointType.Success],
['Processing package: Node(@node/pkg2)', CheckpointType.Success],
['Processing package: Node(googleapis)', CheckpointType.Success],
]);
});

it('respects python releaser specific config over defaults', async function () {
// https://github.com/googleapis/release-please/pull/790#issuecomment-783792069
if (process.versions.node.split('.')[0] === '10') {
Expand Down Expand Up @@ -1750,6 +1825,86 @@ describe('Manifest', () => {
],
]);
});

it('releases library in root (".")', async () => {
const manifest = JSON.stringify({
'.': '3.2.1',
});
const config = JSON.stringify({
packages: {
'.': {},
},
});

const github = new GitHub({
owner: 'fake',
repo: 'repo',
defaultBranch,
});
const mock = mockGithub(github);
expectManifest(mock, {manifest, lastReleaseSha});
expectPR(mock, {
lastReleaseSha,
mergedPRFiles: [
// lack of any "node/pkg2/ files indicates that package did not
// change in the last merged PR.
'package.json',
'CHANGELOG.md',
],
});
expectGetFiles(mock, {
fixtureFiles: ['package.json'],
inlineFiles: [
['release-please-config.json', config],
['.release-please-manifest.json', manifest],
['CHANGELOG.md', '#Changelog\n\n## v3.2.1\n\n* entry'],
],
});
expectLabelAndComment(mock, {
addLabel: 'autorelease: tagged',
removeLabel: 'autorelease: pending',
prComments: [
':robot: Release for googleapis is at https://googleapis@3.2.1:html :sunflower:',
],
});
mock
.expects('createRelease')
.withArgs(
'googleapis',
'googleapis-v3.2.1',
lastReleaseSha,
sinon.match.string,
false
)
.once()
.resolves({
name: 'googleapis googleapis-v3.2.1',
tag_name: 'googleapis-v3.2.1',
draft: false,
body: '',
html_url: 'https://googleapis@3.2.1:html',
upload_url: 'https://googleapis@3.2.1:upload',
});

const releases = await new Manifest({github}).githubRelease();
mock.verify();
expect(releases).to.eql({
'.': {
version: '3.2.1',
major: 3,
minor: 2,
patch: 1,
pr: 22,
draft: false,
body: '',
sha: 'abc123',
html_url: 'https://googleapis@3.2.1:html',
tag_name: 'googleapis-v3.2.1',
name: 'googleapis googleapis-v3.2.1',
upload_url: 'https://googleapis@3.2.1:upload',
},
});
});
});

describe('validate', () => {
Expand Down

0 comments on commit 7ec1037

Please sign in to comment.