Git Product home page Git Product logo

nlm's Introduction

GitHub nlm-coverage nlm-version nlm-node nlm-github

nlm

A tool for automating the release of libraries in the spirit of semantic-release. For a list of supported commit types and their affect on the version, see CONTRIBUTING.md.

Highlights

  • Automatically tags pull requests with semver-{patch,minor,major,none} based on the commit history
  • All information is also part of the git history
  • Smart CHANGELOG.md generator that incorporates pull request data
  • Adds license headers for JavaScript and CoffeeScript files

Getting Started

Prerequisites

  1. A GitHub access token with repo scope. This is required for creating version commits, releases, and tagging issues. GitHub has instructions for creating an access token.
  2. A valid repository field in your package.json. E.g. https://github.mycorp.net/myorg/repo.git or https://github.com/myorg/repo.git.
  3. The repository field should point to an existing project on GitHub.

Install nlm

  1. Run npm install --save-dev nlm.
  2. Set publishConfig.registry in your package.json if you haven't already.
  3. Set your posttest script in package.json to nlm verify.

Setting up CI

nlm will automatically look for well-known environment variables during CI builds like CI=true, BRANCH=branch-name, etc. It should work out-of-the-box for Travis, DotCI, and CircleCI.

For GitHub and npm interactions to work, it requires the following additional environment variables:

  • GH_TOKEN: The access token from above.
  • NPM_TOKEN: An npm access token. You can find this in ~/.npmrc as _authToken.

For registries that don't support _authToken, it's possible to configure NPM_USERNAME, NPM_EMAIL, and NPM_PASSWORD_BASE64 instead. Those values can be found in your ~/.npmrc as username, email, and _password.

All tokens and passwords should be set up as encrypted environment variables.

Travis

For Travis, you can follow the official Travis docs:

travis encrypt GH_TOKEN=your_github_token --add env

If you want to publish from CI, you can either use the official Travis feature or nlm itself. The latter gives you support for managing different dist-tags based on branches.

If you want to use nlm to publish, you'll have to add NPM_TOKEN:

travis encrypt NPM_TOKEN=your_npm_token --add env

CircleCI

You may reference the official circleci docs on setting up environment variables using the admin console.

nlm will look for CIRCLE_BRANCH and CIRCLE_PULL_REQUEST environment variables to operate correctly.

To enable publishing, you may add a check in your run steps for a branch and build you want to release on:

- run: |
    if [ "$CIRCLE_BRANCH" == "master" ] && [ "$CIRCLE_STAGE" == "test-3" ]; then
          echo "Running nlm release";
          npx nlm release;
    else
          echo "Not running nlm release!";
    fi

GitHub Actions

Running nlm with GitHub Actions requires small modifications to the default GH actions templates, as well as setting up the NPM_TOKEN secret.

Workflow: Run CI

The template below is almost the same as the default one. The only difference is that on.push: is left empty, so the action will trigger on every push on every branch.

Click to open: workflows/node.js.yml

# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: Node.js CI

on:
  push: # leave events empty so they triggers in every branch

jobs:
  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [10.x, 12.x, 14.x]

    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v2
      with:
        node-version: ${{ matrix.node-version }}
    - run: npm ci
    - run: npm run build --if-present
    - run: npm test

NOTE: With the setup above, If you are using nlm verify in the package posttest script, verify will state that the changes are none. You can either ignore this, or set fetch-depth: 0 in the checkout step to fetch the full git history.

- uses: actions/checkout@v2
    with:
      fetch-depth: 0
Workflow: Tagging PRs

Tagging the PR with nlm requires

  • the pull_request event, so a PR id can be determined
  • GH_TOKEN to be passed to the environment
    env:
      GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
  • the entire git history. Set fetch-depth: 0 to overwrite the default in actions/checkout@v2
    # see https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches
    - uses: actions/checkout@v2
      with:
        fetch-depth: 0
Click to open: workflows/tag-pr.yml

name: NLM

on:
  pull_request:

jobs:
  tag:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0  # necessary to get full commit history
      - name: Use Node.js
        uses: actions/setup-node@v2
        with:
          node-version: 14
      - run: npm ci
      - run: npx nlm verify
        env:
          GH_TOKEN: ${{secrets.GITHUB_TOKEN}}

Workflow: Releasing with nlm

To have nlm release on merge to the default branch or other branches, you need to

  • set the trigger to the push event
    push:
      branches: [ main, v10.x ] # branches to release from
  • pass the GH_TOKEN and NPM_TOKEN to the env
    - run: npx nlm release  # nlm release command
      env:
      GH_TOKEN: ${{secrets.GITHUB_TOKEN}}
      NPM_TOKEN: ${{secrets.NPM_TOKEN}}
  • the entire git history. Set fetch-depth: 0 to overwrite the default in actions/checkout@v2
    # see https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches
    - uses: actions/checkout@v2
      with:
        fetch-depth: 0
Click to open: workflows/npm-publish.yml

name: Publish to NPM

on:
  push:
    branches: [ main ] # default branch

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
        with:
          node-version: 14
      - run: npm ci
      - run: npm test

  publish-npm:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0 # necessary to get full commit history
      - uses: actions/setup-node@v2
        with:
          node-version: 14
          
      - run: npm ci
      - run: npx nlm release  # nlm release command
        env:
          GH_TOKEN: ${{secrets.GITHUB_TOKEN}} # pass GH_TOKEN
          NPM_TOKEN: ${{secrets.NPM_TOKEN}}   # pass NPM_TOKEN.

Creating Secrets

The above templates show two secrets passed to the env environment. By default, the GITHUB_TOKEN secret exists in every repo and doesn't need to be set to the repository or org secrets. The NPM_TOKEN on the contrary, needs to set to the org or repository secrets. It becomes available to the workflow on the secrets object

See Official GitHub Documentation on how to set a secret.

Configuration

Most nlm configuration happens via native npm options in package.json:

  • repository: This field is parsed to detect GitHub API baseUrl and repository name. nlm supports both public GitHub and GitHub Enterprise instances. For GitHub Enterprise, it assumes the API to be at https://<hostname>/api/v3.
  • files: By default nlm will add license headers to everything listed here.

In most cases these settings are enough to make nlm do the right thing. For more customization, you can use .nlmrc or an nlm section in package.json:

  • channels: A map of branch name to npm dist-tag. When publishing, this will determine what will be published and how it's tagged. By default, there's two entries in this map: { master: 'latest', main: 'latest' }. Which means that publishing from masterormainupdates thelatest` tag and publishing from any other branch does nothing.
  • hooks: A map of hook names to shell commands. When executing any of the commands listed below some of these hooks will get triggered. The available hooks are:
Hook Description
prepare Called when the release is about to be prepared. This is before updating files such as
package.json, CHANGELOG.md and pushing a commit. It provides a reference to the next version number
via the environment variable NLM_NEXT_VERSION.
interface NlmOptions {
  acceptInvalidCommits?: boolean;
  changelog: { 
    omit?: string[], 
    verbose?: boolean 
  };
  deprecated?: boolean;
  emoji?: {
    skip?: boolean
    set?: {[type: string]: string}
  };
  badges?: {
    enable?: boolean | true
    npm : {
      enable?: boolean | true, 
      color?: string | 'blue'
    }
    meta: {
      enable?: boolean | true,
      color?: string | 'F4D03F', 
      url?: boolean | true
    }
    coverage: {
      enable?: boolean | true, 
      thresholds?: [number, string][] | [[95, 'success'], [90, 'green'], [75, 'yellow'], [50, 'critical']]
    }
  }
  license?: { 
    files?: string[], 
    exclude?: string[] 
  }
}
  • license:
    • files: List of files and/or directories to add license headers to.
    • exclude: List of files to exclude that would otherwise be included. nlm will always exclude anything in node_modules.
  • acceptInvalidCommits: Accept commit messages even if they can't be parsed. It's highly discouraged to use this option. In this mode any commit with an invalid commit message will be treated as "semver-major".
  • deprecated: String (may be empty) describing reason this package has been deprecated. To deprecate a package, set it to a descriptive reason. To "un-deprecate" a package, set it to an empty string (can then be later deleted).
  • changelog:
    • omit: Array of types, which will be omitted from the changelog.
    • verbose: Display PR's commits. Default: false
  • emoji: Configure changelog emoji setting logic
    • skip: deactivates emoji in changelog. Default: null
    • set: Custom emojis map, which will overwrite the default one
Example for emoji
{
  "nlm": {
    "emoji": { 
      "set": {
        "refactor": "๐Ÿ”ฅ" // will overwrite the existing setting for "refactor" type
      }
    }
  } 
}   

The default emojis for the commit types are:

{

  "breaking": "๐Ÿ’ฅ",
  "feat": "๐Ÿš€",
  "fix": "๐Ÿ›",
  "perf": "โšก",
  "refactor": "๐Ÿ“ฆ๏ธ",
  "revert": "โ†ฉ๏ธ",
  "docs": "๐Ÿ“",
  "style": "๐Ÿ’…",
  
  // internal types
  "dep": "๐Ÿ”ผ",     // will be set when dependencies are found in PR commit subject
  "internal": "๐Ÿก", // will be set for types: "chore", "build", "test", "ci" or commits without type

}

badges

Sets shield.io badges to the README.md

{
  "nlm": {
    "badges": {
      "enable": true,
      "npm": {
        "enable": false,
        "color": "yellow"
      },
      "coverage": {
        "enable": true,
        "thresholds": [[75, "blue"], [50, "yellow"]]
      },
      "meta": {
        "enable": true,
        "url": false,
        "color": "CCC"
      }
    }
  } 
}   
  • badges.enable: enables setting badges to the README. Default: true
section: badges.npm

set package version and engine information

  • badges.npm.enable: enables setting npm related badges. Default: true
  • badges.npm.color: custom color set as HEX value (without #) or color literals listed on shields.io. Default: blue
section: badges.coverage

set coverage information badge given coverage/coverage-summary.json exists

  • badges.coverageenable: enables coverage badge. Default: true
  • badges.coveragethresholds: List of threshold/color ranges. Default: [95, 'success'], [90, 'green'], [75, 'yellow'], [50, 'critical']
section: badges.meta

adds badges for entries in bugs section. Can detect JIRA and Slack urls.

  • badges.metaenable: enables meta badges. Default: true
  • badges.metaurl: makes meta badges clickable. Default: true
  • badges.metacolor: custom color set as HEX value (without #) or color literals listed on shields.io. Default: F4D03F

If there's no file named LICENSE in the repository, nlm won't attempt to add the headers.

Commands

nlm verify

Intended use: posttest script for matrix builds.

Verify that the current state is valid and could be released. Will also add license headers where they are missing.

  1. Add missing license headers.
  2. Verify that the checkout is clean.
  3. Collect change log items and determine what kind of change it is.

nlm release

Intended use: deploy script, or posttest script if not running matrix builds.

Verify that the current state is valid and could be released. Will also add license headers where they are missing.

  1. Everything nlm verify does.
  2. If hooks#prepare is present in the nlm section of the package.json, the shell command defined by the hook will be executed.
  3. If there are unreleased changes:
  4. Create a new CHANGELOG entry and update package.json#version.
  5. Commit and tag the release.
  6. Push the tag, and the release branch (e.g. master).
  7. Create a GitHub release.
  8. Publish the package to npm or update dist-tag if required.

By default nlm release will not do anything unless it's running on CI. You can force a release by running nlm release --commit.

Note: If your current version is below 1.0.0, nlm will always release 1.0.0. The semantics of versions below 1.0.0 can be tricky and nlm tries to not make any assumptions about how people might interpret those version ranges.

nlm changelog

Preview the changelog that would be generated by the commits between the last version tag and the current HEAD. If there are no unreleased commits, the output will be empty.

nlm's People

Contributors

aotarola avatar daniel-beard avatar dbushong avatar dependabot[bot] avatar i-tier-bot avatar jkrems avatar johan avatar markowsiak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nlm's Issues

Bug: tagging PRs should only look at the PR commits

Bug:

When a PR is merged and npm publish fails, a new PR will consider the commits from the last release tag instead of the PR commits to determine the semver tag.

Expected behavior:

  • The tagging logic should only consider PR commits.

add tests for commands

Many of the steps are tested, but the commands themselves (release, verify, changelog) have non-trivial bits of code also, as mentioned in #27

Strip prefixes from PR titles

When opening a PR from a single commit, Github uses the commit message as the default title. This looks slightly ugly in the change log. We could strip the prefix so that a PR like fix: Stops crashing on invalid input would show up as Stops crashing on invalid input. The commit would still be listed below with the prefix.

Changelog can get confused by "foreign" PRs

When merging in commits from other repos, especially ones that merged PRs, nlm gets confused. It tries to load PR meta data from the current repo that might not contain a PR with the same number (or an entirely unrelated one). It should ignore non-existing PRs or ones where the commits do not match up.

Tags not being created/pushed when releasing

I have a slightly unusual situation: I'm using nlm for an app, not a library. I don't use CI for the app, so I run nlm release --commit as part of the deploy script.

When I run this, it successfully creates a release in GitHub and a commit with the version number. However, it doesn't create a Git tag with vX.X.X. I've checked both on my machine and on GitHub, and the tag wasn't created in either place.

As a result, on my next deploy, NLM fails, because it can't find a git tag with the version number currently in package.json.

Note that I haven't configured CI at all, since I'm not using it. I'm not sure if this is relevant to the problem, though.

Any ideas?

PR labels should only consider PR commits

When the base branch contains unreleased commits, the current logic includes them when determining the semver implications of a PR. Instead it should only look at the version range from the base branch to the head of the checkout.

Support for emoji prefixes

Abbreviations are way too easy to understand. I propose allowing the use of emoji for tagging the kind of change:

๐Ÿ’„ fix lint error (style)
๐Ÿ’… fix lint error (style, alternate proposal)
๐Ÿš€ add new feature (feat)
โž• add new feature (feat, alternate proposal)
๐Ÿ› stop crashing when using the new feature (fix)
๐Ÿค“ document the new feature (docs)
๐Ÿ“š document the new feature (docs, alternate proposal)
๐Ÿšง bump dependencies (chore)
๐Ÿ— bump dependencies (chore, alternate proposal)
๐Ÿ‘ฉโ€๐Ÿ”ฌ test a new edge case (test)
โš—๏ธ test a new edge case (test, alternate proposal)
โšก๏ธ improve perf of thing (perf)
โฑ improve perf of thing (perf, alternate proposal)
๐Ÿ”€ move stuff around (refactor)

Unfortunately the broom emoji isn't out yet. That would've been a great one for chore as well.

Escape html in github release body

Things like "Enable " should be escaped because otherwise Github will just remove the text. Markdown should be enough.

Maybe it would be enough to prefix every < with \..?

Commits shouldn't be listed for PRs

It's always possible to open the PR link and see what commits were contained in the PR. It might be nice to mention the merge commit somehow so that it can be used without the Github UI.

Add generated badges to README.md on publish

Besides generating the changelog on publish, it would be great to generate / update badges in the readme. This would be handy esp for internal usage of nlm

Tasks:

  • use https://shields.io/ to build badges https://img.shields.io/badge/<LABEL>-<MESSAGE>-<COLOR>
  • add opt-out config
  • add badges for:
    • code coverage e.g nyc
    • github stats: contributing, issues, version, engine information (node)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.