Skip to content

Commit

Permalink
Verify yaml (#4639)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
bengl authored Dec 13, 2024
1 parent 69b27b3 commit baf22d9
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 62 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/appsec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ jobs:
version:
- 18
- latest
range: ['9.5.0', '11.1.4', '13.2.0', '>=14.0.0 <=14.2.6', '>=14.2.7 <15', '>=15.0.0']
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']
runs-on: ubuntu-latest
env:
PLUGINS: next
Expand Down
75 changes: 20 additions & 55 deletions .github/workflows/plugins.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,54 +15,30 @@ concurrency:


jobs:
aerospike-node-16:
runs-on: ubuntu-latest
services:
aerospike:
image: aerospike:ce-5.7.0.15
ports:
- "127.0.0.1:3000-3002:3000-3002"
env:
PLUGINS: aerospike
SERVICES: aerospike
PACKAGE_VERSION_RANGE: '>=4.0.0 <5.2.0'
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/testagent/start
- uses: ./.github/actions/node/setup
- id: pkg
run: |
content=`cat ./package.json | tr '\n' ' '`
echo "json=$content" >> $GITHUB_OUTPUT
- id: extract
run: |
version="${{fromJson(steps.pkg.outputs.json).version}}"
majorVersion=$(echo "$version" | cut -d '.' -f 1)
echo "Major Version: $majorVersion"
echo "MAJOR_VERSION=$majorVersion" >> $GITHUB_ENV
- uses: ./.github/actions/node/oldest
- name: Install dependencies
if: env.MAJOR_VERSION == '4'
uses: ./.github/actions/install
- name: Run tests
if: env.MAJOR_VERSION == '4'
run: yarn test:plugins:ci
- if: always()
uses: ./.github/actions/testagent/logs
- uses: codecov/codecov-action@v3

aerospike-node-18-20:
aerospike:
strategy:
matrix:
node-version: [18]
range: ['5.2.0 - 5.7.0']
node-version: [16]
range: ['>=4.0.0 <5.2.0']
aerospike-image: [ce-5.7.0.15]
test-image: [ubuntu-latest]
include:
- node-version: 18
range: '>=5.2.0'
aerospike-image: ce-6.4.0.3
test-image: ubuntu-latest
- node-version: 20
range: '>=5.8.0'
runs-on: ubuntu-latest
range: '>=5.5.0'
aerospike-image: ce-6.4.0.3
test-image: ubuntu-latest
- node-version: 22
range: '>=5.12.1'
aerospike-image: ce-6.4.0.3
test-image: ubuntu-latest
runs-on: ${{ matrix.test-image }}
services:
aerospike:
image: aerospike:ce-6.4.0.3
image: aerospike:${{ matrix.aerospike-image }}
ports:
- "127.0.0.1:3000-3002:3000-3002"
env:
Expand All @@ -73,24 +49,13 @@ jobs:
- uses: actions/checkout@v4
- uses: ./.github/actions/testagent/start
- uses: ./.github/actions/node/setup
- id: pkg
run: |
content=`cat ./package.json | tr '\n' ' '`
echo "json=$content" >> $GITHUB_OUTPUT
- id: extract
run: |
version="${{fromJson(steps.pkg.outputs.json).version}}"
majorVersion=$(echo "$version" | cut -d '.' -f 1)
echo "Major Version: $majorVersion"
echo "MAJOR_VERSION=$majorVersion" >> $GITHUB_ENV
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: yarn config set ignore-engines true
- name: Install dependencies
if: env.MAJOR_VERSION == '5'
uses: ./.github/actions/install
- name: Run tests
if: env.MAJOR_VERSION == '5'
run: yarn test:plugins:ci
- if: always()
uses: ./.github/actions/testagent/logs
Expand Down Expand Up @@ -759,7 +724,7 @@ jobs:
version:
- 18
- latest
range: ['9.5.0', '11.1.4', '13.2.0', '>=14.0.0 <=14.2.6', '>=14.2.7 <15', '>=15.0.0']
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']
runs-on: ubuntu-latest
env:
PLUGINS: next
Expand Down
7 changes: 7 additions & 0 deletions .github/workflows/project.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,10 @@ jobs:
- run: yarn type:test
- run: yarn type:doc

verify-yaml:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/node/setup
- uses: ./.github/actions/install
- run: node scripts/verify-ci-config.js
1 change: 1 addition & 0 deletions LICENSE-3rdparty.csv
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ dev,sinon,BSD-3-Clause,Copyright 2010-2017 Christian Johansen
dev,sinon-chai,WTFPL and BSD-2-Clause,Copyright 2004 Sam Hocevar 2012–2017 Domenic Denicola
dev,tap,ISC,Copyright 2011-2022 Isaac Z. Schlueter and Contributors
dev,tiktoken,MIT,Copyright (c) 2022 OpenAI, Shantanu Jain
dev,yaml,ISC,Copyright Eemeli Aro <[email protected]>
file,aws-lambda-nodejs-runtime-interface-client,Apache 2.0,Copyright 2019 Amazon.com Inc. or its affiliates. All Rights Reserved.
file,profile.proto,Apache license 2.0,Copyright 2016 Google Inc.
file,is-git-url,MIT,Copyright (c) 2017 Jon Schlinkert.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@
"sinon": "^16.1.3",
"sinon-chai": "^3.7.0",
"tap": "^16.3.7",
"tiktoken": "^1.0.15"
"tiktoken": "^1.0.15",
"yaml": "^2.5.0"
}
}
2 changes: 1 addition & 1 deletion packages/datadog-instrumentations/src/aerospike.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function wrapProcess (process) {
addHook({
name: 'aerospike',
file: 'lib/commands/command.js',
versions: ['^3.16.2', '4', '5']
versions: ['4', '5']
},
commandFactory => {
return shimmer.wrapFunction(commandFactory, f => wrapCreateCommand(f))
Expand Down
11 changes: 7 additions & 4 deletions packages/datadog-instrumentations/src/next.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

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

const startChannel = channel('apm:next:request:start')
const finishChannel = channel('apm:next:request:finish')
Expand Down Expand Up @@ -221,7 +220,7 @@ addHook({

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

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

addHook({ name: 'next', versions: ['>=11.1 <13.2'], file: 'dist/server/next-server.js' }, nextServer => {
addHook({
name: 'next',
versions: ['>=11.1 <13.2'],
file: 'dist/server/next-server.js'
}, nextServer => {
const Server = nextServer.default
shimmer.wrap(Server.prototype, 'handleApiRequest', wrapHandleApiRequest)
return nextServer
})

addHook({
name: 'next',
versions: DD_MAJOR >= 4 ? ['>=10.2 <11.1'] : ['>=9.5 <11.1'],
versions: ['>=10.2 <11.1'],
file: 'dist/next-server/server/next-server.js'
}, nextServer => {
const Server = nextServer.default
Expand Down
156 changes: 156 additions & 0 deletions scripts/verify-ci-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
'use strict'
/* eslint-disable no-console */

const fs = require('fs')
const path = require('path')
const util = require('util')
const proxyquire = require('proxyquire')
const yaml = require('yaml')
const semver = require('semver')
const { execSync } = require('child_process')
const Module = require('module')
if (!Module.isBuiltin) {
Module.isBuiltin = mod => Module.builtinModules.includes(mod)
}

const nodeMajor = Number(process.versions.node.split('.')[0])

const names = fs.readdirSync(path.join(__dirname, '..', 'packages', 'datadog-instrumentations', 'src'))
.filter(file => file.endsWith('.js'))
.map(file => file.slice(0, -3))

const instrumentations = names.reduce((acc, key) => {
let instrumentations = []
const name = key

try {
loadInstFile(`${name}/server.js`, instrumentations)
loadInstFile(`${name}/client.js`, instrumentations)
} catch (e) {
loadInstFile(`${name}.js`, instrumentations)
}

instrumentations = instrumentations.filter(i => i.versions)
if (instrumentations.length) {
acc[key] = instrumentations
}

return acc
}, {})

const versions = {}

function checkYaml (yamlPath) {
const yamlContent = yaml.parse(fs.readFileSync(yamlPath, 'utf8'))

const rangesPerPluginFromYaml = {}
const rangesPerPluginFromInst = {}
for (const jobName in yamlContent.jobs) {
const job = yamlContent.jobs[jobName]
if (!job.env || !job.env.PLUGINS) continue

const pluginName = job.env.PLUGINS
if (Module.isBuiltin(pluginName)) continue
const rangesFromYaml = getRangesFromYaml(job)
if (rangesFromYaml) {
if (!rangesPerPluginFromYaml[pluginName]) {
rangesPerPluginFromYaml[pluginName] = new Set()
}
rangesFromYaml.forEach(range => rangesPerPluginFromYaml[pluginName].add(range))
const plugin = instrumentations[pluginName]
const allRangesForPlugin = new Set(plugin.map(x => x.versions).flat())
rangesPerPluginFromInst[pluginName] = allRangesForPlugin
}
}
for (const pluginName in rangesPerPluginFromYaml) {
const yamlRanges = Array.from(rangesPerPluginFromYaml[pluginName])
const instRanges = Array.from(rangesPerPluginFromInst[pluginName])
const yamlVersions = getMatchingVersions(pluginName, yamlRanges)
const instVersions = getMatchingVersions(pluginName, instRanges)
if (!util.isDeepStrictEqual(yamlVersions, instVersions)) {
const opts = { colors: true }
const colors = x => util.inspect(x, opts)
errorMsg(pluginName, 'Mismatch', `
Valid version ranges from YAML: ${colors(yamlRanges)}
Valid version ranges from INST: ${colors(instRanges)}
${mismatching(yamlVersions, instVersions)}
Note that versions may be dependent on Node.js version. This is Node.js v${colors(nodeMajor)}
> These don't match the same sets of versions in npm.
>
> Please check ${yamlPath} and the instrumentations
> for ${pluginName} to see that the version ranges match.`.trim())
}
}
}

function loadInstFile (file, instrumentations) {
const instrument = {
addHook (instrumentation) {
instrumentations.push(instrumentation)
}
}

const instPath = path.join(__dirname, `../packages/datadog-instrumentations/src/${file}`)

proxyquire.noPreserveCache()(instPath, {
'./helpers/instrument': instrument,
'../helpers/instrument': instrument
})
}

function getRangesFromYaml (job) {
// eslint-disable-next-line no-template-curly-in-string
if (job.env && job.env.PACKAGE_VERSION_RANGE && job.env.PACKAGE_VERSION_RANGE !== '${{ matrix.range }}') {
errorMsg(job.env.PLUGINS, 'ERROR in YAML', 'You must use matrix.range instead of env.PACKAGE_VERSION_RANGE')
process.exitCode = 1
}
if (job.strategy && job.strategy.matrix && job.strategy.matrix.range) {
const possibilities = [job.strategy.matrix]
if (job.strategy.matrix.include) {
possibilities.push(...job.strategy.matrix.include)
}
return possibilities.map(possibility => {
if (possibility.range) {
return [possibility.range].flat()
} else {
return undefined
}
}).flat()
}

return null
}

function getMatchingVersions (name, ranges) {
if (!versions[name]) {
versions[name] = JSON.parse(execSync('npm show ' + name + ' versions --json').toString())
}
return versions[name].filter(version => ranges.some(range => semver.satisfies(version, range)))
}

checkYaml(path.join(__dirname, '..', '.github', 'workflows', 'plugins.yml'))
checkYaml(path.join(__dirname, '..', '.github', 'workflows', 'appsec.yml'))

function mismatching (yamlVersions, instVersions) {
const yamlSet = new Set(yamlVersions)
const instSet = new Set(instVersions)

const onlyInYaml = yamlVersions.filter(v => !instSet.has(v))
const onlyInInst = instVersions.filter(v => !yamlSet.has(v))

const opts = { colors: true }
return [
`Versions only in YAML: ${util.inspect(onlyInYaml, opts)}`,
`Versions only in INST: ${util.inspect(onlyInInst, opts)}`
].join('\n')
}

function errorMsg (pluginName, title, message) {
console.log('===========================================')
console.log(title + ' for ' + pluginName)
console.log('-------------------------------------------')
console.log(message)
console.log('\n')
process.exitCode = 1
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5252,6 +5252,11 @@ yaml@^1.10.2:
resolved "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz"
integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==

yaml@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.5.0.tgz#c6165a721cf8000e91c36490a41d7be25176cf5d"
integrity sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==

[email protected]:
version "20.2.4"
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz"
Expand Down

0 comments on commit baf22d9

Please sign in to comment.