I do something like this, and while I make no pretense that this is the best or only way to do things, here’s what I do.
I have a program that I call “slugger” (it’s written in Go, but would be pretty easy to convert to run in a shell or node). It fetches three bits of data, returned from three git commands:
git branch --show-current
gives me the branch
git rev-parse --short HEAD
gives me the commit
the return code from git diff --quiet
tells me whether we’re dirty
slugger is designed to do different things with this information depending on what language it’s working with. In the TypeScript case, it writes a file that looks like this:
export interface Version {
branch: string;
commit: string;
snapshot: boolean;
}
export const version: Version = {
branch: "%s",
commit: "%s",
snapshot: %t,
}
As you can probably surmise, the %
things are format arguments to a sprintf
-type function. The idea is that you’re replacing that stuff with the results you got from the three git
commands. The result gets written out to a file (I put it in src/environments/version.ts
).
It is very important to make git ignore this file. I add it to src/environments/.gitignore
. Failing to do this properly will result in an Escher Drawing Hands situation where you never get stable results because the commit hash changes, causing that file to change, causing the commit hash to change again, and so on down the rabbit hole.
Inside the app, you can simply import version
from wherever you put it and refer to version.branch
, version.commit
, and version.snapshot
to your heart’s content.
The final step is integrating this into the build process. What I do is to modify the build
script in package.json
to look like this:
"build": "slugger --lang=ts > src/environments/version.ts && ng build",
Now, whenever I run npm run build
, slugger does its thing and then we perform the ordinary angular build process, which will include the most recent git information in the app bundle.
Hope this gives you at least a possible avenue of exploration.