Skip to content

Commit d8c5c0a

Browse files
ci(global): INFRA-902 test metrics delivery (part 1) (#5849)
* ci(global): INFRA-902 test metrics delivery * fix(global): INFRA-902 replace fetch with KS one * fix(global): INFRA-902 replace fetch with node-fetch * fix(global): INFRA-902 txt * fix(global): INFRA-902 status * ci(global): INFRA-902 test prom-client * ci(global): INFRA-902 test prom-client * ci(global): INFRA-902 test prometheus-remote-write * ci(global): INFRA-902 add custom tests reporter * ci(global): INFRA-902 TMP CHANGE TRIGGER * ci(global): INFRA-902 add envs to CI jobs * ci(global): INFRA-902 change jest configs to include reporter * Revert "ci(global): INFRA-902 TMP CHANGE TRIGGER" This reverts commit ec349a3.
1 parent bcac847 commit d8c5c0a

File tree

9 files changed

+212
-15
lines changed

9 files changed

+212
-15
lines changed

.github/workflows/nodejs.condo.ci.yml

+55-5
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,20 @@ jobs:
313313
docker exec condo-container yarn workspace @app/address-service makemigrations --check
314314
- name: Run apps and tests
315315
run: |
316-
docker exec condo-container sh -c "(\
316+
docker exec \
317+
-e PROMETHEUS_RW_SERVER_URL=$PROMETHEUS_RW_SERVER_URL \
318+
-e PROMETHEUS_USER=$PROMETHEUS_USER \
319+
-e PROMETHEUS_PASSWORD=$PROMETHEUS_PASSWORD \
320+
-e GH_REF_NAME=$GH_REF_NAME \
321+
condo-container sh -c "(\
317322
yarn workspace @app/address-service start & \
318323
node bin/wait-apps-apis.js -f address-service) && \
319324
yarn workspace @app/address-service test"
325+
env:
326+
PROMETHEUS_RW_SERVER_URL: ${{ secrets.K6_PROMETHEUS_RW_SERVER_URL }}
327+
PROMETHEUS_USER: ${{ secrets.K6_PROMETHEUS_USER }}
328+
PROMETHEUS_PASSWORD: ${{ secrets.K6_PROMETHEUS_PASSWORD }}
329+
GH_REF_NAME: ${{ github.ref_name }}
320330

321331
run-condo-tests:
322332
name: Condo Tests
@@ -389,7 +399,17 @@ jobs:
389399
docker exec condo-container sh -c "yarn workspace @app/condo start" 2>&1 > ./test_logs/dev_portal_api.condo.dev.log &
390400
docker exec condo-container sh -c "yarn workspace @app/dev-portal-api start" 2>&1 > ./test_logs/dev_portal_api.dev-portal-api.dev.log &
391401
docker exec condo-container sh -c "node bin/wait-apps-apis.js -f condo dev-portal-api"
392-
docker exec condo-container sh -c "yarn workspace @app/dev-portal-api test" 2>&1 > ./test_logs/dev_portal_api.tests.log
402+
docker exec \
403+
-e PROMETHEUS_RW_SERVER_URL=$PROMETHEUS_RW_SERVER_URL \
404+
-e PROMETHEUS_USER=$PROMETHEUS_USER \
405+
-e PROMETHEUS_PASSWORD=$PROMETHEUS_PASSWORD \
406+
-e GH_REF_NAME=$GH_REF_NAME \
407+
condo-container sh -c "yarn workspace @app/dev-portal-api test" 2>&1 > ./test_logs/dev_portal_api.tests.log
408+
env:
409+
PROMETHEUS_RW_SERVER_URL: ${{ secrets.K6_PROMETHEUS_RW_SERVER_URL }}
410+
PROMETHEUS_USER: ${{ secrets.K6_PROMETHEUS_USER }}
411+
PROMETHEUS_PASSWORD: ${{ secrets.K6_PROMETHEUS_PASSWORD }}
412+
GH_REF_NAME: ${{ github.ref_name }}
393413
- name: Collect docker logs on failure
394414
if: failure()
395415
uses: jwalton/gh-docker-logs@v1
@@ -427,6 +447,11 @@ jobs:
427447
yarn install --immutable
428448
- name: Run @open-condo/migrator tests
429449
run: yarn workspace @open-condo/migrator test
450+
env:
451+
PROMETHEUS_RW_SERVER_URL: ${{ secrets.K6_PROMETHEUS_RW_SERVER_URL }}
452+
PROMETHEUS_USER: ${{ secrets.K6_PROMETHEUS_USER }}
453+
PROMETHEUS_PASSWORD: ${{ secrets.K6_PROMETHEUS_PASSWORD }}
454+
GH_REF_NAME: ${{ github.ref_name }}
430455

431456
run-rb-tests:
432457
name: RB Tests
@@ -464,11 +489,21 @@ jobs:
464489
docker exec condo-container yarn workspace @app/rb makemigrations --check
465490
- name: Run apps and tests
466491
run: |
467-
docker exec condo-container sh -c "(\
492+
docker exec \
493+
-e PROMETHEUS_RW_SERVER_URL=$PROMETHEUS_RW_SERVER_URL \
494+
-e PROMETHEUS_USER=$PROMETHEUS_USER \
495+
-e PROMETHEUS_PASSWORD=$PROMETHEUS_PASSWORD \
496+
-e GH_REF_NAME=$GH_REF_NAME \
497+
condo-container sh -c "(\
468498
yarn workspace @app/condo start & \
469499
yarn workspace @app/rb start & \
470500
node bin/wait-apps-apis.js -f condo rb) && \
471501
yarn workspace @app/rb test"
502+
env:
503+
PROMETHEUS_RW_SERVER_URL: ${{ secrets.K6_PROMETHEUS_RW_SERVER_URL }}
504+
PROMETHEUS_USER: ${{ secrets.K6_PROMETHEUS_USER }}
505+
PROMETHEUS_PASSWORD: ${{ secrets.K6_PROMETHEUS_PASSWORD }}
506+
GH_REF_NAME: ${{ github.ref_name }}
472507

473508
run-registry-tests:
474509
name: Registry-importer Tests
@@ -506,11 +541,21 @@ jobs:
506541
docker exec condo-container yarn workspace @app/registry-importer makemigrations --check
507542
- name: Run apps and tests
508543
run: |
509-
docker exec condo-container sh -c "(\
544+
docker exec \
545+
-e PROMETHEUS_RW_SERVER_URL=$PROMETHEUS_RW_SERVER_URL \
546+
-e PROMETHEUS_USER=$PROMETHEUS_USER \
547+
-e PROMETHEUS_PASSWORD=$PROMETHEUS_PASSWORD \
548+
-e GH_REF_NAME=$GH_REF_NAME \
549+
condo-container sh -c "(\
510550
yarn workspace @app/condo start & \
511551
yarn workspace @app/registry-importer start & \
512552
node bin/wait-apps-apis.js -f condo registry-importer) && \
513553
yarn workspace @app/registry-importer test"
554+
env:
555+
PROMETHEUS_RW_SERVER_URL: ${{ secrets.K6_PROMETHEUS_RW_SERVER_URL }}
556+
PROMETHEUS_USER: ${{ secrets.K6_PROMETHEUS_USER }}
557+
PROMETHEUS_PASSWORD: ${{ secrets.K6_PROMETHEUS_PASSWORD }}
558+
GH_REF_NAME: ${{ github.ref_name }}
514559

515560
run-webhooks-tests:
516561
name: Webhooks Tests
@@ -532,4 +577,9 @@ jobs:
532577
npm i -g turbo
533578
yarn install --immutable
534579
- name: Test webhooks utils
535-
run: yarn workspace @open-condo/webhooks jest
580+
run: yarn workspace @open-condo/webhooks test
581+
env:
582+
PROMETHEUS_RW_SERVER_URL: ${{ secrets.K6_PROMETHEUS_RW_SERVER_URL }}
583+
PROMETHEUS_USER: ${{ secrets.K6_PROMETHEUS_USER }}
584+
PROMETHEUS_PASSWORD: ${{ secrets.K6_PROMETHEUS_PASSWORD }}
585+
GH_REF_NAME: ${{ github.ref_name }}

apps/address-service/jest.config.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
/** @type {import('jest').Config} */
22
module.exports = {
3+
rootDir: './',
4+
reporters: ['default', '<rootDir>/../../bin/report-failed-tests.js'],
35
projects: [
46
{
57
testRunner: 'jasmine2',
68
displayName: 'schema',
79
testEnvironment: 'node',
8-
testMatch: [`${__dirname}/schema/**/*.test.js`, `${__dirname}/domains/**/schema/*.test.js`],
9-
setupFilesAfterEnv: [`${__dirname}/jest.setupTest.js`],
10+
testMatch: ['<rootDir>/schema/**/*.test.js', '<rootDir>/domains/**/schema/*.test.js'],
11+
setupFilesAfterEnv: ['<rootDir>/jest.setupTest.js'],
1012
// NOTE: need to pass uuid export syntax through babel
1113
transformIgnorePatterns: ['/node_modules/(?!(uuid)/)'],
1214
},
@@ -19,7 +21,7 @@ module.exports = {
1921
transform: {
2022
'\\.[jt]sx?$': 'babel-jest',
2123
},
22-
setupFilesAfterEnv: [`${__dirname}/jest.setupSpec.js`],
24+
setupFilesAfterEnv: ['<rootDir>/jest.setupSpec.js'],
2325
// NOTE: need to pass uuid export syntax through babel
2426
transformIgnorePatterns: ['/node_modules/(?!(uuid)/)'],
2527
},

apps/dev-portal-api/jest.config.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
1+
/** @type {import('jest').Config} */
12
module.exports = {
3+
rootDir: './',
4+
reporters: ['default', '<rootDir>/../../bin/report-failed-tests.js'],
25
projects: [
36
{
47
testRunner: 'jasmine2',
58
displayName: 'schema tests',
69
testEnvironment: 'node',
7-
testMatch: [`${__dirname}/schema/**/*.test.js`, `${__dirname}/domains/**/schema/*.test.js`],
8-
setupFilesAfterEnv: [`${__dirname}/jest.setupTest.js`],
10+
testMatch: ['<rootDir>/schema/**/*.test.js', '<rootDir>/domains/**/schema/*.test.js'],
11+
setupFilesAfterEnv: ['<rootDir>/jest.setupTest.js'],
912
},
1013
{
1114
testRunner: 'jasmine2',
1215
displayName: 'schema specs',
1316
testEnvironment: 'node',
1417
testMatch: [
15-
`${__dirname}/domains/**/schema/**/*.spec.js`,
18+
'<rootDir>/domains/**/schema/**/*.spec.js',
1619
],
17-
setupFilesAfterEnv: [`${__dirname}/jest.setupSpec.js`],
20+
setupFilesAfterEnv: ['<rootDir>/jest.setupSpec.js'],
1821
},
1922
],
2023
}

bin/report-failed-tests.js

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
const path = require('path')
2+
3+
const fetch = require('node-fetch')
4+
const { pushTimeseries } = require('prometheus-remote-write')
5+
6+
const REPO_ROOT = path.join(__dirname, '..')
7+
const PROMETHEUS_REMOTE_WRITE_URL = process.env.PROMETHEUS_RW_SERVER_URL
8+
const PROMETHEUS_AUTH_USER = process.env.PROMETHEUS_USER
9+
const PROMETHEUS_AUTH_PASSWORD = process.env.PROMETHEUS_PASSWORD
10+
const RUNTIME_REF_NAME = process.env.GH_REF_NAME || 'local'
11+
const BATCH_SIZE = 10
12+
13+
/** @implements {import('@jest/reporters').Reporter} */
14+
class PrometheusReporter {
15+
#config = null
16+
17+
constructor () {
18+
if (PROMETHEUS_REMOTE_WRITE_URL && PROMETHEUS_AUTH_USER && PROMETHEUS_AUTH_PASSWORD) {
19+
this.#config = {
20+
url: PROMETHEUS_REMOTE_WRITE_URL,
21+
auth: {
22+
username: PROMETHEUS_AUTH_USER,
23+
password: PROMETHEUS_AUTH_PASSWORD,
24+
},
25+
fetch,
26+
labels: {
27+
__name__: 'ci_failed_test',
28+
ref: RUNTIME_REF_NAME,
29+
},
30+
}
31+
}
32+
}
33+
34+
/**
35+
* @param {string} testName
36+
* @param {string} testPath
37+
* @param {number} timestamp
38+
*/
39+
async #reportFailedTest ({ testName, testPath, timestamp }) {
40+
if (this.#config) {
41+
await pushTimeseries({
42+
labels: {
43+
test_name: testName,
44+
test_file: testPath,
45+
},
46+
samples: [
47+
{ value: 1, timestamp },
48+
],
49+
}, this.#config)
50+
}
51+
}
52+
53+
/**
54+
* @param {Set<import('@jest/reporters').TestContext>} testContexts
55+
* @param {import('@jest/reporters').AggregatedResult} runResults
56+
*/
57+
async onRunComplete (
58+
testContexts,
59+
runResults
60+
) {
61+
62+
/**
63+
* @type {Array<{ testName: string, testPath: string, timestamp: number }>}
64+
*/
65+
const failedTests = []
66+
67+
if (runResults.numFailedTests === 0) {
68+
return
69+
}
70+
71+
for (const testFileResult of runResults.testResults) {
72+
if (testFileResult.numFailingTests === 0) {
73+
continue
74+
}
75+
76+
const absoluteTestFilePath = testFileResult.testFilePath
77+
const testFilePath = path.relative(REPO_ROOT, absoluteTestFilePath)
78+
const fileEndTimestamp = testFileResult.perfStats.end
79+
80+
for (const assertionResult of testFileResult.testResults) {
81+
if (assertionResult.status === 'failed') {
82+
const testNameParts = [...assertionResult.ancestorTitles, assertionResult.title]
83+
// Clean tabulation / spaces and join
84+
const testFullName = testNameParts
85+
.map(part => part.replace(/\s+/g, ' '))
86+
.join(' > ')
87+
failedTests.push({
88+
testName: testFullName,
89+
testPath: testFilePath,
90+
timestamp: fileEndTimestamp,
91+
})
92+
}
93+
}
94+
}
95+
96+
for (let startIdx = 0; startIdx < failedTests.length; startIdx += BATCH_SIZE) {
97+
const endIdx = Math.min(startIdx + BATCH_SIZE, failedTests.length)
98+
const batch = failedTests.slice(startIdx, endIdx)
99+
100+
await Promise.allSettled(batch.map(test => this.#reportFailedTest({
101+
testName: test.testName,
102+
testPath: test.testPath,
103+
timestamp: test.timestamp,
104+
})))
105+
}
106+
}
107+
}
108+
109+
module.exports = PrometheusReporter

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"@faker-js/faker": "^7.6.0",
3030
"@graphql-codegen/cli": "1.21.8",
3131
"@graphql-codegen/typescript": "1.23.0",
32+
"@jest/reporters": "^29.7.0",
3233
"@mono-pub/commit-analyzer": "^1.0.5",
3334
"@mono-pub/git": "^1.0.5",
3435
"@mono-pub/github": "^1.0.5",
@@ -54,6 +55,7 @@
5455
"node-fetch": "^2.6.7",
5556
"postcss": "^8.3.5",
5657
"postcss-less": "^6.0.0",
58+
"prometheus-remote-write": "^0.5.0",
5759
"stylelint": "^14.11.0",
5860
"stylelint-config-rational-order": "^0.1.2",
5961
"stylelint-config-standard": "^28.0.0",

packages/migrator/jest.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module.exports = {
33
preset: 'ts-jest',
44
testEnvironment: 'node',
55
rootDir: './',
6+
reporters: ['default', '<rootDir>/../../bin/report-failed-tests.js'],
67
testPathIgnorePatterns: ['/node_modules/'],
78
moduleFileExtensions: ['js', 'ts'],
89
projects: [

packages/webhooks/jest.config.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1+
/** @type {import('jest').Config} */
12
module.exports = {
3+
rootDir: './',
4+
reporters: ['default', '<rootDir>/../../bin/report-failed-tests.js'],
25
projects: [
36
{
47
displayName: 'Specs',
58
testEnvironment: 'node',
69
testRunner: 'jasmine2',
7-
testMatch: [`${__dirname}/**/*.spec.js`],
10+
testMatch: ['<rootDir>/**/*.spec.js'],
811
testPathIgnorePatterns: ['/tasks/'],
9-
setupFilesAfterEnv: [`${__dirname}/jest.setupSpec.js`],
12+
setupFilesAfterEnv: ['<rootDir>/jest.setupSpec.js'],
1013
},
1114
],
1215
}

packages/webhooks/package.json

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
"keystone",
88
"webhooks"
99
],
10+
"scripts": {
11+
"test": "jest"
12+
},
1013
"version": "0.0.0-development",
1114
"repository": {
1215
"type": "git",

yarn.lock

+25-1
Original file line numberDiff line numberDiff line change
@@ -45608,6 +45608,21 @@ __metadata:
4560845608
languageName: node
4560945609
linkType: hard
4561045610

45611+
"prometheus-remote-write@npm:^0.5.0":
45612+
version: 0.5.0
45613+
resolution: "prometheus-remote-write@npm:0.5.0"
45614+
dependencies:
45615+
protobufjs: ^7.2.4
45616+
snappyjs: ^0.6.1
45617+
peerDependencies:
45618+
node-fetch: ^2.6.7
45619+
peerDependenciesMeta:
45620+
node-fetch:
45621+
optional: true
45622+
checksum: e0fed2f5dcdda9b1cf1eab111c12342a1b1ba6e1c6970ce92a27e6f27185b6e94dfdabcaeb322d51ad01ab5c75a992be648f6ebac1a4ce3610e524474aa031ad
45623+
languageName: node
45624+
linkType: hard
45625+
4561145626
"promise-inflight@npm:^1.0.1":
4561245627
version: 1.0.1
4561345628
resolution: "promise-inflight@npm:1.0.1"
@@ -45738,7 +45753,7 @@ __metadata:
4573845753
languageName: node
4573945754
linkType: hard
4574045755

45741-
"protobufjs@npm:^7.2.5, protobufjs@npm:^7.2.6, protobufjs@npm:^7.3.2":
45756+
"protobufjs@npm:^7.2.4, protobufjs@npm:^7.2.5, protobufjs@npm:^7.2.6, protobufjs@npm:^7.3.2":
4574245757
version: 7.4.0
4574345758
resolution: "protobufjs@npm:7.4.0"
4574445759
dependencies:
@@ -50250,6 +50265,7 @@ __metadata:
5025050265
"@faker-js/faker": ^7.6.0
5025150266
"@graphql-codegen/cli": 1.21.8
5025250267
"@graphql-codegen/typescript": 1.23.0
50268+
"@jest/reporters": ^29.7.0
5025350269
"@mono-pub/commit-analyzer": ^1.0.5
5025450270
"@mono-pub/git": ^1.0.5
5025550271
"@mono-pub/github": ^1.0.5
@@ -50281,6 +50297,7 @@ __metadata:
5028150297
node-fetch: ^2.6.7
5028250298
postcss: ^8.3.5
5028350299
postcss-less: ^6.0.0
50300+
prometheus-remote-write: ^0.5.0
5028450301
stylelint: ^14.11.0
5028550302
stylelint-config-rational-order: ^0.1.2
5028650303
stylelint-config-standard: ^28.0.0
@@ -51414,6 +51431,13 @@ __metadata:
5141451431
languageName: node
5141551432
linkType: hard
5141651433

51434+
"snappyjs@npm:^0.6.1":
51435+
version: 0.6.1
51436+
resolution: "snappyjs@npm:0.6.1"
51437+
checksum: ff1e129207e8dead5674fdf066c4b91ea8aa8f4a09b25a8de14904dce6c2a361463a0d502f6d2c074529cc3fe0aa176ed1f990528ed8f324f23b542ebc14caff
51438+
languageName: node
51439+
linkType: hard
51440+
5141751441
"socket.io-adapter@npm:~2.5.2":
5141851442
version: 2.5.2
5141951443
resolution: "socket.io-adapter@npm:2.5.2"

0 commit comments

Comments
 (0)