How to include git revision into angular-cli application?
Solution 1
As suggested by @Yuri, I was able to solve this by using npm
scripting.
- Defined
git.version.ts
in the root of the angular-cli project:
import { Observable, combineLatest } from 'rxjs'
declare var require: any;
declare var process: any;
const fs = require('fs');
const exec = require('child_process').exec;
const revision = new Observable<string>(s => {
exec('git rev-parse --short HEAD',
(error: Error, stdout, stderr) => {
if (error !== null) {
console.log('git error: ' + error + stderr);
}
s.next(stdout.toString().trim());
s.complete();
});
});
const branch = new Observable<string>(s => {
exec('git rev-parse --abbrev-ref HEAD',
(error: Error, stdout, stderr) => {
if (error !== null) {
console.log('git error: ' + error + stderr);
}
s.next(stdout.toString().trim());
s.complete();
});
});
combineLatest(revision, branch)
.subscribe(([revision, branch]) => {
console.log(`version: '${process.env.npm_package_version}', revision: '${revision}', branch: '${branch}'`);
const content = '// this file is automatically generated by git.version.ts script\n' +
`export const versions = {version: '${process.env.npm_package_version}', revision: '${revision}', branch: '${branch}'};`;
fs.writeFileSync(
'src/environments/versions.ts',
content,
{encoding: 'utf8'}
);
});
- Added pre-build hook in
package.json
:
"scripts": {
"ng": "ng",
...
"start": "ng serve --proxy proxy-config.json",
"prebuild.prod": "ts-node -O \"{\\\"module\\\":\\\"commonjs\\\"}\" git.version.ts",
"build.prod": "ng build -prod",
...
}
Use the generated
src/environments/versions.ts
in the application.UPDATE 10/2018: Here is the more-readable version of the script, rxjs-version-agnostic:
import { writeFileSync } from 'fs';
import { dedent } from 'tslint/lib/utils';
import { promisify } from 'util';
import * as child from 'child_process';
const exec = promisify(child.exec);
async function createVersionsFile(filename: string) {
const revision = (await exec('git rev-parse --short HEAD')).stdout.toString().trim();
const branch = (await exec('git rev-parse --abbrev-ref HEAD')).stdout.toString().trim();
console.log(`version: '${process.env.npm_package_version}', revision: '${revision}', branch: '${branch}'`);
const content = dedent`
// this file is automatically generated by git.version.ts script
export const versions = {
version: '${process.env.npm_package_version}',
revision: '${revision}',
branch: '${branch}'
};`;
writeFileSync(filename, content, {encoding: 'utf8'});
}
createVersionsFile('src/environments/versions.ts');
Note, when using angular-cli v7.0.6, I also had to change script invocation in the package.json
:
"scripts": {
...
"prebuild.prod": "ts-node -O '{\"module\": \"commonjs\"}' git.version.ts",
...
}
Solution 2
The other answers were helpful, but I preferred a more simple, direct approach. Here's mine.
Run npm install git-describe --save-dev
. Then add git-version.js
to the root:
// This script runs operations *synchronously* which is normally not the best
// approach, but it keeps things simple, readable, and for now is good enough.
const { gitDescribeSync } = require('git-describe');
const { writeFileSync } = require('fs');
const gitInfo = gitDescribeSync();
const versionInfoJson = JSON.stringify(gitInfo, null, 2);
writeFileSync('git-version.json', versionInfoJson);
Optionally you can add /git-version.json
to your .gitignore
file.
Update your package.json
to do something like this:
"scripts": {
"build": "node git-version.js && ng build"
}
Then add version-info.ts
to the root of your project:
export const versionInfo = (() => {
try {
// tslint:disable-next-line:no-var-requires
return require('../../git-version.json');
} catch {
// In dev the file might not exist:
return { tag: 'v0.0.0', hash: 'dev' };
}
})();
And import
the versionInfo
in your app.component.ts
or anywhere else you'd want to use it.
Solution 3
- Add
git-version.js
to the root.This code will execute git commands and write the output to thegit-version.json
file.
const childProcess = require('child_process');
const { writeFileSync } = require('fs');
const longSHA = childProcess.execSync("git rev-parse HEAD").toString().trim();
const shortSHA = childProcess.execSync("git rev-parse --short HEAD").toString().trim();
const branch = childProcess.execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
const authorName = childProcess.execSync("git log -1 --pretty=format:'%an'").toString().trim();
const commitTime = childProcess.execSync("git log -1 --pretty=format:'%cd'").toString().trim();
const commitMsg = childProcess.execSync("git log -1 --pretty=%B").toString().trim();
const totalCommitCount = childProcess.execSync("git rev-list --count HEAD").toString().trim();
const versionInfo = {
shortSHA: shortSHA,
SHA : longSHA,
branch: branch,
lastCommitAuthor: authorName,
lastCommitTime: commitTime,
lastCommitMessage: commitMsg,
lastCommitNumber: totalCommitCount
}
const versionInfoJson = JSON.stringify(versionInfo, null, 2);
writeFileSync('/src/git-version.json', versionInfoJson);
This code will generate the git-version.json
file :-
{
"shortSHA": "0e786d4",
"SHA": "0e786d4ad3778463f6f30c28f254cc85c24eb4b3",
"branch": "master",
"lastCommitAuthor": "'saurabh'",
"lastCommitTime": "'Thu Apr 9 12:59:16 2020 +0530'",
"lastCommitMessage": "Commit message",
"lastCommitNumber": "200"
}
Modify above code as per your requirements.
Run: node git-version.js
This will generate the git-version.json
into src
directory.
- To run this code before or after the build. add a new script to
package.json
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"build.prod": "node git-version.js && ng build --prod"
}
- Run:-
npm run build.prod
suggestions for code improvement are welcome :)
Solution 4
I like to keep things simple. Can add to your index.html:
<script>window.version = '{git-hash}';</script>
Then add a postbuild
script to your package.json
:
"postbuild": "sed -i '' \"s/{git\\-hash}/$(git rev-parse --short HEAD)/g\" dist/*/index.html"
Not elegant by any means. Personally I create an object on window
with various information about the build (time, version, and a release summary link).
To stay more 'pure', stick the {git-hash}
string in environment.prod.ts
and run the sed
against all main-*.js
files produced.
"postbuild": "sed -i '' \"s/{git\\-hash}/$(git rev-parse --short HEAD)/g\" dist/*/main-*.js"
Note you'll always see '{git-hash}' running locally as it's only replaced post-build. If you replace it before the build, obviously can't replace it on future builds locally and would most definitely accidentally check that in.
---- UPDATE ----
Ended up creating a library to pull various information. Only ended up using version, build time, and commitTime personally.
https://www.npmjs.com/package/@rippell/ngx-build-info
Solution 5
Display branch name and commit hash
I have a little different approach, inspired by answers repo Seba Arce and Jeroen , in main project directory:
- execute:
npm install git-rev-sync --save
(this lib give acces to hash and branch name) - add file
git-version-gen.js
with following body
const git = require('git-rev-sync');
const { writeFileSync } = require('fs');
const gitInfo = { commit: git.short(), commitLong: git.long(), branch: git.branch() };
const ts = 'export const gitVersion = ' + JSON.stringify(gitInfo, null, 2);
writeFileSync('src/environments/git-version.ts', ts);
- in
package.json
inscripts
add"build": "node git-version-gen.js && ng build ..."
- in your main app file e.g.
app.component.ts
use it as follows
import { gitVersion } from '../../../environments/git-version';
// ...
constructor() {
console.log(`GIT branch:`,gitVersion.branch);
console.log(`GIT commit:`,gitVersion.commit);
}
What are advantages of use this?
we create here
src/environments/git-version.ts
file so this is TypeScript, not .json - similar like you environments files - this will turn on support from your code editor (e.g VSCode)you have acces to commit hash nad branch name (lib
git-describe
not gives acces to branch name)if you commit generated
git-version.ts
file instead put it to.gitignore
then project will run without build (e.g. byng serve ...
) and fresh developers will not be confused that there is missing some 'mystic' file... - however choice is up to you.cross platform - tested on Azure (windows), MacOs (~linux-like)
gwentech
Updated on July 21, 2022Comments
-
gwentech almost 2 years
I need to display git revision on my angular2 application's about page. The project is based on angular-cli.
How can build be extended so git revision is put for example into
environment.ts
or other place accessible to application? -
George C. about 6 years
ts-node git.version.ts
command does not work and I don't know why I geting this:Did you mean one of these? rebuild prefix profile
-
Cameron Yick over 5 yearsFor anyone coming to this using
angular 6
/rxjs 6
: change the import toimport { Observable, combineLatest } from 'rxjs';
, and then replaceObservable.combineLatest
with justcombineLatest
. -
thouliha over 5 yearsThis was a beautiful solution, but I also suggest adding the tag:
git describe --abbrev=0 --tags
-
kinjelom over 5 yearsnpm ERR! notsup Unsupported platform for [email protected]: wanted {"os":"linux","arch":"any"} (current: {"os":"win32","arch":"x64"})
-
Fitrah M over 5 yearsHow to generate the src/environments/versions.ts file? I call the
ng prebuild.prod
command but nothing happens. I wait for several minutes but no output. My versions:bash Angular CLI: 6.0.8 Node: 8.11.1 OS: win32 x64 Angular: 5.2.10 Package Version ----------------------------------------------------------- @angular/cli 6.0.8 @angular/pwa 0.6.5 @angular/service-worker 5.2.11 @ngtools/webpack 6.0.5 rxjs 5.5.10
-
Jeroen over 5 yearsStrange. I ran this on my Windows 10 x64 machine without problems, and it runs fine on AppVeyor's VS2017 image too.
-
oded over 5 yearsthis is a very clean and nice way to acheive it!!! i thought sharing a code that i added to this solution that will print out more git information and jobname or BUILD_NUMBER if you are running it through jenkins
-
oded over 5 yearshere is the additional code: add 4 more observables lastCommitTime which is git log --format="%ai" -n1 HEAD, lastCommitMessage which is git log --format="%B" -n1 HEAD, lastCommitAuthor which is git log --format="%aN" -n1 HEAD, lastCommitNumber which is git rev-list --count HEAD, const commitSHA = process.env.GIT_COMMIT || branch; const buildInfo = process.env.BUILD_NUMBER || 'LOCAL ' + revision + ' - last commit number ' + lastCommitNumber + ', by ' + lastCommitAuthor + ' on ' + lastCommitTime; const jobName = process.env.JOB_NAME || 'local build'
-
codingbadger over 5 years@wildloop The npm syntax to install
git-describe
should benpm install git-describe --save-dev
-
Kamil Kiełczewski over 4 yearsthis is probably only for systems which have
sed
command (linux:Yes, windows: No) -
Charly over 4 yearsAbsolutely true, partially why I ended up creating the npm library
-
MIWMIB almost 4 years
-O '{\"module\": \"commonjs\"}'
in package.json didn't work for me (win10). I had to remove it and change the imports in git.version.ts to require statements. -
David over 3 yearsThis worked great, my only critique is that you misspelled the variable
chidProcess
-
Saurabh Gangamwar over 3 yearsThanks for letting me know.fixed that issue
-
Ivan Gavlik over 3 yearswhat is require('fs'), require('git-rev-sync') and require('mkdirp') do i need to install them
-
theo over 3 yearsnice one! You can add
version: process.env.npm_package_version,
to add the version in the json file produced. -
theo over 3 years@MIWMIB yeah I had the same. At first it worked fine on my macos and build server (linux) but was failing on windoze with
'ts-node' is not recognized as an internal or external command, operable program or batch file