Skip to content

Commit a6c07ba

Browse files
committed
feat: pull the release version from package.json
This makes our calculation of system version a lot more solid. This is going to be required for OpenTelemetry metrics, because any metric sent without a version will end up in the Dead Letter metrics. Because of this I want to give users of Reliability Kit more of a guarantee that their metrics will arrive.
1 parent 3732e3b commit a6c07ba

File tree

2 files changed

+71
-43
lines changed

2 files changed

+71
-43
lines changed

packages/app-info/lib/index.js

Lines changed: 24 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,28 @@ const path = require('node:path');
66
// - Heroku: https://devcenter.heroku.com/articles/dyno-metadata
77
// - Lambda: https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
88

9-
/**
10-
* Get the application system code from a package.json file.
11-
*
12-
* @param {string} directoryPath
13-
* The directory to look for a package.json file in.
14-
* @returns {(string | null)}
15-
* Returns a system code if one is found in `process.env`.
16-
*/
17-
function getSystemCodeFromPackage(directoryPath) {
18-
try {
19-
const manifest = require(path.join(directoryPath, 'package.json'));
20-
return typeof manifest?.name === 'string'
21-
? normalizePackageName(manifest.name)
22-
: null;
23-
} catch (error) {}
24-
return null;
25-
}
26-
27-
/**
28-
* Normalize the name property of a package.json file.
29-
*
30-
* @param {string} name
31-
* The name to normalize.
32-
* @returns {string}
33-
* Returns a normalized copy of the package name.
34-
*/
35-
function normalizePackageName(name) {
36-
// Remove a prefix of "ft-", this is a hangover and we have plenty of
37-
// apps which use this prefix but their system code does not include
38-
// it. E.g. MyFT API has a system code of "next-myft-api", but a
39-
// package.json `name` field of "ft-next-myft-api"
40-
// - https://biz-ops.in.ft.com/System/next-myft-api
41-
// - https://github.com/Financial-Times/next-myft-api/blob/main/package.json
42-
//
43-
return name.replace(/^ft-/, '');
44-
}
9+
/** @type {null | any} */
10+
let manifest = null;
11+
try {
12+
manifest = require(path.join(process.cwd(), 'package.json'));
13+
} catch (error) {}
14+
15+
/** @type {string | null} */
16+
const manifestName =
17+
typeof manifest?.name === 'string'
18+
? // Remove a prefix of "ft-", this is a hangover and we have plenty of
19+
// apps which use this prefix but their system code does not include
20+
// it. E.g. MyFT API has a system code of "next-myft-api", but a
21+
// package.json `name` field of "ft-next-myft-api"
22+
// - https://biz-ops.in.ft.com/System/next-myft-api
23+
// - https://github.com/Financial-Times/next-myft-api/blob/main/package.json
24+
//
25+
manifest.name.replace(/^ft-/, '')
26+
: null;
27+
28+
/** @type {string | null} */
29+
const manifestVersion =
30+
typeof manifest?.version === 'string' ? manifest.version : null;
4531

4632
/**
4733
* Extract the process type from a Heroku dyno name.
@@ -55,9 +41,6 @@ function normalizeHerokuProcessType(dyno) {
5541
return dyno.split('.')[0];
5642
}
5743

58-
const systemCode =
59-
process.env.SYSTEM_CODE || getSystemCodeFromPackage(process.cwd()) || null;
60-
6144
const processType =
6245
process.env.AWS_LAMBDA_FUNCTION_NAME ||
6346
(process.env.DYNO && normalizeHerokuProcessType(process.env.DYNO)) ||
@@ -124,15 +107,15 @@ exports.releaseDate = process.env.HEROKU_RELEASE_CREATED_AT || null;
124107
exports.releaseVersion =
125108
process.env.HEROKU_RELEASE_VERSION ||
126109
process.env.AWS_LAMBDA_FUNCTION_VERSION ||
127-
null;
110+
manifestVersion;
128111

129112
/**
130113
* The application system code.
131114
*
132115
* @readonly
133116
* @type {string | null}
134117
*/
135-
exports.systemCode = systemCode;
118+
exports.systemCode = process.env.SYSTEM_CODE || manifestName;
136119

137120
/**
138121
* The dyno process type.

packages/app-info/test/unit/lib/index.spec.js

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,60 @@ describe('@dotcom-reliability-kit/app-info', () => {
155155
});
156156
});
157157

158-
describe('when neither environment variable is defined', () => {
158+
describe('when neither environment variable is defined but a package.json exists', () => {
159159
beforeEach(() => {
160160
jest.resetModules();
161+
jest.mock(
162+
'/mock-cwd/package.json',
163+
() => ({ version: 'mock-package-version' }),
164+
{ virtual: true }
165+
);
166+
delete process.env.HEROKU_RELEASE_VERSION;
161167
delete process.env.AWS_LAMBDA_FUNCTION_VERSION;
168+
appInfo = require('../../../lib');
169+
});
170+
171+
it('is set to the package.json version in the current working directory', () => {
172+
expect(appInfo.releaseVersion).toBe('mock-package-version');
173+
});
174+
175+
describe('when the package.json has a non-string `version` property', () => {
176+
beforeEach(() => {
177+
jest.resetModules();
178+
jest.mock('/mock-cwd/package.json', () => ({ version: 123 }), {
179+
virtual: true
180+
});
181+
appInfo = require('../../../lib');
182+
});
183+
184+
it('is set to `null`', () => {
185+
expect(appInfo.releaseVersion).toBe(null);
186+
});
187+
});
188+
189+
describe('when the package.json is not an object', () => {
190+
beforeEach(() => {
191+
jest.resetModules();
192+
jest.mock('/mock-cwd/package.json', () => null, { virtual: true });
193+
appInfo = require('../../../lib');
194+
});
195+
196+
it('is set to `null`', () => {
197+
expect(appInfo.releaseVersion).toBe(null);
198+
});
199+
});
200+
});
201+
202+
describe('when neither environment variable is defined and a package.json does not exist', () => {
203+
beforeEach(() => {
204+
jest.unmock('/mock-cwd/package.json');
205+
jest.resetModules();
162206
delete process.env.HEROKU_RELEASE_VERSION;
207+
delete process.env.AWS_LAMBDA_FUNCTION_VERSION;
163208
appInfo = require('../../../lib');
164209
});
165210

166-
it('is set to null', () => {
211+
it('is set to `null`', () => {
167212
expect(appInfo.releaseVersion).toBe(null);
168213
});
169214
});

0 commit comments

Comments
 (0)