Skip to content

Commit

Permalink
feat: add a command for automated releases (#62)
Browse files Browse the repository at this point in the history
  • Loading branch information
gumptious committed Nov 14, 2019
1 parent 5a7ceb0 commit 600cc44
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 23 deletions.
1 change: 1 addition & 0 deletions .diezrc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"./scripts/commands/generate-docs",
"./scripts/commands/health",
"./scripts/commands/minify-sources",
"./scripts/commands/release",
"./scripts/commands/watch"
]
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"health": "yarn diez-cli health",
"lint": "lerna run lint --no-bail",
"postinstall": "yarn compile",
"release": "yarn diez-cli release",
"test": "lerna run test",
"watch": "yarn diez-cli watch",
"prepublishOnly": "yarn clean",
Expand Down
1 change: 1 addition & 0 deletions packages/types/semver.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
declare module 'semver' {
export function gt(a: string, b: string): boolean;
export function gte(a: string, b: string): boolean;
}
4 changes: 2 additions & 2 deletions scripts/commands/build-examples.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* tslint:disable:max-line-length */
import {fatalError} from '@diez/cli-core';
import chalk from 'chalk';
import glob from 'glob';
import {basename, join, resolve} from 'path';
Expand Down Expand Up @@ -55,8 +56,7 @@ export = {
}],
action: async ({target}: Flags) => {
if (!target) {
console.log(chalk.red('--target is required.'));
process.exit(1);
fatalError('--target is required.');
}

switch (target) {
Expand Down
4 changes: 2 additions & 2 deletions scripts/commands/create-package.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {fatalError} from '@diez/cli-core';
import chalk from 'chalk';
import enquirer from 'enquirer';
import {copy, existsSync} from 'fs-extra';
Expand All @@ -10,8 +11,7 @@ export = {
action: async () => {
const templateLocation = join(root, 'templates', 'package');
if (!existsSync(templateLocation)) {
console.log(chalk.red(`Unable to location template project in ${templateLocation}. Aborting.`));
return;
fatalError(`Unable to location template project in ${templateLocation}. Aborting.`);
}

interface Answers {
Expand Down
11 changes: 5 additions & 6 deletions scripts/commands/generate-docs.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import chalk from 'chalk';
import {fatalError} from '@diez/cli-core';
import {Stats} from 'fs-extra';
import {walkSync} from 'fs-walk';
import {extname, join, relative, sep} from 'path';
import {Project} from 'ts-morph';
import {assertNotWatching, root, run} from '../internal/helpers';
import {assertNotWatching, root, run, runQuiet} from '../internal/helpers';

const packageRoot = join(root, 'packages');

Expand All @@ -12,10 +12,9 @@ export = {
description: 'Generates docs.',
action: async () => {
assertNotWatching();
const gitChanges = run('git diff packages', root, 'pipe');
if (gitChanges && gitChanges.toString()) {
console.log(chalk.red('Found untracked Git changes in packages/. Stash them before generating docs.'));
process.exit(1);
const gitChanges = runQuiet('git diff packages');
if (gitChanges) {
fatalError('Found untracked Git changes in packages/. Stash them before generating docs.');
}

const project = new Project();
Expand Down
19 changes: 8 additions & 11 deletions scripts/commands/health.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import chalk from 'chalk';
import {root, run} from '../internal/helpers';
import {fatalError} from '@diez/cli-core';
import {run, runQuiet} from '../internal/helpers';

export= {
name: 'health',
description: 'Executes monorepo health checks.',
action: async () => {
const gitChanges = run('git diff yarn.lock', root, 'pipe');
if (gitChanges && gitChanges.toString()) {
console.log(
chalk.red('Found untracked Git changes in `yarn.lock`. Be sure to stage and commit all `yarn.lock` changes.'));
process.exit(1);
const gitChanges = runQuiet('git diff yarn.lock');
if (gitChanges) {
fatalError('Found untracked Git changes in `yarn.lock`. Be sure to stage and commit all `yarn.lock` changes.');
}

// Ensures docs are generated without errors.
const docs = run('yarn docs', root, 'pipe');
if (!docs || docs.toString().includes('Error:')) {
console.log(chalk.red('Generating docs produced an error. Please fix the issue and try again.'));
process.exit(1);
const docs = runQuiet('yarn docs');
if (docs.includes('Error:')) {
fatalError('Generating docs produced an error. Please fix the issue and try again.');
}

// Run health checks in all packages.
Expand Down
4 changes: 2 additions & 2 deletions scripts/commands/minify-sources.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import chalk from 'chalk';
import {fatalError} from '@diez/cli-core';
import {outputFileSync, readFileSync} from 'fs-extra';
import glob from 'glob';
import {join} from 'path';
Expand All @@ -24,7 +24,7 @@ export = {

if (minified.error) {
minificationError = true;
console.log(chalk.red(`Unable to minify ${filePath}!`));
fatalError(`Unable to minify ${filePath}!`);
}

outputFileSync(filePath, minified.code);
Expand Down
53 changes: 53 additions & 0 deletions scripts/commands/release.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {diezVersion, fatalError} from '@diez/cli-core';
import {readJsonSync, writeJsonSync} from 'fs-extra';
import {join} from 'path';
import {gte} from 'semver';
import {root, run, runQuiet} from '../internal/helpers';

export = {
name: 'release [version]',
description: 'Creates a release.',
action: async (_: {}, version: string) => {
if (!version || gte(diezVersion, version)) {
fatalError('Refusing to set a lower version.');
}

if (runQuiet('git rev-parse --abbrev-ref HEAD') !== 'master') {
fatalError('You must be on the `master` branch to create a release.');
}

if (runQuiet('git diff')) {
fatalError('Working tree has untracked changes; unable to proceed.');
}

run('git fetch');
if (runQuiet('git diff origin/master')) {
fatalError('You must be up to date on the latest `master` branch to create a release.');
}

try {
runQuiet('aws s3 ls s3://diez-docs');
} catch (e) {
fatalError('Unable to run AWS S3 commands. `aws` is either not installed or missing privileges.');
}

const docs = runQuiet('yarn docs');
if (docs.includes('Error:')) {
fatalError('Generating docs produced an error. Please fix the issue and try again.');
}

run(`aws s3 cp api s3://diez-docs/${version} --recursive`);
run('aws s3 sync api s3://diez-docs/latest');

// Manually bump the monorepo package.json version of `diez-cli`.
const packageJsonPath = join(root, 'package.json');
const packageJson = readJsonSync(packageJsonPath);
packageJson.devDependencies['diez-cli'] = version;
writeJsonSync(packageJsonPath, packageJson, {spaces: 2});
run('git add package.json');
run(`git commit -m 'release: ${version}'`);

// Create the release with Lerna.
run(`yarn lerna publish ${version} --github-release --conventional-commits --amend --yes`);
},
};
5 changes: 5 additions & 0 deletions scripts/internal/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export const currentVersion = require(join(root, 'packages', 'engine', 'package.
*/
export const run = (command: string, cwd = root, stdio: StdioOptions = 'inherit') => execSync(command, {cwd, stdio});

/**
* Runs the provided command synchronously in band.
*/
export const runQuiet = (command: string, cwd = root) => execSync(command, {cwd, stdio: 'pipe'}).toString().trim();

/**
* The location of the watchfile indicating a watch is active.
*/
Expand Down

0 comments on commit 600cc44

Please sign in to comment.