Semantic release on GitLab

Share on Facebook0Share on Google+0Tweet about this on TwitterShare on LinkedIn0

Imagine you got yourself a private GitLab instance and your own NPM registry.
Now you can achieve automated
semantic release
nirvana in less than five minutes.

This guide assumes that your GitLab instance runs at https://gitlab.team.com
and your private NPM registry is available at https://registry.team.com/.

  • Create a new project “foo” on GitLab, in my case it will be hosted
    at our private https://gitlab.team.com/gleb/foo server.
  • Create local repo with simple test project.
1
2
3
git init
git remote add origin [email protected]:gleb/foo.git
npm init -y
  • Use scoped package name to prevent accidental publishing to the public registry.
    For example, we can use @team/foo

  • Create .npmrc file that points at our private NPM registry
    for packages scoped with @team

1
2
registry=https://registry.npmjs.org
@team:registry=https://registry.team.com
  • We will need to tell semantic release tool where the remote GitLab server
    lives. Edit the created package.json file and add the repo HTTPS url
    (and not SSH git url. This will be fixed soon).
    We also should add the publishing config to point at our private NPM registry,
    while we are here. I also recommend changing the version to reflect
    the fact that we will no longer publish it manually.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"name": "@team/foo",
"version": "0.0.0-semantic-release",
"publishConfig": {
"registry": "https://registry.team.com/"
}
,

"release": {
"preset": "angular",
"debug": false
}
,

"repository": {
"type": "git",
"url": "https://gitlab.team.com/gleb/foo.git"
}

}

  • Add actual project source files, tests, etc. For this project,
    I will just echo a message on npm test
1
2
3
4
5
{
"scripts": {
"test": "echo All good"
}

}

  • Create GitLab CI file with two stages. First stage will just run unit
    tests. If it passes, then we are going to publish a new package version
    (if there are semantic changes) to NPM. Here is an example .gitlab.ci
    file with cached modules for speed.
1
image: node:6

stages:
  - test
  - deploy

test:
  stage: test
  cache:
    paths:
      - node_modules/
    key: "node_modules"
    untracked: true
  script:
    - npm install --silent
    # add "npm run build" any other steps here
    - npm test

publish:
  stage: deploy
  # no need to cache anything, we are just
  # installing new tool
  before_script:
    - npm install -g --quiet semantic-release-gitlab
  # only publish from master, exclude pure tag builds
  only:
    - [email protected]/foo
  script:
    - semantic-release-gitlab || true
  • The actual commit log parsing, version increment, publishing new
    version and tagging the release is done by the module
    semantic-release-gitlab.

  • Push the change to the GitLab server and enable a runner for the project
    at https://gitlab.team.com/gleb/foo/runners

The runner executes the two build steps and should display in the “Deploy”
step the following

1
2
3
$ semantic-release-gitlab || true
Unable to determine next version to release.
Likely because there are no changes to release.

Notice that we are ignoring the result of the semantic-release-gitlab
call. This is to ignore non-zero exit code when there is nothing to be
published.

We probably did not have any commits that followed
semantic convention.
For example, if we fix a bug, we should commit code with message that starts
with fix(what): ...

1
git commit -m "fix(log): fixed logging call"

Similarly, a commit that adds a new feature should start with feat(what): ....
Any commit that breaks existing API should have BREAKING CHANGE text somewhere
inside the commit message text.

  • Let us add a couple of fake commits to force the publish.
1
2
git commit --allow-empty -m "chore(ci): setup CI"
git commit --allow-empty -m "feat(release): semantic release FTW"

Because we are following Angular commit convention the chore(ci): ...
commit message should trigger patch release. But the next commit is a
feature commit feat(release): ... it will trigger minor version upgrade.
The larger upgrade wins. If you do not want to release a new version,
just commit with regular text that does not start with fix, feat, etc.

  • The new test run should complain about missing NPM_TOKEN variable
1
2
3
4
$ semantic-release-gitlab || true
setting auth token for registry https://registry.team.com/
Cannot find NPM_TOKEN
use https://www.npmjs.com/package/get-npm-token to get one

The CI job needs to authenticate with both NPM registry to publish, and
with GitLab itself to push new tag.

  • Grab the NPM_TOKEN from your private registry and set it as variable
    in the GitLab CI https://gitlab.team.com/gleb/foo/variables
    Set it as the CI variable NPM_TOKEN.

  • While we are setting CI variables, go to GitLab and make yourself a new
    access token at https://gitlab.team.com/profile/personal_access_tokens.
    I prefer naming them <project_name> semantic release.
    Set it as the CI variable GITLAB_AUTH_TOKEN.

  • Go back to the CI pipeline and restart the “Deploy” build.
    You should see the package publish and release log messages.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ semantic-release-gitlab || true
setting auth token for registry https://registry.team.com/
saved /root/.npmrc
npm info it worked if it ends with ok
npm info using npm@3.10.3
npm info using [email protected]4.0
npm info lifecycle @team/foo@1.0.0~prepublish: @team/foo@1.0.0
npm info attempt registry request try #1 at 7:07:42 PM
npm http request PUT https:[email protected]%2ffoo
npm http 200 https:[email protected]%2ffoo
+ @team/foo@1.0.0
npm info lifecycle @team/foo@1.0.0~publish: @team/foo@1.0.0
npm info lifecycle @team/foo@1.0.0~postpublish: @team/foo@1.0.0
npm info ok
Released version 1.0.0
Build succeeded

We just got ourselves package @[email protected]! Let us add a few commits,
for example a fix commit and watch publishing and tagging happen
automatically after pushing the code change to the remote.

  • Add another commit
1
2
git commit --allow-empty -m "fix(oops): good thing I have noticed this"
git push origin master
  • Check the build job and observe new version and tag
1
2
+ @team/foo@1.0.1
Released version 1.0.1
  • Take a look at the project tags page https://gitlab.team.com/gleb/foo/tags.
    It shows nicely formatted change log – you no longer have to generate it manually.

tags

  • Even better, install as-a and
    available-versions and
    query the releases and change log from the command line
1
2
3
4
5
6
7
$ as-a gitlab-team vers @team/foo
@team/foo from https://gitlab.team.com/gleb/foo.git
-----------------------------------------------------------------------
version age release dist-tag
------- --------- ----------------------------------------- --------
1.0.0 8 minutes feat(release): semantic release FTW
1.0.1 4 minutes fix(oops): good thing I have noticed this latest

Further info

Share on Facebook0Share on Google+0Tweet about this on TwitterShare on LinkedIn0