From 0be441d808570461daedc3fb178405dbcac54de0 Mon Sep 17 00:00:00 2001 From: Michael Cousins Date: Thu, 20 Apr 2023 10:24:49 -0400 Subject: [PATCH] Update to version 2 (#84) --- .github/workflows/ci-cd.yml | 2 + .vscode/launch.json | 27 ---- .vscode/tasks.json | 36 ------ CHANGELOG.md | 6 +- README.md | 243 ++++++++++++++++++++++-------------- bin/npm-publish.js | 2 +- package.json | 2 +- src/cli/index.ts | 2 +- 8 files changed, 157 insertions(+), 163 deletions(-) delete mode 100644 .vscode/launch.json delete mode 100644 .vscode/tasks.json diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index a9c3be9..3c10678 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -27,6 +27,7 @@ jobs: node-version: - 16 - 18 + - 20 steps: - name: Checkout source @@ -99,6 +100,7 @@ jobs: node-version: - 16 - 18 + - 20 services: verdaccio: diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 0bee668..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,27 +0,0 @@ -// VSCode Launch Configuration -// https://code.visualstudio.com/docs/editor/debugging#_launch-configurations - -// Available variables which can be used inside of strings. -// ${workspaceRoot}: the root folder of the team -// ${file}: the current opened file -// ${fileBasename}: the current opened file's basename -// ${fileDirname}: the current opened file's dirname -// ${fileExtname}: the current opened file's extension -// ${cwd}: the current working directory of the spawned process - -{ - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Run Mocha", - "program": "${workspaceRoot}/node_modules/mocha/bin/_mocha", - "args": ["--timeout=60000", "--retries=0"], - "outFiles": ["${workspaceFolder}/lib/**/*.js"], - "smartStep": true, - "skipFiles": ["/**/*.js"], - "outputCapture": "std" - } - ] -} diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 4a958bf..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,36 +0,0 @@ -// VSCode Tasks -// https://code.visualstudio.com/docs/editor/tasks - -// Available variables which can be used inside of strings. -// ${workspaceRoot}: the root folder of the team -// ${file}: the current opened file -// ${fileBasename}: the current opened file's basename -// ${fileDirname}: the current opened file's dirname -// ${fileExtname}: the current opened file's extension -// ${cwd}: the current working directory of the spawned process - -{ - "version": "2.0.0", - "command": "npm", - "tasks": [ - { - "type": "npm", - "script": "build", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": "$tsc" - }, - - { - "type": "npm", - "script": "test", - "group": { - "kind": "test", - "isDefault": true - }, - "problemMatcher": "$eslint-stylish" - } - ] -} diff --git a/CHANGELOG.md b/CHANGELOG.md index 9892fd6..f69d4f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ -# Change Log +# Change Log (Archived) + +See [releases](https://github.com/JS-DevTools/npm-publish/releases) for current change log. + +--- All notable changes will be documented in this file. NPM Publish adheres to [Semantic Versioning](http://semver.org/). diff --git a/README.md b/README.md index 3f23b70..9a417a0 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,26 @@ # Fast, easy publishing to NPM -[![Cross-Platform Compatibility](https://jstools.dev/img/badges/os-badges.svg)](https://github.com/JS-DevTools/npm-publish/actions) [![Build Status](https://github.com/JS-DevTools/npm-publish/workflows/CI-CD/badge.svg)](https://github.com/JS-DevTools/npm-publish/actions) - [![Coverage Status](https://coveralls.io/repos/github/JS-DevTools/npm-publish/badge.svg?branch=main)](https://coveralls.io/github/JS-DevTools/npm-publish) - [![npm](https://img.shields.io/npm/v/@jsdevtools/npm-publish.svg)](https://www.npmjs.com/package/@jsdevtools/npm-publish) [![License](https://img.shields.io/npm/l/@jsdevtools/npm-publish.svg)](LICENSE) [![Buy us a tree](https://img.shields.io/badge/Treeware-%F0%9F%8C%B3-lightgreen)](https://plant.treeware.earth/JS-DevTools/npm-publish) +Publish your packages to npm automatically in GitHub Actions by updating the version number. + ## Features - 🧠 **Smart**
- Only publishes if the version number in `package.json` differs from the latest on NPM + Only publishes if the version number in `package.json` differs from the latest on npm. - 🛠 **Configurable**
- Customize the version-checking behavior, the registry URL, and path of your package + Customize the version-checking behavior, the registry URL, and path of your package. - 🔐 **Secure**
- Keeps your NPM access token secret. Doesn't write it to `~/.npmrc` + Keeps your npm authentication token secret. Doesn't read from or write to `~/.npmrc`. - ⚡ **Fast**
- 100% JavaScript (which is faster than Docker) and bundled to optimize loading time + 100% JavaScript (which is faster than Docker) and bundled to optimize loading time. - 📤 **Outputs**
Exposes the old and new version numbers, and the type of change (major, minor, patch, etc.) as variables that you can use in your workflow. @@ -36,9 +35,42 @@ This package can be used three different ways: - 🖥 A [**CLI**](#command-line-interface) that you run in your terminal +## v2 Migration Guide + +The v1 to v2 upgrade brought a few notable **breaking changes**. To migrate, make the following updates: + +- The `type` output is now an empty string instead of `none` when no release occurs + ```diff + - - if: ${{ steps.publish.outputs.type != 'none' }} + + - if: ${{ steps.publish.outputs.type }} + run: echo "Version changed!" + ``` +- The `check-version` and `greater-version-only` options have been removed and replaced with `strategy`. + - Use `strategy: all` (default) to publish all versions that do not yet exist in the registry. + ```diff + with: + token: ${{ secrets.NPM_TOKEN }} + - check-version: true + - greater-version-only: false + + strategy: all + ``` + - Use `strategy: upgrade` to only publish versions that upgrade the selected tag. + ```diff + with: + token: ${{ secrets.NPM_TOKEN }} + - check-version: true + - greater-version-only: true + + strategy: upgrade + ``` + - `check-version: false` has been removed. You don't need this action if you're not checking already published versions; use `npm` directly, instead. + +See the [change log][] for more details and other changes in the v2 release. + +[change log]: https://github.com/JS-DevTools/npm-publish/releases + ## GitHub Action -To use the GitHub Action, you'll need to add it as a step in your [Workflow file](https://help.github.com/en/actions/automating-your-workflow-with-github-actions). By default, the only thing you need to do is set the `token` parameter to your [NPM auth token](https://docs.npmjs.com/creating-and-viewing-authentication-tokens). +To use the GitHub Action, you'll need to add it as a step in your [workflow file][]. By default, the only thing you need to do is set the `token` parameter to your [npm authentication token][]. ```yaml on: push @@ -53,123 +85,136 @@ jobs: node-version: 18 - run: npm ci - run: npm test - - uses: JS-DevTools/npm-publish@v1 + - uses: JS-DevTools/npm-publish@v2 with: token: ${{ secrets.NPM_TOKEN }} ``` -## Input Parameters +[workflow file]: https://help.github.com/en/actions/automating-your-workflow-with-github-actions +[npm authentication token]: https://docs.npmjs.com/creating-and-viewing-authentication-tokens + +### Usage -You can set any or all of the following input parameters: +You can set any or all of the following input parameters using `with`: -| Name | Type | Default | Description | -| ---------------------- | ------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| `token` | string | **required** | The NPM auth token to use for publishing | -| `registry` | string | https://registry.npmjs.org/ | The NPM registry URL to use | -| `package` | string | ./package.json | The path of your package.json file | -| `tag` | string | "latest" | The tag to publish to. This allows people to install the package using `npm install @`. | -| `access` | string | "public" for non-scoped packages. "restricted" for scoped packages. | Determines whether the published package should be publicly visible, or restricted to members of your NPM organization. | -| `dry-run` | boolean | false | Run NPM publish with the `--dry-run` flag to prevent publication | -| `check-version` | boolean | true | Only publish to NPM if the version number in `package.json` differs from the latest on NPM | -| `greater-version-only` | boolean | false | Only publish to NPM if the version number in `package.json` is greater than the latest on NPM | +| Name | Type | Default | Description | +| ---------- | ---------------------- | ----------------------------- | ----------------------------------------------------------------------------- | +| `token` | string | **required** | Authentication token to use with the configured registry. | +| `registry` | string | `https://registry.npmjs.org/` | Registry URL to use. | +| `package` | string | Current working directory | Path to a package directory, a `package.json`, or a packed `.tgz` to publish | +| `tag` | string | `latest` | [Distribution tag][npm-tag] to publish to. | +| `access` | `public`, `restricted` | [npm defaults][npm-access] | Whether the package should be publicly visible or restricted. | +| `strategy` | `all`, `upgrade` | `all` | Use `all` to publish all unique versions, `upgrade` for only semver upgrades. | +| `dry-run` | boolean | `false` | Run `npm publish` with the `--dry-run` flag to prevent publication. | -## Output Variables +[npm-tag]: https://docs.npmjs.com/cli/v9/commands/npm-publish#tag +[npm-access]: https://docs.npmjs.com/cli/v9/commands/npm-publish#access + +### Output npm-publish exposes some output variables, which you can use in later steps of your workflow. To access the output variables, you'll need to set an `id` for the npm-publish step. ```yaml steps: - id: publish - uses: JS-DevTools/npm-publish@v1 + uses: JS-DevTools/npm-publish@v2 with: token: ${{ secrets.NPM_TOKEN }} - - if: steps.publish.outputs.type != 'none' + - if: ${{ steps.publish.outputs.type }} run: | - echo "Version changed: ${{ steps.publish.outputs.old-version }} => ${{ steps.publish.outputs.version }}" + echo "Version changed!" ``` -| Variable | Type | Description | -| ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `type` | string | The type of version change that occurred ("major", "minor", "patch", etc.). If there was no version change, then type will be "none". If `greater-version-only` is set and the version is lower, then type will be "lower". | -| `version` | string | The version that was published | -| `old-version` | string | The version number that was previously published to NPM | -| `tag` | string | The tag that the package was published to. | -| `access` | string | Indicates whether the published package is publicly visible or restricted to members of your NPM organization. | -| `dry-run` | boolean | Indicates whether NPM was run in "dry run" mode | +| Name | Type | Description | +| ------------- | ------- | ------------------------------------------------------------------------------------------------------------- | +| `id` | string | Package identifier of the release: `${name}@${version}` or empty if no release. | +| `type` | string | [Semver release type][], `initial` if first release, `different` if other change, or empty if no release. | +| `name` | string | Name of the package. | +| `version` | string | Version of the package. | +| `old-version` | string | Previously published version on `tag` or empty if no previous version on tag. | +| `tag` | string | [Distribution tag][npm-tag] the package was published to. | +| `access` | string | [Access level][npm-access] the package was published with, or `default` if scoped-package defaults were used. | +| `dry-run` | boolean | Whether `npm publish` was run in "dry run" mode. | + +[semver release type]: https://github.com/npm/node-semver#release_types ## JavaScript Function -To use npm-package in your JavaScript code, you'll need to install it using [NPM](https://docs.npmjs.com/about-npm/): +To use npm-package in your JavaScript code, you'll need to install it using [npm][] or other package manager of choice: ```bash -npm install @jsdevtools/npm-publish +npm install --save-dev @jsdevtools/npm-publish ``` You can then import it and use it in your code like this: ```javascript -const npmPublish = require("@jsdevtools/npm-publish"); +import { npmPublish } from "@jsdevtools/npm-publish"; // Run npm-publish with all defaults -await npmPublish(); +await npmPublish({ token: "YOUR_NPM_AUTH_TOKEN_HERE" }); +``` + +[npm]: https://docs.npmjs.com/about-npm/ -// Run npm-publish with options -await npmPublish({ - package: "./path/to/package.json", - token: "YOUR_NPM_AUTH_TOKEN_HERE", -}); +### Usage + +As shown in the example above, you should pass an options object to the `npmPublish` function. In TypeScript, the `Options` interface is available as an import. + +```ts +import type { Options } from "@jsdevtools/npm-publish"; ``` -### Options +| Name | Type | Default | Description | +| -------------------- | ---------------------- | ----------------------------- | ----------------------------------------------------------------------------- | +| `token` | string | **required** | Authentication token to use with the configured registry. | +| `registry` | string, `URL` | `https://registry.npmjs.org/` | Registry URL to use. | +| `package` | string | Current working directory | Path to a package directory, a `package.json`, or a packed `.tgz` to publish | +| `tag` | string | `latest` | [Distribution tag][npm-tag] to publish to. | +| `access` | `public`, `restricted` | [npm defaults][npm-access] | Whether the package should be publicly visible or restricted. | +| `strategy` | `all`, `upgrade` | `all` | Use `all` to publish all unique versions, `upgrade` for only semver upgrades. | +| `dryRun` | boolean | `false` | Run `npm publish` with the `--dry-run` flag to prevent publication. | +| `logger` | object | `undefined` | Logging interface with `debug`, `info`, and `error` log methods. | +| `temporaryDirectory` | string | `os.tmpdir()` | Temporary directory to hold a generated `.npmrc` file | -As shown in the example above, you can pass options to the `npmPublish()` function. Here are the available options: - -| Name | Type | Default | Description | -| -------------------- | -------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `token` | string | NPM's default credentials | The NPM auth token to use for publishing. If not set, then NPM will | -| `registry` | string | https://registry.npmjs.org/ | The NPM registry URL to use | -| `package` | string | ./package.json | The path of your package.json file | -| `tag` | string | "latest" | The tag to publish to. This allows people to install the package using `npm install @`. | -| `access` | string | "public" for non-scoped packages. "restricted" for scoped packages. | Determines whether the published package should be publicly visible, or restricted to members of your NPM organization. | -| `dryRun` | boolean | false | Run NPM publish with the `--dry-run` flag to prevent publication | -| `checkVersion` | boolean | true | Only publish to NPM if the version number in `package.json` differs from the latest on NPM | -| `greaterVersionOnly` | boolean | false | Only publish to NPM if the version number in `package.json` is greater then the latest on NPM | -| `quiet` | boolean | false | Suppress console output from NPM and npm-publish | -| `debug` | function | no-op | A function to log debug messages. You can set this to a custom function to receive debug messages, or just set it to `console.debug` to print debug messages to the console. | - -### Return Value - -The `npmPublish()` function asynchronously returns an object with the following properties: - -| Name | Type | Description | -| ------------ | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `type` | string | The type of version change that occurred ("major", "minor", "patch", etc.) If there was no version change, then the the type is "none". If `greater-version-only` is set and the version is lower, then type will be "lower". | -| `package` | string | The name of the NPM package that was published | -| `version` | string | The version number that was published | -| `oldVersion` | string | The version number that was previously published to NPM | -| `tag` | string | The tag that the package was published to. | -| `access` | string | Indicates whether the published package is publicly visible or restricted to members of your NPM organization. | -| `dryRun` | boolean | Indicates whether NPM was run in "dry run" mode | +### Output + +The `npmPublish()` function returns a promise of a `Results` object. In TypeScript, the `Results` interface is available as an import. + +```ts +import type { Results } from "@jsdevtools/npm-publish"; +``` + +| Name | Type | Description | +| ------------ | --------------- | --------------------------------------------------------------------------------------------------------------- | +| `id` | Optional string | Package identifier of the release: `${name}@${version}` or `undefined` if no release. | +| `type` | Optional string | [Semver release type][], `initial` if first release, `different` if other change, or `undefined` if no release. | +| `name` | string | Name of the package. | +| `version` | string | Version of the package. | +| `oldVersion` | Optional string | Previously published version on `tag` or `undefined` if no previous version. | +| `tag` | string | [Distribution tag][npm-tag] that the package was published to. | +| `access` | Optional string | [Access level][npm-access] the package was published with, or `undefined` if scoped-package defaults were used. | +| `dryRun` | boolean | Whether `npm publish` was run in "dry run" mode. | ## Command Line Interface -To use npm-package from as a command-line tool in your terminal, you'll need to install it globally using [NPM](https://docs.npmjs.com/about-npm/): +You can also use `npm-publish` as a command-line tool in your terminal. ```bash -npm install -g @jsdevtools/npm-publish +npm install --save-dev @jsdevtools/npm-publish ``` -You can then use it in your terminal or in Bash scripts. You can call it without any arguments, and it will publish the current directory using NPM's default credentials. +You can then use it in your terminal or in `npm run` scripts. ```bash -npm-publish +npx npm-publish --token YOUR_NPM_AUTH_TOKEN_HERE ``` -Or you can call it with arguments to explicitly set the NPM auth token, registry, package path, etc. +You can customize your call with options to change the registry, package, etc. ```bash -npm-publish --token=YOUR_NPM_AUTH_TOKEN_HERE ./path/to/package.json +npm-publish --token YOUR_NPM_AUTH_TOKEN_HERE --registry http://example.com ./path/to/package ``` ### Options @@ -177,36 +222,42 @@ npm-publish --token=YOUR_NPM_AUTH_TOKEN_HERE ./path/to/package.json Run `npm-publish --help` to see the full list of options available. ``` -> npm-publish --help +Usage: + + npm-publish [package] + +Arguments: -Usage: npm-publish [options] [package_path] + package The path to the package to publish. + May be a directory, package.json, or .tgz file. + Defaults to the package in the current directory. -options: - --token The NPM access token to use when publishing +Options: - --registry The NPM registry URL to use + --token (Required) npm authentication token. - --tag The tag to publish to. Allows the package to be installed - using "npm install @" + --registry Registry to read from and write to. + Defaults to "https://registry.npmjs.org/". - --access "public" = The package will be publicly visible. - "restricted" = The package will only be visible to members - of your NPM organization. + --tag The distribution tag to check against and publish to. + Defaults to "latest". - --dry-run Don't actually publish to NPM, but report what would have - been published + --access Package access, may be "public" or "restricted". + See documentation for details. - --debug, -d Enable debug mode, with increased logging + --strategy Publish strategy, may be "all" or "upgrade". + Defaults to "all", see documentation for details. - --quiet, -q Suppress unnecessary output + --dry-run Do not actually publish anything. + --quiet Only print errors. + --debug Print debug logs. - --version, -v Print the version number + -v, --version Print the version number. + -h --help Show usage text. - --help, -h Show help +Examples: -package_path The absolute or relative path of the NPM package to publish. - Can be a directory path, or the path of a package.json file. - Defaults to the current directory. + $ npm-publish --token abc123 ./my-package ``` ## License diff --git a/bin/npm-publish.js b/bin/npm-publish.js index e9c11da..70de1f7 100644 --- a/bin/npm-publish.js +++ b/bin/npm-publish.js @@ -7,6 +7,6 @@ const { version } = require("../package.json"); const { main } = require("../lib/cli/index.js"); main(process.argv.slice(2), version).catch((error) => { - console.log(error); + console.error(error); process.exitCode = 1; }); diff --git a/package.json b/package.json index 5b50a26..91b2de6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@jsdevtools/npm-publish", "description": "Fast, easy publishing to NPM", - "version": "1.4.3", + "version": "2.0.0", "keywords": [ "github-action", "npm", diff --git a/src/cli/index.ts b/src/cli/index.ts index 36671dc..cda1098 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -9,7 +9,7 @@ Usage: Arguments: package The path to the package to publish. - May be a directory or package.json file. + May be a directory, package.json, or .tgz file. Defaults to the package in the current directory. Options: