Skip to content

Commit baf22d9

Browse files
authored
Verify yaml (#4639)
* add script to verify plugin yaml * add github actions job to verify yaml * fix instrumentations * fix up aerospike * better version ranges for aerospike * fix ci script * make it pass hopefully * update license 3rdparty * fix it no longer assuming nodejs versions * fix aerospike * since node version is now ignored, run on only one version of node
1 parent 69b27b3 commit baf22d9

File tree

9 files changed

+200
-62
lines changed

9 files changed

+200
-62
lines changed

.github/workflows/appsec.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ jobs:
210210
version:
211211
- 18
212212
- latest
213-
range: ['9.5.0', '11.1.4', '13.2.0', '>=14.0.0 <=14.2.6', '>=14.2.7 <15', '>=15.0.0']
213+
range: ['>=10.2.0 <11', '>=11.0.0 <13', '11.1.4', '>=13.0.0 <14', '13.2.0', '>=14.0.0 <=14.2.6', '>=14.2.7 <15', '>=15.0.0']
214214
runs-on: ubuntu-latest
215215
env:
216216
PLUGINS: next

.github/workflows/plugins.yml

Lines changed: 20 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -15,54 +15,30 @@ concurrency:
1515

1616

1717
jobs:
18-
aerospike-node-16:
19-
runs-on: ubuntu-latest
20-
services:
21-
aerospike:
22-
image: aerospike:ce-5.7.0.15
23-
ports:
24-
- "127.0.0.1:3000-3002:3000-3002"
25-
env:
26-
PLUGINS: aerospike
27-
SERVICES: aerospike
28-
PACKAGE_VERSION_RANGE: '>=4.0.0 <5.2.0'
29-
steps:
30-
- uses: actions/checkout@v4
31-
- uses: ./.github/actions/testagent/start
32-
- uses: ./.github/actions/node/setup
33-
- id: pkg
34-
run: |
35-
content=`cat ./package.json | tr '\n' ' '`
36-
echo "json=$content" >> $GITHUB_OUTPUT
37-
- id: extract
38-
run: |
39-
version="${{fromJson(steps.pkg.outputs.json).version}}"
40-
majorVersion=$(echo "$version" | cut -d '.' -f 1)
41-
echo "Major Version: $majorVersion"
42-
echo "MAJOR_VERSION=$majorVersion" >> $GITHUB_ENV
43-
- uses: ./.github/actions/node/oldest
44-
- name: Install dependencies
45-
if: env.MAJOR_VERSION == '4'
46-
uses: ./.github/actions/install
47-
- name: Run tests
48-
if: env.MAJOR_VERSION == '4'
49-
run: yarn test:plugins:ci
50-
- if: always()
51-
uses: ./.github/actions/testagent/logs
52-
- uses: codecov/codecov-action@v3
53-
54-
aerospike-node-18-20:
18+
aerospike:
5519
strategy:
5620
matrix:
57-
node-version: [18]
58-
range: ['5.2.0 - 5.7.0']
21+
node-version: [16]
22+
range: ['>=4.0.0 <5.2.0']
23+
aerospike-image: [ce-5.7.0.15]
24+
test-image: [ubuntu-latest]
5925
include:
26+
- node-version: 18
27+
range: '>=5.2.0'
28+
aerospike-image: ce-6.4.0.3
29+
test-image: ubuntu-latest
6030
- node-version: 20
61-
range: '>=5.8.0'
62-
runs-on: ubuntu-latest
31+
range: '>=5.5.0'
32+
aerospike-image: ce-6.4.0.3
33+
test-image: ubuntu-latest
34+
- node-version: 22
35+
range: '>=5.12.1'
36+
aerospike-image: ce-6.4.0.3
37+
test-image: ubuntu-latest
38+
runs-on: ${{ matrix.test-image }}
6339
services:
6440
aerospike:
65-
image: aerospike:ce-6.4.0.3
41+
image: aerospike:${{ matrix.aerospike-image }}
6642
ports:
6743
- "127.0.0.1:3000-3002:3000-3002"
6844
env:
@@ -73,24 +49,13 @@ jobs:
7349
- uses: actions/checkout@v4
7450
- uses: ./.github/actions/testagent/start
7551
- uses: ./.github/actions/node/setup
76-
- id: pkg
77-
run: |
78-
content=`cat ./package.json | tr '\n' ' '`
79-
echo "json=$content" >> $GITHUB_OUTPUT
80-
- id: extract
81-
run: |
82-
version="${{fromJson(steps.pkg.outputs.json).version}}"
83-
majorVersion=$(echo "$version" | cut -d '.' -f 1)
84-
echo "Major Version: $majorVersion"
85-
echo "MAJOR_VERSION=$majorVersion" >> $GITHUB_ENV
8652
- uses: actions/setup-node@v3
8753
with:
8854
node-version: ${{ matrix.node-version }}
55+
- run: yarn config set ignore-engines true
8956
- name: Install dependencies
90-
if: env.MAJOR_VERSION == '5'
9157
uses: ./.github/actions/install
9258
- name: Run tests
93-
if: env.MAJOR_VERSION == '5'
9459
run: yarn test:plugins:ci
9560
- if: always()
9661
uses: ./.github/actions/testagent/logs
@@ -759,7 +724,7 @@ jobs:
759724
version:
760725
- 18
761726
- latest
762-
range: ['9.5.0', '11.1.4', '13.2.0', '>=14.0.0 <=14.2.6', '>=14.2.7 <15', '>=15.0.0']
727+
range: ['>=10.2.0 <11', '>=11.0.0 <13', '11.1.4', '>=13.0.0 <14', '13.2.0', '>=14.0.0 <=14.2.6', '>=14.2.7 <15', '>=15.0.0']
763728
runs-on: ubuntu-latest
764729
env:
765730
PLUGINS: next

.github/workflows/project.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,3 +162,10 @@ jobs:
162162
- run: yarn type:test
163163
- run: yarn type:doc
164164

165+
verify-yaml:
166+
runs-on: ubuntu-latest
167+
steps:
168+
- uses: actions/checkout@v4
169+
- uses: ./.github/actions/node/setup
170+
- uses: ./.github/actions/install
171+
- run: node scripts/verify-ci-config.js

LICENSE-3rdparty.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ dev,sinon,BSD-3-Clause,Copyright 2010-2017 Christian Johansen
7272
dev,sinon-chai,WTFPL and BSD-2-Clause,Copyright 2004 Sam Hocevar 2012–2017 Domenic Denicola
7373
dev,tap,ISC,Copyright 2011-2022 Isaac Z. Schlueter and Contributors
7474
dev,tiktoken,MIT,Copyright (c) 2022 OpenAI, Shantanu Jain
75+
dev,yaml,ISC,Copyright Eemeli Aro <eemeli@gmail.com>
7576
file,aws-lambda-nodejs-runtime-interface-client,Apache 2.0,Copyright 2019 Amazon.com Inc. or its affiliates. All Rights Reserved.
7677
file,profile.proto,Apache license 2.0,Copyright 2016 Google Inc.
7778
file,is-git-url,MIT,Copyright (c) 2017 Jon Schlinkert.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@
155155
"sinon": "^16.1.3",
156156
"sinon-chai": "^3.7.0",
157157
"tap": "^16.3.7",
158-
"tiktoken": "^1.0.15"
158+
"tiktoken": "^1.0.15",
159+
"yaml": "^2.5.0"
159160
}
160161
}

packages/datadog-instrumentations/src/aerospike.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function wrapProcess (process) {
4040
addHook({
4141
name: 'aerospike',
4242
file: 'lib/commands/command.js',
43-
versions: ['^3.16.2', '4', '5']
43+
versions: ['4', '5']
4444
},
4545
commandFactory => {
4646
return shimmer.wrapFunction(commandFactory, f => wrapCreateCommand(f))

packages/datadog-instrumentations/src/next.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const { channel, addHook } = require('./helpers/instrument')
44
const shimmer = require('../../datadog-shimmer')
5-
const { DD_MAJOR } = require('../../../version')
65

76
const startChannel = channel('apm:next:request:start')
87
const finishChannel = channel('apm:next:request:finish')
@@ -221,7 +220,7 @@ addHook({
221220

222221
addHook({
223222
name: 'next',
224-
versions: DD_MAJOR >= 4 ? ['>=10.2 <11.1'] : ['>=9.5 <11.1'],
223+
versions: ['>=10.2 <11.1'],
225224
file: 'dist/next-server/server/serve-static.js'
226225
}, serveStatic => shimmer.wrap(serveStatic, 'serveStatic', wrapServeStatic))
227226

@@ -248,15 +247,19 @@ addHook({ name: 'next', versions: ['>=13.2'], file: 'dist/server/next-server.js'
248247
return nextServer
249248
})
250249

251-
addHook({ name: 'next', versions: ['>=11.1 <13.2'], file: 'dist/server/next-server.js' }, nextServer => {
250+
addHook({
251+
name: 'next',
252+
versions: ['>=11.1 <13.2'],
253+
file: 'dist/server/next-server.js'
254+
}, nextServer => {
252255
const Server = nextServer.default
253256
shimmer.wrap(Server.prototype, 'handleApiRequest', wrapHandleApiRequest)
254257
return nextServer
255258
})
256259

257260
addHook({
258261
name: 'next',
259-
versions: DD_MAJOR >= 4 ? ['>=10.2 <11.1'] : ['>=9.5 <11.1'],
262+
versions: ['>=10.2 <11.1'],
260263
file: 'dist/next-server/server/next-server.js'
261264
}, nextServer => {
262265
const Server = nextServer.default

scripts/verify-ci-config.js

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
'use strict'
2+
/* eslint-disable no-console */
3+
4+
const fs = require('fs')
5+
const path = require('path')
6+
const util = require('util')
7+
const proxyquire = require('proxyquire')
8+
const yaml = require('yaml')
9+
const semver = require('semver')
10+
const { execSync } = require('child_process')
11+
const Module = require('module')
12+
if (!Module.isBuiltin) {
13+
Module.isBuiltin = mod => Module.builtinModules.includes(mod)
14+
}
15+
16+
const nodeMajor = Number(process.versions.node.split('.')[0])
17+
18+
const names = fs.readdirSync(path.join(__dirname, '..', 'packages', 'datadog-instrumentations', 'src'))
19+
.filter(file => file.endsWith('.js'))
20+
.map(file => file.slice(0, -3))
21+
22+
const instrumentations = names.reduce((acc, key) => {
23+
let instrumentations = []
24+
const name = key
25+
26+
try {
27+
loadInstFile(`${name}/server.js`, instrumentations)
28+
loadInstFile(`${name}/client.js`, instrumentations)
29+
} catch (e) {
30+
loadInstFile(`${name}.js`, instrumentations)
31+
}
32+
33+
instrumentations = instrumentations.filter(i => i.versions)
34+
if (instrumentations.length) {
35+
acc[key] = instrumentations
36+
}
37+
38+
return acc
39+
}, {})
40+
41+
const versions = {}
42+
43+
function checkYaml (yamlPath) {
44+
const yamlContent = yaml.parse(fs.readFileSync(yamlPath, 'utf8'))
45+
46+
const rangesPerPluginFromYaml = {}
47+
const rangesPerPluginFromInst = {}
48+
for (const jobName in yamlContent.jobs) {
49+
const job = yamlContent.jobs[jobName]
50+
if (!job.env || !job.env.PLUGINS) continue
51+
52+
const pluginName = job.env.PLUGINS
53+
if (Module.isBuiltin(pluginName)) continue
54+
const rangesFromYaml = getRangesFromYaml(job)
55+
if (rangesFromYaml) {
56+
if (!rangesPerPluginFromYaml[pluginName]) {
57+
rangesPerPluginFromYaml[pluginName] = new Set()
58+
}
59+
rangesFromYaml.forEach(range => rangesPerPluginFromYaml[pluginName].add(range))
60+
const plugin = instrumentations[pluginName]
61+
const allRangesForPlugin = new Set(plugin.map(x => x.versions).flat())
62+
rangesPerPluginFromInst[pluginName] = allRangesForPlugin
63+
}
64+
}
65+
for (const pluginName in rangesPerPluginFromYaml) {
66+
const yamlRanges = Array.from(rangesPerPluginFromYaml[pluginName])
67+
const instRanges = Array.from(rangesPerPluginFromInst[pluginName])
68+
const yamlVersions = getMatchingVersions(pluginName, yamlRanges)
69+
const instVersions = getMatchingVersions(pluginName, instRanges)
70+
if (!util.isDeepStrictEqual(yamlVersions, instVersions)) {
71+
const opts = { colors: true }
72+
const colors = x => util.inspect(x, opts)
73+
errorMsg(pluginName, 'Mismatch', `
74+
Valid version ranges from YAML: ${colors(yamlRanges)}
75+
Valid version ranges from INST: ${colors(instRanges)}
76+
${mismatching(yamlVersions, instVersions)}
77+
Note that versions may be dependent on Node.js version. This is Node.js v${colors(nodeMajor)}
78+
79+
> These don't match the same sets of versions in npm.
80+
>
81+
> Please check ${yamlPath} and the instrumentations
82+
> for ${pluginName} to see that the version ranges match.`.trim())
83+
}
84+
}
85+
}
86+
87+
function loadInstFile (file, instrumentations) {
88+
const instrument = {
89+
addHook (instrumentation) {
90+
instrumentations.push(instrumentation)
91+
}
92+
}
93+
94+
const instPath = path.join(__dirname, `../packages/datadog-instrumentations/src/${file}`)
95+
96+
proxyquire.noPreserveCache()(instPath, {
97+
'./helpers/instrument': instrument,
98+
'../helpers/instrument': instrument
99+
})
100+
}
101+
102+
function getRangesFromYaml (job) {
103+
// eslint-disable-next-line no-template-curly-in-string
104+
if (job.env && job.env.PACKAGE_VERSION_RANGE && job.env.PACKAGE_VERSION_RANGE !== '${{ matrix.range }}') {
105+
errorMsg(job.env.PLUGINS, 'ERROR in YAML', 'You must use matrix.range instead of env.PACKAGE_VERSION_RANGE')
106+
process.exitCode = 1
107+
}
108+
if (job.strategy && job.strategy.matrix && job.strategy.matrix.range) {
109+
const possibilities = [job.strategy.matrix]
110+
if (job.strategy.matrix.include) {
111+
possibilities.push(...job.strategy.matrix.include)
112+
}
113+
return possibilities.map(possibility => {
114+
if (possibility.range) {
115+
return [possibility.range].flat()
116+
} else {
117+
return undefined
118+
}
119+
}).flat()
120+
}
121+
122+
return null
123+
}
124+
125+
function getMatchingVersions (name, ranges) {
126+
if (!versions[name]) {
127+
versions[name] = JSON.parse(execSync('npm show ' + name + ' versions --json').toString())
128+
}
129+
return versions[name].filter(version => ranges.some(range => semver.satisfies(version, range)))
130+
}
131+
132+
checkYaml(path.join(__dirname, '..', '.github', 'workflows', 'plugins.yml'))
133+
checkYaml(path.join(__dirname, '..', '.github', 'workflows', 'appsec.yml'))
134+
135+
function mismatching (yamlVersions, instVersions) {
136+
const yamlSet = new Set(yamlVersions)
137+
const instSet = new Set(instVersions)
138+
139+
const onlyInYaml = yamlVersions.filter(v => !instSet.has(v))
140+
const onlyInInst = instVersions.filter(v => !yamlSet.has(v))
141+
142+
const opts = { colors: true }
143+
return [
144+
`Versions only in YAML: ${util.inspect(onlyInYaml, opts)}`,
145+
`Versions only in INST: ${util.inspect(onlyInInst, opts)}`
146+
].join('\n')
147+
}
148+
149+
function errorMsg (pluginName, title, message) {
150+
console.log('===========================================')
151+
console.log(title + ' for ' + pluginName)
152+
console.log('-------------------------------------------')
153+
console.log(message)
154+
console.log('\n')
155+
process.exitCode = 1
156+
}

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5252,6 +5252,11 @@ yaml@^1.10.2:
52525252
resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
52535253
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
52545254

5255+
yaml@^2.5.0:
5256+
version "2.5.0"
5257+
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.0.tgz#c6165a721cf8000e91c36490a41d7be25176cf5d"
5258+
integrity sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==
5259+
52555260
yargs-parser@20.2.4:
52565261
version "20.2.4"
52575262
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz"

0 commit comments

Comments
 (0)