GithubHelp home page GithubHelp logo

isabella232 / lerna-travis-demo Goto Github PK

View Code? Open in Web Editor NEW

This project forked from fezvrasta/lerna-travis-demo

0.0 0.0 0.0 93 KB

Just a simple monorepo with a publish-from-travis setup and chan support.

JavaScript 100.00%

lerna-travis-demo's Introduction

Playing with chan on monorepos

Build Status

⚠️ This is a demo project showcasing: lerna + chan + travis + npm

Okay, let's say you have a monorepo and you are happy with it. Everything seems to be OK but one day your monorepo open source project starts to be used by someone else so you say let's automatize things.

Probably at this point, some steps are manually controlled, like publish for example. At the same time, you are a cool person and make use of travis for CI.

So you say to yourself, what about CDing? Can I release a new lerna-managed package version from Travis? Is that even possible?

Ok, lets figure it out. Oh! But one more thing. I've mentioned that you are cool person, and that means your project will maintain a CHANGELOG.md file. OMG, that is so cool. Luckily for us, the GEUT team is here to help us, they have built this little tool called chan which can be used to easily create and maintain a changelog file based on keepachangelog directives. Which in the end, results in a human readable list of changes about the progress of our project.

How?

I've found 2 ways to solve this problem:

A. Fully "automatic"
B. Half & Half

Let's explore them.

A - Fully Automatic

It's really cool to automate everything but there is a thing to solve, "how to tell travis what should be the next semver bump?". Anyway, this workflow can still be useuful for staging/dev scenarios where you can publish to an internal registry for example or something like that.

Setup

The important bits of your .travis.yml:

language: node_js
node_js:
  - "10"
cache:
  yarn: true
  directories:
    - "node_modules"
before_install:
  - curl -o- -L https://yarnpkg.com/install.sh | bash -s
  - export PATH="$HOME/.yarn/bin:$PATH"
before_script:
  - yarn run lerna run prepublish
script:
  - yarn test
before_deploy:
  - git config --global user.email ${GITHUB_EMAIL}
  - git config --global user.name ${GITHUB_USER}
  - git remote set-url origin "https://${GITHUB_TOKEN}@github.com/YOUR/PROJECT.git" > /dev/null 2>&1
  - git checkout release
  - echo "//registry.npmjs.org/:_authToken=\${NPM_TOKEN}" >> $HOME/.npmrc 2> /dev/null
deploy:
  provider: script
  script: "yarn run lerna:publish"
  skip_cleanup: true
  on:
    node: "10"
    branch: release

Using this config you can deploy (for our purposes, deploy == release) only when a merge happens to a branch called "release". So as you may figure it out, on a workflow like this you will end up having a parallel release branch. This branch will be used to track our releases.

Usage

When you want to trigger a release you should create a PR from master to release. When the PR is approved and it's merged this will signal the condition and travis will execute the deploy part. Finally, when the PR got merged you should create another PR from release back to master to get the changelog changes and version bumps.

Requirements

Since we are pushing and publising from travis, we will need to pass: a GITHUB_EMAIL (this can be [email protected]), GITHUB_USER (Deployment Bot), GITHUB_TOKEN and finally a NPM_TOKEN.

Changelog

Our deploy script is the following: "yarn run lerna:publish". If we take a look to our package.json this is what we are running:

"lerna:publish": "lerna publish prerelease --yes --npm-client yarn --preid beta --npm-tag beta"

This alone wont do nothing changelog-related. Since we are using chan we can use one of the npm lifecycle hooks, in this case will be the postversion hook and it will look like this:

"postversion": "chan release --group-changes $(node -p -e \"require('./lerna.json').version\") && git add CHANGELOG.md && git commit -m \"Update: changelog\""

One thing, we are using postversion and not just the version hook due to the missing npm env var $npm_package_version. On the other side, it makes sense to get the upcoming version directly from the lerna.json if we are using the fixed (default) mode.

Chan works great on monorepos thanks to a new option for releases, called --group-changes with in combination of the commit level option -g package help us to separate and organize our changes.

B - Half & Half

The previous strategy has a clear drawback, you can't specify the next semver and it is logical, this is a manual part of the process (at least for the time being 😉). But, we have another option. Lerna from version 3 splitted out the version from the publish. In fact they are now 2 different commands. Having this in mind, we could divide the release process in 2 steps that will be quite close each other. One would involve the version bump, push and tag. The other, the npm publish. We can connect both using travis conditions. 🆒

Setup

The first part involves versioning, the command (npm script) will look like this:

"lerna:version": "lerna version prerelease --preid beta"

Also, it is very convenient to add the following to the lerna.json file to limit the branch where we want to release:

"command": {
  "publish": {
    "allowBranch": "master"
  }
}

So far, so good. If we run the lerna:version script we would only need to choose/confirm the version bump and we will end up with a new version and a new tag on github.

For the publish we will use the new tag on master as a travis condition for deploy:

language: node_js
node_js:
  - "10"
cache:
  yarn: true
  directories:
    - "node_modules"
before_install:
  - curl -o- -L https://yarnpkg.com/install.sh | bash -s
  - export PATH="$HOME/.yarn/bin:$PATH"
before_script:
  - yarn run lerna run prepublish
script:
  - yarn test
before_deploy:
  - echo "//registry.npmjs.org/:_authToken=\${NPM_TOKEN}" >> $HOME/.npmrc 2> /dev/null
deploy:
  provider: script
  script: "yarn run lerna:publish"
  skip_cleanup: true
  on:
    node: "10"
    tags: true

The relevant parts from the travis setup are the tags: true condition and the NPM_TOKEN being set as part of the "local" .npmrc file. For the conditional, tags: true means that travis will only deploy iff the TRAVIS_TAG env var is set and the var will only be set if we are building from a git tag.

Combining the travis condition a github protected branch and the lerna version protection too we can have a quite robust split workflow.

Finally, let's take a look into the travis deploy script, it will look like this:

"lerna:publish": "lerna publish from-git --yes --npm-client yarn --npm-tag beta

Here we are telling lerna to use the version from the current git commit this is a special option very useful for a CI scenario like ours.

Usage

Like we said, this is a "2 steps" workflow.

  1. From master you can launch the versioning: yarn run lerna:version
  2. The automatic step, travis will detect a new tag on master and this will trigger a new deploy. 🚀

Requirements

We only need a NPM_TOKEN for travis.

Changelog

Last but not least, how do we maintaing a changelog with a strategy like this? Remember, we are using chan. With this setup, we can't use npm hooks and lerna does not offer any hook (but maybe in the future) so we need to add our own "hooks", we can do something like the following:

{
  "scripts": {
    "lerna:postversion": "chan release --group-changes $(node -p -e \"require('./lerna.json').version\") && git add CHANGELOG.md && git commit -m \"Update: changelog\" && git push --follow-tags",
    "lerna:version": "lerna version prerelease --preid beta && yarn run lerna:postversion"
  }
}

...and that's it!


brought to you by:

GEUT Labs

The place to try ideas.

lerna-travis-demo's People

Contributors

dpaez avatar traviscibot avatar

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.