Deprecated: ember-cli-release is deprecated. We recommend using release-it instead. If you would like to automate changelog generation as well, you might want to consider rwjblue's setup script. The script automates the setup of release-it with lerna-changelog integration.
Ember CLI addon that defines a release
command for bumping the version of your app or addon. It's a streamlined alternative to the npm version
command, with a number of additional advantages:
bower.json
version replacement$ ember install ember-cli-release
This will also generate the config file config/release.js
which can be used to provide default options (see below).
This addon revolves around git tags, and so relies heavily on shelling out to run git commands (unlike the wonderful git-repo-info
).
When invoked with no options:
$ ember release
It will:
version
property of package.json
and bower.json
with the new versionorigin
See the examples section for more ways to use the command.
Options can be specified on the command line or in config/release.js
unless marked with an asterisk (*
). Options specified on the command line always take precedence over options in the config file. Run ember help
to see CLI aliases.
local
Default: false
Whether to only create the git tag locally or not.
remote
Default: 'origin'
The git remote to push new tags to, ignored if local
is true.
tag
*
Default: null
Optional name of the tag to create, overrides versioning strategies.
annotation
Default: null
Message to add when creating a tag, indicates that the tag should be annotated, where %@
is replaced with tag name.
message
Default: 'Released %@'
Message to use when committing changes to the working tree (including changes to package.json
and bower.json
), where %@
is replaced with tag name.
manifest
Default: [ 'package.json', 'bower.json' ]
A set of JSON manifest files to replace the top-level version
key in with the new tag name.
publish
Default: false
Whether to publish the package to NPM after tagging or not. Uses the currently logged in NPM user and the registry as defined in the project's package.json
.
yes
*
Default: false
Whether to skip confirmation prompts or not (answer 'yes' to all questions).
strategy
Default: 'semver'
The versioning strategy to use, either semver
or date
.
major
*
Default: false
Increment the major SemVer version, takes precedence over minor
. Only used when the strategy
option is 'semver'
.
minor
*
Default: false
Increment the minor SemVer version, if both major
and minor
are false, patch is incremented. Only used when the strategy
option is 'semver'
.
premajor
*
Default: ''
Increment the major SemVer version, and add given prerelease identifier with version of 0
. Only used when the strategy
option is 'semver'
, and ignored if major
or minor
are specified.
preminor
*
Default: ''
Increment the minor SemVer version, and add given prerelease identifier with version of 0
. Only used when the strategy
option is 'semver'
, and ignored if major
, minor
, or premajor
are specified.
prerelease
*
Default: false
When using SemVer, has multiple behaviors:
0
.Only used when the strategy
option is 'semver'
, and ignored if major
, minor
, premajor
, or preminor
are specified.
format
Default: 'YYYY.MM.DD'
The format string used when creating a tag based on the current date using moment().format()
. Only used when the strategy
option is 'date'
.
timezone
Default: 'UTC'
The timezone to consider the current date in. Only used when the strategy
option is 'date'
.
A set of lifecycle hooks exists as a means to inject additional behavior into the release process. Lifecycle hooks can be specified in config/release.js
. All hooks can return a thenable that will be resolved before continuing the release process. Throwing from a hook or rejecting a promise returned by a hook will halt the release process and print the error.
Hooks are passed two arguments:
project
- a reference to the current ember-cli projecttags
- an object containing tag information, which will always have a next
property and depending on the strategy you are using, may also have a latest
property. Note that these values will be the exact values used for the tag, which by default includes a v
prefix.There are three lifecycle hooks available:
init
Called after the new version has been computed but before any changes are made to the filesystem or repository. Use this hook if you need to verify that the local environment is setup for releasing, and abort if not.
Aborting:
// config/release.js
module.exports = {
init: function() {
if (!process.env.SUPER_SECRET_KEY) {
throw 'Super secret key missing!';
}
}
};
beforeCommit
Called after the new version has been replaced in manifest files but before the changes have been committed. Use this hook if you need to update the version number in additional files, or build the project to update dist files. Note that this hook runs regardless of whether a commit will be made.
Version replacement:
// config/release.js
var path = require('path');
var xmlpoke = require('xmlpoke');
module.exports = {
beforeCommit: function(project, tags) {
xmlpoke(path.join(project.root, 'cordova/config.xml'), function(xml) {
xml.errorOnNoMatches();
xml.addNamespace('w', 'http://www.w3.org/ns/widgets');
xml.set('w:widget/@version', tags.next);
});
}
};
Building:
// config/release.js
var BuildTask = require('ember-cli/lib/tasks/build');
module.exports = {
// Build the project in the production environment, outputting to dist/
beforeCommit: function(project) {
var task = new BuildTask({
project: project,
ui: project.ui,
analytics: project.cli.analytics
});
return task.run({
environment: 'production',
outputPath: 'dist/'
});
}
};
afterPush
Called after successfully pushing all changes to the specified remote, but before exiting. Use this hook for post-release tasks like cleanup or sending notifications from your CI server.
Notification:
// config/release.js
var Slack = require('node-slack');
// Look for slack configuration in the CI environment
var isCI = process.env.CI;
var hookURL = process.env.SLACK_HOOK_URL;
module.exports = {
// Notify the #dev channel when a new release is created
afterPush: function(project, tags) {
if (isCI && hookURL) {
var slack = new Slack(hookURL);
return slack.send({
text: 'ZOMG, ' + project.name() + ' ' + tags.next + ' RELEASED!!1!',
channel: '#dev',
username: 'Mr. CI'
});
}
}
};
afterPublish
Called after successfully publishing the package to NPM, but before exiting. Use this hook exactly as afterPush
is used when performing a publish. Note that this hook is not run when --publish
option is not set.
If your app does not use SemVer or date-based tags, you may specify a custom method for generating the next tag by making the strategy
property a function in config/release.js
. The function takes three arguments: the project instance, an array of existing git tags, and an options hash with all option values. It must return a non-empty string specifying the next tag, or a promise that resolves with the tag name. For example:
// config/release.js
module.exports = {
// Emulate Subversion-style build numbers
strategy: function(project, tags, options) {
var builds = tags
.map(function(tag) { return +tag; })
.filter(function(build) { return !isNaN(build); })
.sort()
.reverse();
return builds[0] + 1;
}
};
Alternatively, if the custom strategy requires additional CLI options, an object can be specified with availableOptions
, getLatestTag
, and getNextTag
properties:
// config/release.js
module.exports = {
strategy: {
availableOptions: [
{
name: 'channel',
type: String,
default: 'stable',
description: "the release's channel"
},
],
getLatestTag: function(project, tags, options) {
// Find the latest tag in the `tags` array
var latest = '...';
return latest;
},
getNextTag: function(project, tags, options) {
// Generate an identifier
var next = '...';
// Prepend the specified channel
return options.channel + '-' + next;
}
}
};
These are the steps that take place when running the release
command:
publish
option is true
and no NPM user is logged in or strategy
is not 'semver'tag
option if presentstrategy
option (default: 'semver')
node-semver
orderingmajor
, minor
, or patch
(default: patch
)format
option (default: YYYY.MM.DD
).X
where X is an incrementing integerinit
hookversion
property of files specified by the manifest
option (default: package.json
/bower.json
)beforeCommit
hookmessage
option as the commit messageannotation
option if specifiedlocal
option is true
(default: false
)remote
optionafterPush
hookpublish
option is true
(default: false
)afterPublish
hookTo create a new tag based on the date in east cost time with a custom format:
> ember release --strategy=date --format="YYYY-MM-DD" --timezone="America/New_York"
Or to create a specific tag (no versioning strategy) with annotation, locally only:
> ember release --local --tag="what_am_i_doing" --annotation="First version wooooo!"
To create a series of SemVer prereleases, use the --premajor
(or --preminor
) option followed by any number of --prerelease
s, and finally --major
(or --minor
):
# v1.3.2
> ember release --premajor alpha
# v2.0.0-alpha.0
> ember release --prerelease
# v2.0.0-alpha.1
> ember release --prerelease beta
# v2.0.0-beta.0
> ember release --prerelease
# v2.0.0-beta.1
> ember release --major
# v2.0.0
Pull requests welcome, but they must be fully tested (and pass all existing tests) to be considered. Discussion issues also welcome.
$ npm test