Skip to content

Commit 7a1e8b3

Browse files
trentmpichlermarc
andauthored
chore: add 'lint:semconv-deps' (open-telemetry#2569)
Co-authored-by: Marc Pichler <[email protected]>
1 parent 58bc158 commit 7a1e8b3

File tree

2 files changed

+102
-2
lines changed

2 files changed

+102
-2
lines changed

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,15 @@
2020
"test:ci:changed": "nx affected -t test --base=origin/main --head=HEAD",
2121
"test-all-versions": "nx run-many -t test-all-versions",
2222
"changelog": "lerna-changelog",
23-
"lint": "nx run-many -t lint && npm run lint:readme && npm run lint:markdown",
23+
"lint": "nx run-many -t lint && npm run lint:readme && npm run lint:markdown && npm run lint:semconv-deps",
2424
"lint:fix": "nx run-many -t lint:fix && npm run lint:markdown:fix",
2525
"lint:deps": "npx --yes [email protected] --dependencies --production --tags=-knipignore",
2626
"lint:examples": "eslint ./examples/**/*.js",
2727
"lint:examples:fix": "eslint ./examples/**/*.js --fix",
2828
"lint:markdown": "markdownlint-cli2 $(git ls-files '*.md')",
2929
"lint:markdown:fix": "markdownlint-cli2 --fix $(git ls-files '*.md')",
30-
"lint:readme": "nx run-many -t lint:readme"
30+
"lint:readme": "nx run-many -t lint:readme",
31+
"lint:semconv-deps": "./scripts/lint-semconv-deps.mjs"
3132
},
3233
"keywords": [
3334
"opentelemetry",

scripts/lint-semconv-deps.mjs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#!/usr/bin/env node
2+
/*
3+
* Copyright The OpenTelemetry Authors
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
/**
19+
* Lint the usage of `@opentelemetry/semantic-conventions` in packages in
20+
* the workspace.
21+
*
22+
* See "Rule:" comments for things that are checked.
23+
*
24+
* Usage:
25+
* node scripts/lint-semconv-deps.js
26+
*/
27+
28+
import fs from 'fs';
29+
import path from 'path';
30+
import { fileURLToPath } from 'url';
31+
import { globSync } from 'glob';
32+
33+
const TOP = path.resolve(fileURLToPath(new URL('.', import.meta.url)), '..');
34+
const SEMCONV = '@opentelemetry/semantic-conventions';
35+
const USE_COLOR = process.stdout.isTTY && !process.env.NO_COLOR?.length > 0;
36+
37+
let numProbs = 0;
38+
function problem(...args) {
39+
numProbs += 1;
40+
if (USE_COLOR) {
41+
process.stdout.write('\x1b[31m');
42+
}
43+
args.unshift('lint-semconv-deps error:');
44+
console.log(...args);
45+
if (USE_COLOR) {
46+
process.stdout.write('\x1b[39m');
47+
}
48+
}
49+
50+
function getAllWorkspaceDirs() {
51+
const pj = JSON.parse(
52+
fs.readFileSync(path.join(TOP, 'package.json'), 'utf8')
53+
);
54+
return pj.workspaces
55+
.map((wsGlob) => globSync(path.join(wsGlob, 'package.json')))
56+
.flat()
57+
.map(path.dirname);
58+
}
59+
60+
function lintSemconvDeps() {
61+
const wsDirs = getAllWorkspaceDirs();
62+
63+
for (let wsDir of wsDirs) {
64+
const pj = JSON.parse(
65+
fs.readFileSync(path.join(wsDir, 'package.json'), 'utf8')
66+
);
67+
const depRange = pj?.dependencies?.[SEMCONV];
68+
const devDepRange = pj?.devDependencies?.[SEMCONV];
69+
if (!(depRange || devDepRange)) {
70+
continue;
71+
}
72+
73+
// Rule: The semconv dep should *not* be pinned. Expect `^X.Y.Z`.
74+
const pinnedVerRe = /^\d+\.\d+\.\d+$/;
75+
if (depRange && pinnedVerRe.exec(depRange)) {
76+
problem(`${wsDir}/package.json: package ${pj.name} pins "${SEMCONV}" in dependencies, but should not (see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#why-not-pin-the-version)`);
77+
} else if (devDepRange && pinnedVerRe.exec(devDepRange)) {
78+
problem(`${wsDir}/package.json: package ${pj.name} pins "${SEMCONV}" in devDependencies, but should not (see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#why-not-pin-the-version)`);
79+
}
80+
81+
// Rule: The incubating entry-point should not be used.
82+
const srcFiles = globSync(path.join(wsDir, 'src', '**', '*.ts'));
83+
const usesIncubatingRe = /import\s+\{?[^{;]*\s+from\s+'@opentelemetry\/semantic-conventions\/incubating'/s;
84+
for (let srcFile of srcFiles) {
85+
const srcText = fs.readFileSync(srcFile, 'utf8');
86+
const match = usesIncubatingRe.exec(srcText);
87+
if (match) {
88+
problem(`${srcFile}: uses the 'incubating' entry-point from '@opentelemetry/semantic-conventions', but should not (see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#unstable-semconv)`)
89+
}
90+
}
91+
}
92+
}
93+
94+
// mainline
95+
await lintSemconvDeps();
96+
if (numProbs > 0) {
97+
process.exitCode = 1;
98+
}
99+

0 commit comments

Comments
 (0)