Skip to content

Commit

Permalink
Merge 197d8e5 into 21ec33c
Browse files Browse the repository at this point in the history
  • Loading branch information
bcoe committed Feb 3, 2021
2 parents 21ec33c + 197d8e5 commit dd12f3b
Show file tree
Hide file tree
Showing 11 changed files with 303 additions and 266 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
exports['ReleasePRFactory buildStatic returns an instance of a statically loaded releaser 1'] = `
exports['factory ReleasePR returns instance of dynamically loaded releaser 1'] = `
[
[
"CHANGELOG.md",
Expand All @@ -17,7 +17,7 @@ exports['ReleasePRFactory buildStatic returns an instance of a statically loaded
]
`

exports['ReleasePRFactory build returns instance of dynamically loaded releaser 1'] = `
exports['factory buildStatic returns an instance of a statically loaded releaser 1'] = `
[
[
"CHANGELOG.md",
Expand Down
91 changes: 35 additions & 56 deletions src/bin/release-please.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@

import chalk = require('chalk');
import {coerceOption} from '../util/coerce-option';
import {GitHubRelease, GitHubReleaseOptions} from '../github-release';
import {GitHubReleaseOptions} from '../github-release';
import {ReleasePROptions} from '../release-pr';
import {ReleasePRFactory} from '../release-pr-factory';
import {factory} from '../factory';
import {getReleaserNames} from '../releasers';
import * as yargs from 'yargs';

Expand All @@ -41,34 +41,23 @@ interface YargsOptionsBuilder {
option(opt: string, options: YargsOptions): YargsOptionsBuilder;
}

const argv = yargs
export const parser = yargs
.command(
'release-pr',
'create or update a PR representing the next release',
(yargs: YargsOptionsBuilder) => {
yargs
.option('package-name', {
describe: 'name of package release is being minted for',
demand: true,
})
.option('version-file', {
describe: 'path to version file to update, e.g., version.rb',
})
.option('last-package-version', {
describe: 'last version # that package was released as',
})
.option('repo-url', {
describe: 'GitHub URL to generate release for',
demand: true,
})
.option('fork', {
describe: 'should the PR be created from a fork',
type: 'boolean',
default: false,
})
.option('label', {
describe: 'label(s) to add to generated PR',
})
.option('snapshot', {
describe: 'is it a snapshot (or pre-release) being generated?',
type: 'boolean',
Expand All @@ -78,55 +67,25 @@ const argv = yargs
describe: 'default branch to open release PR against',
type: 'string',
})
.option('path', {
describe: 'release from path other than root directory',
type: 'string',
})
.option('monorepo-tags', {
describe: 'include library name in tags and release branches',
type: 'boolean',
default: false,
});
},
(argv: ReleasePROptions) => {
const rp = ReleasePRFactory.build(argv.releaseType, argv);
rp.run().catch(handleError);
factory.runCommand('release-pr', argv).catch(handleError);
}
)
.command(
'github-release',
'create a GitHub release from a release PR',
(yargs: YargsOptionsBuilder) => {
yargs
.option('package-name', {
describe: 'name of package release is being minted for',
})
.option('repo-url', {
describe: 'GitHub URL to generate release for',
demand: true,
})
.option('changelog-path', {
default: 'CHANGELOG.md',
describe: 'where can the CHANGELOG be found in the project?',
})
.option('label', {
default: 'autorelease: pending',
describe: 'label to remove from release PR',
})
.option('release-type', {
describe: 'what type of repo is a release being created for?',
choices: getReleaserNames(),
default: 'node',
})
.option('path', {
describe: 'release from path other than root directory',
type: 'string',
})
.option('monorepo-tags', {
describe: 'include library name in tags and release branches',
type: 'boolean',
default: false,
})
.option('draft', {
describe:
'mark release as a draft. no tag is created but tag_name and ' +
Expand All @@ -137,8 +96,7 @@ const argv = yargs
});
},
(argv: GitHubReleaseOptions) => {
const gr = new GitHubRelease(argv);
gr.createRelease().catch(handleError);
factory.runCommand('github-release', argv).catch(handleError);
}
)
.middleware(_argv => {
Expand All @@ -147,7 +105,6 @@ const argv = yargs
// rather than being passed directly to the bin.
if (argv.token) argv.token = coerceOption(argv.token);
if (argv.apiUrl) argv.apiUrl = coerceOption(argv.apiUrl);
if (argv.proxyKey) argv.proxyKey = coerceOption(argv.proxyKey);
})
.option('token', {describe: 'GitHub token with repo write permissions'})
.option('release-as', {
Expand All @@ -170,10 +127,6 @@ const argv = yargs
default: 'https://api.github.com',
type: 'string',
})
.option('proxy-key', {
describe: 'key used by some GitHub proxies',
type: 'string',
})
.option('debug', {
describe: 'print verbose errors (use only for local debugging).',
default: false,
Expand All @@ -183,9 +136,35 @@ const argv = yargs
describe: '',
type: 'string',
})
.option('label', {
default: 'autorelease: pending',
describe: 'label to remove from release PR',
})
.option('repo-url', {
describe: 'GitHub URL to generate release for',
demand: true,
})
.option('path', {
describe: 'release from path other than root directory',
type: 'string',
})
.option('package-name', {
describe: 'name of package release is being minted for',
})
.option('monorepo-tags', {
describe: 'include library name in tags and release branches',
type: 'boolean',
default: false,
})
.demandCommand(1)
.strict(true)
.parse();
.strict(true);

// Only run parser if executed with node bin, this allows
// for the parser to be easily tested:
let argv: yargs.Arguments;
if (require.main === module) {
argv = parser.parse();
}

// The errors returned by octokit currently contain the
// request object, this contains information we don't want to
Expand All @@ -194,7 +173,7 @@ const argv = yargs
// the request object, don't do this in CI/CD).
function handleError(err: ErrorObject) {
let status = '';
const command = argv._.length === 0 ? '' : argv._[0];
const command = argv?._?.length ? argv._[0] : '';
if (err.status) {
status = '' + err.status;
}
Expand All @@ -203,7 +182,7 @@ function handleError(err: ErrorObject) {
`command ${command} failed${status ? ` with status ${status}` : ''}`
)
);
if (argv.debug) {
if (argv?.debug) {
console.error('---------');
console.error(err.stack);
}
Expand Down
73 changes: 73 additions & 0 deletions src/factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Factory shared by GitHub Action and CLI for creating Release PRs
// and GitHub Releases:

import {ReleasePR, ReleasePROptions} from './release-pr';
import {RubyReleasePROptions} from './releasers/ruby';
import {
GitHubReleaseOptions,
GitHubRelease,
ReleaseResponse,
} from './github-release';
import {getReleasers} from './releasers';

function runCommand(
command: string,
options: GitHubReleaseOptions | ReleasePROptions
): Promise<number | undefined | ReleaseResponse> {
if (isGitHubRelease(command, options)) {
return factory.run(githubRelease(options));
} else {
return factory.run(releasePR(options));
}
}

function isGitHubRelease(
command: string,
options: GitHubReleaseOptions | ReleasePROptions
): options is GitHubReleaseOptions {
return command === 'github-release' && typeof options === 'object';
}

function run(runnable: ReleasePR | GitHubRelease) {
return runnable.run();
}

function githubRelease(options: GitHubReleaseOptions): GitHubRelease {
return new GitHubRelease(options);
}

function releasePR(options: ReleasePROptions): ReleasePR {
const releaseOptions: ReleasePROptions | RubyReleasePROptions = options;
return new (factory.releasePRClass(options.releaseType))(releaseOptions);
}

export function releasePRClass(releaseType: string): typeof ReleasePR {
const releasers = getReleasers();
const releaser = releasers[releaseType];
if (!releaser) {
throw Error('unknown release type');
}
return releaser;
}

export const factory = {
githubRelease,
releasePR,
releasePRClass,
run,
runCommand,
};
38 changes: 17 additions & 21 deletions src/github-release.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import {SharedOptions, DEFAULT_LABELS} from './';
import {checkpoint, CheckpointType} from './util/checkpoint';
import {ReleasePRFactory} from './release-pr-factory';
import {factory} from './factory';
import {GitHub, OctokitAPIs} from './github';
import {parse} from 'semver';
import {ReleasePR} from './release-pr';
Expand All @@ -22,7 +23,7 @@ import {ReleasePR} from './release-pr';
const parseGithubRepoUrl = require('parse-github-repo-url');
const GITHUB_RELEASE_LABEL = 'autorelease: tagged';

interface ReleaseResponse {
export interface ReleaseResponse {
major: number;
minor: number;
patch: number;
Expand All @@ -35,16 +36,7 @@ interface ReleaseResponse {
draft: boolean;
}

export interface GitHubReleaseOptions {
label: string;
repoUrl: string;
path?: string;
packageName?: string;
monorepoTags?: boolean;
token?: string;
apiUrl: string;
proxyKey?: string;
octokitAPIs?: OctokitAPIs;
export interface GitHubReleaseOptions extends SharedOptions {
releaseType?: string;
changelogPath?: string;
draft?: boolean;
Expand All @@ -61,15 +53,15 @@ export class GitHubRelease {
packageName?: string;
monorepoTags?: boolean;
token?: string;
proxyKey?: string;
releaseType?: string;
draft: boolean;
defaultBranch?: string;

constructor(options: GitHubReleaseOptions) {
this.apiUrl = options.apiUrl;
this.proxyKey = options.proxyKey;
this.labels = options.label.split(',');
this.labels = options.label
? options.label.split(',')
: DEFAULT_LABELS.split(',');
this.repoUrl = options.repoUrl;
this.monorepoTags = options.monorepoTags;
this.token = options.token;
Expand All @@ -84,11 +76,13 @@ export class GitHubRelease {
this.gh = this.gitHubInstance(options.octokitAPIs);
}

async createRelease(): Promise<ReleaseResponse | undefined> {
async run(): Promise<ReleaseResponse | undefined> {
// Attempt to lookup the package name from a well known location, such
// as package.json, if none is provided:
if (!this.packageName && this.releaseType) {
this.packageName = await ReleasePRFactory.class(
this.releaseType
).lookupPackageName(this.gh, this.path);
this.packageName = await factory
.releasePRClass(this.releaseType)
.lookupPackageName(this.gh, this.path);
}
if (!this.packageName) {
throw Error(
Expand All @@ -107,7 +101,10 @@ export class GitHubRelease {
monorepoTags: this.monorepoTags,
};
const releasePR = this.releaseType
? ReleasePRFactory.build(this.releaseType, releaseOptions)
? factory.releasePR({
...releaseOptions,
...{releaseType: this.releaseType},
})
: new ReleasePR({
...releaseOptions,
...{releaseType: 'unknown'},
Expand Down Expand Up @@ -177,7 +174,6 @@ export class GitHubRelease {
owner,
repo,
apiUrl: this.apiUrl,
proxyKey: this.proxyKey,
octokitAPIs,
});
}
Expand Down

0 comments on commit dd12f3b

Please sign in to comment.