Skip to content

Commit

Permalink
feat: add meow as cli provider
Browse files Browse the repository at this point in the history
  • Loading branch information
antongolub committed Mar 6, 2020
1 parent 4199fa8 commit 6de93b9
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 66 deletions.
64 changes: 30 additions & 34 deletions bin/cli.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,36 @@
#!/usr/bin/env node

if (process.argv.includes("--watchspawn")) {
require("../lib/spawnHook").hook();
}
const meow = require("meow");
const pairs = require("lodash.pairs");
const set = require("lodash.set");
const runner = require("./runner");
const cli = meow(
`
Usage
$ multi-semantic-release
// Execa hook.
if (process.argv.includes("--execasync")) {
require("../lib/execaHook").hook();
}
Options
--sync, Forces all execa calls to be synchronous
--debug, Enables all additional logging
--debug.spawn Turns on logging for process.spawn
// Imports.
const getWorkspacesYarn = require("../lib/getWorkspacesYarn");
const multiSemanticRelease = require("../lib/multiSemanticRelease");

// Get directory.
const cwd = process.cwd();
Examples
$ multi-semantic-release --sync --debug
$ multi-semantic-release --debug.spawn
`,
{
flags: {
sync: {
type: "boolean",
alias: "execasync" // Legacy
},
debug: {
type: "boolean"
}
}
}
);

// Catch errors.
try {
// Get list of package.json paths according to Yarn workspaces.
const paths = getWorkspacesYarn(cwd);
const processFlags = flags => pairs(flags).reduce((m, [k, v]) => set(m, k, v), {});

// Do multirelease (log out any errors).
multiSemanticRelease(paths, {}, { cwd }).then(
() => {
// Success.
process.exit(0);
},
error => {
// Log out errors.
console.error(`[multi-semantic-release]:`, error);
process.exit(1);
}
);
} catch (error) {
// Log out errors.
console.error(`[multi-semantic-release]:`, error);
process.exit(1);
}
runner(processFlags(cli.flags));
42 changes: 42 additions & 0 deletions bin/runner.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
const get = require("lodash.get");

module.exports = flags => {
if (flags.watchspawn || get(flags, "debug.spawn")) {
require("../lib/spawnHook").hook();
}

// Execa hook.
if (flags.sync) {
require("../lib/execaHook").hook();
}

// Imports.
const getWorkspacesYarn = require("../lib/getWorkspacesYarn");
const multiSemanticRelease = require("../lib/multiSemanticRelease");

// Get directory.
const cwd = process.cwd();

// Catch errors.
try {
// Get list of package.json paths according to Yarn workspaces.
const paths = getWorkspacesYarn(cwd);

// Do multirelease (log out any errors).
multiSemanticRelease(paths, {}, { cwd }).then(
() => {
// Success.
process.exit(0);
},
error => {
// Log out errors.
console.error(`[multi-semantic-release]:`, error);
process.exit(1);
}
);
} catch (error) {
// Log out errors.
console.error(`[multi-semantic-release]:`, error);
process.exit(1);
}
};
63 changes: 35 additions & 28 deletions lib/createInlinePluginCreator.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,36 @@ function createInlinePluginCreator(packages, multiContext) {
// List of packages which are still todo (don't yet have a result).
const todo = () => packages.filter(p => p.result === undefined);

/**
* Update pkg deps.
* @param {Package} pkg The package this function is being called on.
* @param {string} path Path to package.json file
* @returns {undefined}
* @internal
*/
const updateManifestDeps = (pkg, path) => {
// Get and parse manifest file contents.
const manifest = getManifest(path);

// Loop through localDeps to update dependencies/devDependencies/peerDependencies in manifest.
pkg._localDeps.forEach(d => {
// Get version of dependency.
const release = d._nextRelease || d._lastRelease;

// Cannot establish version.
if (!release || !release.version)
throw Error(`Cannot release because dependency ${d.name} has not been released`);

// Update version of dependency in manifest.
if (manifest.dependencies.hasOwnProperty(d.name)) manifest.dependencies[d.name] = release.version;
if (manifest.devDependencies.hasOwnProperty(d.name)) manifest.devDependencies[d.name] = release.version;
if (manifest.peerDependencies.hasOwnProperty(d.name)) manifest.peerDependencies[d.name] = release.version;
});

// Write package.json back out.
writeFileSync(path, JSON.stringify(manifest));
};

/**
* Create an inline plugin for an individual package in a multirelease.
* This is called once per package and returns the inline plugin used for semanticRelease()
Expand Down Expand Up @@ -151,38 +181,12 @@ function createInlinePluginCreator(packages, multiContext) {
* @internal
*/
async function prepare(pluginOptions, context) {
// Get and parse manifest file contents.
const manifest = getManifest(path);

// Loop through localDeps to update dependencies/devDependencies/peerDependencies in manifest.
pkg._localDeps.forEach(d => {
// Get version of dependency.
const release = d._nextRelease || d._lastRelease;

// Cannot establish version.
if (!release || !release.version)
throw Error(`Cannot release because dependency ${d.name} has not been released`);

// Update version of dependency in manifest.
if (manifest.dependencies.hasOwnProperty(d.name)) manifest.dependencies[d.name] = release.version;
if (manifest.devDependencies.hasOwnProperty(d.name)) manifest.devDependencies[d.name] = release.version;
if (manifest.peerDependencies.hasOwnProperty(d.name))
manifest.peerDependencies[d.name] = release.version;
});

// Write package.json back out.
writeFileSync(path, JSON.stringify(manifest));
// Update pkg deps.
updateManifestDeps(pkg, path);

// Call other plugins.
await plugins.prepare(context);

// Prevent deps change rollback.
const _manifest = getManifest(path);
Object.assign(_manifest.dependencies, manifest.dependencies);
Object.assign(_manifest.devDependencies, manifest.devDependencies);
Object.assign(_manifest.peerDependencies, manifest.peerDependencies);
writeFileSync(path, JSON.stringify(_manifest));

// Package is prepared.
pkg._prepared = true;

Expand All @@ -195,6 +199,9 @@ function createInlinePluginCreator(packages, multiContext) {
// Need this because: when semanticRelease() does several `git push` simultaneously some will fail due to refs not being locked.
// (semantic-release should probably use `execa.sync()` to ensure Git operations are atomic — if they do there should be no issues with doing several releases at once).
await wait(() => todo()[0] === pkg);

// Prevent deps change rollback.
updateManifestDeps(pkg, path);
}

// These steps just passthrough to plugins.
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@
"execa": "^4.0.0",
"get-stream": "^5.1.0",
"git-log-parser": "^1.2.0",
"lodash.get": "^4.4.2",
"lodash.pairs": "^3.0.1",
"lodash.set": "^4.3.2",
"meow": "^6.0.1",
"require-in-the-middle": "^5.0.3",
"semantic-release": "^17.0.4",
"semver": "^7.1.3",
Expand All @@ -67,16 +71,16 @@
"@semantic-release/git": "^9.0.0",
"@semantic-release/github": "^7.0.4",
"@semantic-release/npm": "^7.0.3",
"codeclimate-test-reporter": "^0.5.1",
"commitlint": "^8.3.5",
"coveralls": "^3.0.9",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-prettier": "^3.1.2",
"file-url": "^3.0.0",
"husky": "^4.2.3",
"jest": "^25.1.0",
"prettier": "^1.19.1",
"coveralls": "^3.0.9",
"codeclimate-test-reporter": "^0.5.1"
"prettier": "^1.19.1"
},
"release": {
"branch": "master",
Expand Down
Loading

0 comments on commit 6de93b9

Please sign in to comment.