When developing an application, maintaining the version of your project can be time-consuming. Let’s explore the steps to improve this process. # Use a commit message convention The very first step to versioning is to have a proper commit message convention. An easy way to get started is to leverage tools like Commitizen and Commitlint in your project and enforce them using Husky.
Install Commitizen
This is optional and will not enforce the commit style as Commitlint would. When you commit with Commitizen, you’ll be prompted to fill out any required commit fields at commit time.
You can install Commitizen globally in one step:
$ npm install commitizen -g
To initialize Commitizen for sensible defaults (using the cz-conventional-changelog convention), you can run this command:
$ commitizen init cz-conventional-changelog --save-dev --save-exact
You can use Commitizen to help you build your commit message by typing this command and following the steps:
$ git cz
Install Commitlint
Commitlint will help your team adhere to a commit convention. To install Commitlint in your project, run this command:
$ npm install --save-dev @commitlint/cli @commitlint/config-conventional
To configure Commitlint to use our convention, create a commitlint.config.js
file with the following content:
module.exports = {extends: ['@commitlint/config-conventional']}
For a one-liner, you can run this command in your terminal:
$ echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js
Install Husky
Installing and configuring Husky in your project will enforce the commit style for each commit. To setup Husky in your project, run the following command:
$ npm install husky --save-dev
Then create a .huskyrc
file in the root of your project and add the following content:
{ "hooks": { "commit-msg": "commitlint -e $GIT_PARAMS" } }
This will run Commitlint before each commit and validate the commit message against your convention. If the commit message is invalid, the commit will be aborted.
Generate a changelog
Now that we are following a commit message convention, we can easily generate a changelog for our project each time we issue a release. For that, I would recommend using Standard Version, which will help you automate versioning and CHANGELOG
generation.
To install Standard Version in your project, run:
$ npm i --save-dev standard-version
Then to generate your initial release version automatically, run:
$ standard-version --first-release
Standard Version will look at your commit history, generate the matching CHANGELOG
file, commit the changes, and create a git tag. For subsequent releases, run:
$ standard-version
This will not only generate/update the CHANGELOG
file but also update your package.json
file with the version number before committing the changes, and creating a git tag.
You can also set up a npm script to generate your release version, by adding the following script to your package.json
:
"scripts": { "release": "standard-version" }
NativeScript-only:
Automate the update of platform-specific manifests Now that we have an easy way to generate our changelog, our package.json
reflecting the right version, we need to update the platform-specific manifests to reflect that version as well.
For Android, the version is specified in the AndroidManifest.xml
file. In a NativeScript project, you will typically find that file under the app/App_Resources/Android/src/main
directory.
Look for the versionCode
and versionName
attributes on the manifest tag:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="__PACKAGE__"
android:versionCode="220000"
android:versionName="2.2.0"
>
For iOS, the version is specified in the Info.plist
file. In a NativeScript project, you will typically find that file under the app/App_Resources/iOS
directory.
Look for the CFBundleShortVersionString
and CFBundleVersion
keys:
<plist version="1.0">
<dict>
<key>CFBundleShortVersionString</key>
<string>2.2.0</string>
<key>CFBundleVersion</key>
<string>2.2.0</string>
</dict>
</plist>
We need to create a script that can look for the version generated by Standard Version in our package.json
, updates these two files accordingly and adds everything to the version commit automatically.
To update the AndroidManifest.xml
& Info.plist
files, we need to install a few tools to manipulate XML and PList files:
$ npm install --save-dev xml-js xml-beautifier plist
Then create a standard-version.js
file in the root directory of your project. We will use that file to open each file, update the version where appropriate and save the file back to the disk.
Now we can create a pre-release script to trigger this code, stage the files and update our release script to make ensure any staged files will be included in the version commit from Standard Version. Update your package.json
like so:
"scripts": {
"pre-release": "node standard-version.js && git add --all",
"release": "standard-version -a"
}
Having the pre-release npm script allows us to test our standard-version script without generating a release commit and tag.
Finally, to run our pre-release script every time we run our release script, we have two options:
- Update the release script to run pre-release beforehand:
"scripts": {
"pre-release": "node standard-version.js && git add --all",
"release": "npm run pre-release && standard-version -a"
}
- Update our
package.json
with a Standard Version post-bump hook:
"standard-version": {
"scripts": {
"postbump": "npm run pre-release"
}
}
Personally, I prefer the second option, as it will enforce the pre-release script even if I run Standard Version with the standalone standard-version command.
We can now push our new version to version control using:
$ git push --follow-tags
and our version is updated in all the right places automagically.
Top comments (0)