Skip to content

Commit 4cc840b

Browse files
authored
feat: Add release version to lambda conext for logging (#14)
* fix: add lambda version to context logging * release tests * release tests * fix: Add lambda version to log context * fix: Add lambda version to log context * fix: Add lambda version to log context * fix: Add lambda version to log context * fix: Add lambda version to log context * feat: Add lambda version to log context
1 parent cd191a3 commit 4cc840b

File tree

5 files changed

+134
-3
lines changed

5 files changed

+134
-3
lines changed

.github/workflows/release.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ jobs:
4040
uses: googleapis/release-please-action@a02a34c4d625f9be7cb89156071d8567266a2445 # v4.2.0
4141
with:
4242
target-branch: ${{ steps.branch.outputs.name }}
43-
release-type: terraform-module
43+
manifest-file: .release-please-manifest.json
44+
config-file: .release-please-config.json
4445
token: ${{ steps.token.outputs.token }}
4546
- name: Attest
4647
if: ${{ steps.release.outputs.releases_created == 'true' }}

.release-please-config.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"release-type": "simple",
3+
"packages": {
4+
".": {
5+
"extra-files": [
6+
{
7+
"type": "json",
8+
"path": "lambdas/functions/ami-housekeeper/package.json",
9+
"jsonpath": "$.version"
10+
},
11+
{
12+
"type": "json",
13+
"path": "lambdas/functions/control-plane/package.json",
14+
"jsonpath": "$.version"
15+
},
16+
{
17+
"type": "json",
18+
"path": "lambdas/functions/gh-agent-syncer/package.json",
19+
"jsonpath": "$.version"
20+
},
21+
{
22+
"type": "json",
23+
"path": "lambdas/functions/termination-watcher/package.json",
24+
"jsonpath": "$.version"
25+
},
26+
{
27+
"type": "json",
28+
"path": "lambdas/functions/webhook/package.json",
29+
"jsonpath": "$.version"
30+
}
31+
]
32+
}
33+
}
34+
}

.release-please-manifest.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
".": "6.6.0"
3+
}

lambdas/libs/aws-powertools-util/src/logger/index.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,34 @@
11
import { Logger } from '@aws-lambda-powertools/logger';
22
import { Context } from 'aws-lambda';
3+
import * as fs from 'fs';
4+
import * as path from 'path';
5+
import { fileURLToPath } from 'url';
36

47
const childLoggers: Logger[] = [];
58

9+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
10+
611
const defaultValues = {
712
region: process.env.AWS_REGION,
813
environment: process.env.ENVIRONMENT || 'N/A',
914
};
1015

16+
function getReleaseVersion(): string {
17+
let version = 'unknown';
18+
try {
19+
const packageFilePath = path.resolve(__dirname, 'package.json');
20+
version = JSON.parse(fs.readFileSync(packageFilePath, 'utf-8')).version || 'unknown';
21+
} catch (error) {
22+
logger.debug(`Failed to read package.json for version: ${(error as Error)?.message ?? 'Unknown error'}`);
23+
}
24+
return version;
25+
}
26+
1127
function setContext(context: Context, module?: string) {
1228
logger.addPersistentLogAttributes({
1329
'aws-request-id': context.awsRequestId,
1430
'function-name': context.functionName,
31+
version: getReleaseVersion(),
1532
module: module,
1633
});
1734

@@ -20,6 +37,7 @@ function setContext(context: Context, module?: string) {
2037
childLogger.addPersistentLogAttributes({
2138
'aws-request-id': context.awsRequestId,
2239
'function-name': context.functionName,
40+
version: getReleaseVersion(),
2341
});
2442
});
2543
}

lambdas/libs/aws-powertools-util/src/logger/logger.test.ts

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { Context } from 'aws-lambda';
2+
import * as fs from 'fs';
3+
import * as path from 'path';
24

3-
import { logger, setContext } from '../';
4-
import { describe, test, expect, beforeEach, vi } from 'vitest';
5+
import { describe, test, expect, beforeEach, afterEach, vi } from 'vitest';
56

67
beforeEach(() => {
78
vi.clearAllMocks();
@@ -29,6 +30,31 @@ const context: Context = {
2930
},
3031
};
3132

33+
const versionFilePath = path.resolve(__dirname, 'version.json');
34+
35+
let logger: typeof import('../').logger;
36+
let setContext: typeof import('../').setContext;
37+
38+
beforeEach(async () => {
39+
// Clear the module cache and reload the logger module
40+
vi.resetModules();
41+
const loggerModule = await import('../');
42+
logger = loggerModule.logger;
43+
setContext = loggerModule.setContext;
44+
45+
// Ensure a clean state before each test
46+
if (fs.existsSync(versionFilePath)) {
47+
fs.unlinkSync(versionFilePath);
48+
}
49+
});
50+
51+
afterEach(() => {
52+
// Clean up after each test
53+
if (fs.existsSync(versionFilePath)) {
54+
fs.unlinkSync(versionFilePath);
55+
}
56+
});
57+
3258
describe('A root logger.', () => {
3359
test('Should log set context.', async () => {
3460
setContext(context, 'unit-test');
@@ -42,3 +68,52 @@ describe('A root logger.', () => {
4268
);
4369
});
4470
});
71+
72+
describe('Logger version handling', () => {
73+
test('Should not fail if package.json does not exist', () => {
74+
const packageFilePath = path.resolve(__dirname, 'package.json');
75+
76+
// Temporarily rename package.json to simulate its absence
77+
const tempFilePath = `${packageFilePath}.bak`;
78+
if (fs.existsSync(packageFilePath)) {
79+
fs.renameSync(packageFilePath, tempFilePath);
80+
}
81+
82+
setContext(context, 'unit-test');
83+
84+
expect(logger.getPersistentLogAttributes()).toEqual(
85+
expect.objectContaining({
86+
version: 'unknown',
87+
}),
88+
);
89+
90+
// Restore package.json
91+
if (fs.existsSync(tempFilePath)) {
92+
fs.renameSync(tempFilePath, packageFilePath);
93+
}
94+
});
95+
96+
test('Should log version from package.json', () => {
97+
const packageFilePath = path.resolve(__dirname, 'package.json');
98+
99+
// Create a mock package.json file
100+
const originalPackageData = fs.existsSync(packageFilePath) ? fs.readFileSync(packageFilePath, 'utf-8') : null;
101+
const mockPackageData = JSON.stringify({ version: '1.0.0' });
102+
fs.writeFileSync(packageFilePath, mockPackageData);
103+
104+
setContext(context, 'unit-test');
105+
106+
expect(logger.getPersistentLogAttributes()).toEqual(
107+
expect.objectContaining({
108+
version: '1.0.0',
109+
}),
110+
);
111+
112+
// Restore the original package.json file
113+
if (originalPackageData) {
114+
fs.writeFileSync(packageFilePath, originalPackageData);
115+
} else {
116+
fs.unlinkSync(packageFilePath);
117+
}
118+
});
119+
});

0 commit comments

Comments
 (0)