Skip to content

Commit

Permalink
feat(laverna): automatic support for CI
Browse files Browse the repository at this point in the history
If the `CI` env var is `true`, `--yes` will be the default behavior so that it does not attempt to read from STDIN.
  • Loading branch information
boneskull committed Mar 12, 2024
1 parent cfe3161 commit 7358d2a
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 22 deletions.
31 changes: 19 additions & 12 deletions packages/laverna/README.md
Expand Up @@ -4,29 +4,33 @@
If you're familiar with [lerna](https://lerna.js.org), **Laverna** does this: `lerna publish from-package`.

If you're unfamiliar with it: **Laverna** publishes all workspaces that haven't yet been published.
If you're unfamiliar with it: **Laverna** publishes all workspacess wherein the _current_ version hasn't yet been published.

## Features

**Laverna** is a thin wrapper around `npm publish` which:

- Invokes `npm publish` for all workspaces _that haven't yet been published_
- Handles new packages (via a flag)
- Invokes `npm publish` on _all_ workspaces _where the current version has not yet been published_
- Publishes new packages via flag
- Ignores private packages
- Requires a confirmation (by default)
- Requires confirmation (by default)
- Prints all output from `npm publish`, including the output of `npm pack`, to enable review prior to confirmation
- Provides a "dry-run" mode
- Prints all output from `npm publish`, including the output of `npm pack`, to enable review

**Laverna**'s scope is intentionally limited to the above use-case.

## Non-Features

Perhaps more importantly, **Laverna**:

- Builds nothing
- Bumps no versions
- Does not write to `package.json`
- Runs no user-defined scripts
- Retains no state nor cache
- Does not write to `package.json` or lockfiles
- Does not interact with `git` (no tags, no commits, no pushes)
- Does not interact with GitHub (no releases)
- Does not cache anything
- Avails no whims

## Supported Environments

Expand All @@ -46,16 +50,16 @@ npm install @lavamoat/laverna -D
```plain
laverna [options..]
Publish multiple workspaces (that's all)
"Publish multiple workspaces (that's all)"
Options:
--dryRun - Enable dry-run mode
--root=<path> - Path to workspace root (default: current working dir)
--newPkg=<name> - Workspace <name> has never been published (repeatable)
--yes/-y - Skip confirmation prompt
--newPkg=<name> - Workspace <name> should be treated as a new package (repeatable)
--yes/-y - Skip confirmation prompt (default: false; true in CI)
Problems? Visit https://github.com/LavaMoat/lavamoat/issues
Problems? Visit https://github.com/LavaMoat/LavaMoat/issues
```

## Examples
Expand All @@ -78,7 +82,10 @@ If you're publishing a package in a new workspace, you might:

### Automating Publishes

You'll need to figure out how to add `--newPkg` to your CI/CD pipeline. Otherwise, use the `--yes` flag when invoking `laverna`.
If the `CI` environment variable is present, `laverna` will skip the confirmation prompt before final publish (i.e., `--yes` defaults to `true`).

> [!WARNING]
> Publishing via CI can bypass 2FA protections. Use at your own risk!
## API

Expand Down
4 changes: 2 additions & 2 deletions packages/laverna/package.json
Expand Up @@ -4,12 +4,12 @@
"description": "Publish multiple workspaces (that's all)",
"repository": {
"type": "git",
"url": "git+https://github.com/LavaMoat/lavamoat.git",
"url": "git+https://github.com/LavaMoat/LavaMoat.git",
"directory": "packages/laverna"
},
"homepage": "https://github.com/LavaMoat/LavaMoat/blob/main/packages/laverna/README.md",
"bugs": {
"url": "https://github.com/LavaMoat/lavamoat/issues"
"url": "https://github.com/LavaMoat/LavaMoat/issues"
},
"author": "boneskull",
"license": "MIT",
Expand Down
18 changes: 10 additions & 8 deletions packages/laverna/src/cli.js
Expand Up @@ -3,7 +3,7 @@
/* eslint-disable n/shebang */
// @ts-check

const { bold, magenta, gray, italic } = require('kleur')
const { bold, magenta, gray, italic, cyan, underline } = require('kleur')
const util = require('node:util')
const { Laverna } = require('./laverna')
const { ERR } = require('./log-symbols')
Expand Down Expand Up @@ -72,18 +72,18 @@ function main() {
// this should be the only place we write to stdout unless we
// want to start outputting JSON
console.log(`
${bold('laverna')} [options..]
${cyan(bold('laverna'))} ${cyan('[options..]')}
${italic(description)}
"${description}"
Options:
--dryRun - Enable dry-run mode
--root=<path> - Path to workspace root (default: current working dir)
--newPkg=<name> - Workspace <name> has never been published (repeatable)
--yes/-y - Skip confirmation prompt
${bold('--dryRun')} - Enable dry-run mode
${bold('--root=<path>')} - Path to workspace root (default: current working dir)
${bold('--newPkg=<name>')} - Workspace <name> should be treated as a new package (repeatable)
${bold('--yes/-y')} - Skip confirmation prompt (default: false; true ${italic('in CI')})
Problems? Visit ${bugs.url}
Problems? Visit ${underline(bugs.url)}
`)
} else {
Expand All @@ -92,6 +92,8 @@ function main() {
opts.newPkg = [
...new Set([...(opts.newPkg ?? []), ...(opts['new-pkg'] ?? [])]),
]
// must be true in CI; --yes=false is not a thing
opts.yes = Boolean(process.env.CI) || opts.yes

console.error(`📦 ${bold(magenta(name)) + gray('@') + magenta(version)}\n`)
const laverna = new Laverna(opts)
Expand Down

0 comments on commit 7358d2a

Please sign in to comment.