Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 39 additions & 6 deletions bin/create-version-test-folders.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ function generateTestWrapper({
mode,
sourceDepth,
nodeConstraint,
verifyDependency
verifyDependency,
hasLockFile,
isTemplateLock
}) {
const currentYear = new Date().getFullYear();
const relSourcePath = sourceDepth === 2 ? '../..' : '..';
Expand Down Expand Up @@ -127,6 +129,8 @@ function copyParentFiles(dir, sourceDir) {
e.name !== 'node_modules' &&
e.name !== 'package.json' &&
!e.name.startsWith('package.json.template') &&
!e.name.startsWith('package-lock.json.v') &&
e.name !== 'package-lock.json.template' &&
e.name !== 'modes.json'
)
.forEach(e => {
Expand Down Expand Up @@ -227,11 +231,18 @@ mochaSuiteFn(suiteTitle, function () {
try {
rmDir(path.join(__dirname, 'node_modules'));

log('[INFO] Running npm install for ${suiteName}@${displayVersion}...');
${hasLockFile ? `\
const lockDir = path.resolve(__dirname, '${sourceDepth === 2 ? '../..' : '..'}');
const lockFileName = '${isTemplateLock ? 'package-lock.json.template' : `package-lock.json.v${rawVersion}`}';
const lockFileSrc = path.join(lockDir, lockFileName);
if (fs.existsSync(lockFileSrc)) {
fs.copyFileSync(lockFileSrc, path.join(__dirname, 'package-lock.json'));
}
` : ''} log('[INFO] Running npm install for ${suiteName}@${displayVersion}...');
const npmCmd = process.env.CI ?
'npm install --cache ${rootDir}/.npm-offline-cache --prefer-offline ' +
'--no-package-lock --no-audit --prefix ./ --no-progress' :
'npm install --no-package-lock --no-audit --prefix ./ --no-progress';
'${hasLockFile ? '' : '--no-package-lock '}--no-audit --prefix ./ --no-progress' :
'npm install ${hasLockFile ? '' : '--no-package-lock '}--no-audit --prefix ./ --no-progress';

for (let attempt = 0; attempt < maxRetries; attempt++) {
const timeout = 5 * 60 * 1000;
Expand Down Expand Up @@ -472,6 +483,9 @@ function main() {

createTgzSymlinks(targetDir);

const lockSrc = path.join(testDir, `package-lock.json.v${version}`);
const hasLockFile = fs.existsSync(lockSrc);

const testContent = generateTestWrapper({
suiteName: currency.name,
displayVersion: dirName.substring(1),
Expand All @@ -481,7 +495,8 @@ function main() {
mode,
sourceDepth: hasModes ? 2 : 1,
nodeConstraint,
verifyDependency: !skipValidation
verifyDependency: !skipValidation,
hasLockFile
});
const fileName = mode ? `${mode}.test.js` : 'default.test.js';
fs.writeFileSync(path.join(targetDir, fileName), testContent);
Expand All @@ -495,6 +510,15 @@ function main() {
isOptional,
majorVersion
});

if (hasLockFile) {
fs.copyFileSync(lockSrc, path.join(targetDir, 'package-lock.json'));
} else {
const tplLock = path.join(testDir, 'package-lock.json.template');
if (fs.existsSync(tplLock)) {
fs.copyFileSync(tplLock, path.join(targetDir, 'package-lock.json'));
}
}
});
});
});
Expand Down Expand Up @@ -535,6 +559,9 @@ function main() {

createTgzSymlinks(targetDir);

const tplLockNonCurrency = path.join(testDir, 'package-lock.json.template');
const hasLockFileNonCurrency = fs.existsSync(tplLockNonCurrency);

const testContent = generateTestWrapper({
suiteName: dirName,
displayVersion: version,
Expand All @@ -543,7 +570,9 @@ function main() {
esmOnly: false,
mode,
sourceDepth: hasModes ? 2 : 1,
verifyDependency: false
verifyDependency: false,
hasLockFile: hasLockFileNonCurrency,
isTemplateLock: true
});
const fileName = mode ? `${mode}.test.js` : 'default.test.js';
fs.writeFileSync(path.join(targetDir, fileName), testContent);
Expand All @@ -556,6 +585,10 @@ function main() {
currencyVersion: null,
isOptional: false
});

if (hasLockFileNonCurrency) {
fs.copyFileSync(tplLockNonCurrency, path.join(targetDir, 'package-lock.json'));
}
});
});
}
Expand Down
9 changes: 7 additions & 2 deletions bin/dependencies/currency/update-currencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,19 @@ currencies.forEach(originalCurrency => {

if (!DRY_RUN) {
fs.writeFileSync(currenciesPath, JSON.stringify(currencies, null, 2));
const lockCmd = isMajorUpdate
? `node bin/generate-lock-files.js --currency "${currency.name}" --version "${latestVersion}"`
: `node bin/generate-lock-files.js --currency "${currency.name}"` +
` --version "${latestVersion}" --from "${installedVersion}"`;
execSync(lockCmd, { cwd, stdio: 'inherit' });
} else {
console.log(`[DRY RUN] Updated currencies.json with ${currency.name} version ${latestVersion}`);
}

if (MAJOR_UPDATES_MODE) {
utils.commitAndCreatePR({
packageName: currency.name,
files: 'currencies.json',
files: "'currencies.json' 'packages/collector/test'",
currentVersion: installedVersion,
newVersion: latestVersion,
branchName,
Expand All @@ -150,7 +155,7 @@ currencies.forEach(originalCurrency => {
});
} else if (!DRY_RUN) {
try {
execSync("git add 'currencies.json'", { cwd });
execSync("git add 'currencies.json' 'packages/collector/test'", { cwd });
execSync(`git commit -m "build: bumped ${currency.name} from ${installedVersion} to ${latestVersion}"`, { cwd });
} catch (err) {
console.error(`[ERROR] Commit failed: ${err.message}`);
Expand Down
13 changes: 12 additions & 1 deletion bin/dependencies/production/update-prod-dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,20 @@ Object.entries(dependencyMap).some(([dep, usageList]) => {
});
});

const isInstanaDep = usageList.some(({ pkgRelDir }) =>
pkgRelDir.startsWith('packages/collector') ||
pkgRelDir.startsWith('packages/core') ||
pkgRelDir.startsWith('packages/shared-metrics')
);

if (isInstanaDep && !DRY_RUN) {
const { execSync } = require('child_process');
execSync('node bin/generate-lock-files.js', { cwd, stdio: 'inherit' });
}

const prCreated = utils.commitAndCreatePR({
packageName: dep,
files: "'*package.json' package-lock.json",
files: "'*package.json' package-lock.json 'packages/collector/test'",
currentVersion: currentVersion,
newVersion: latestVersion,
branchName,
Expand Down
230 changes: 230 additions & 0 deletions bin/generate-lock-files.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
#!/usr/bin/env node
/*
* (c) Copyright IBM Corp. 2026
*/

'use strict';

const { execSync } = require('child_process');
const fs = require('fs');
const os = require('os');
const path = require('path');

const rootDir = path.resolve(__dirname, '..');
const currenciesPath = path.join(rootDir, 'currencies.json');
const collectorTestDir = path.join(rootDir, 'packages', 'collector', 'test');

const currencyFilter = (() => {
const idx = process.argv.indexOf('--currency');
return idx !== -1 ? process.argv[idx + 1] : null;
})();

const versionFilter = (() => {
const idx = process.argv.indexOf('--version');
return idx !== -1 ? process.argv[idx + 1] : null;
})();

const fromVersion = (() => {
const idx = process.argv.indexOf('--from');
return idx !== -1 ? process.argv[idx + 1] : null;
})();

function getInstanaVersion() {
try {
return execSync('npm view @instana/collector version', { encoding: 'utf8' }).trim();
} catch (_) {
return null;
}
}

function findTestDirectories(baseDir, name) {
const results = [];
const parts = name.split('/');

function search(dir) {
let entries;
try {
entries = fs.readdirSync(dir, { withFileTypes: true });
} catch (_) {
return;
}
entries
.filter(entry => entry.isDirectory() && entry.name !== 'node_modules' && !entry.name.startsWith('_v'))
.forEach(entry => {
const full = path.join(dir, entry.name);
if (parts.length === 2) {
if (entry.name === parts[0]) {
const inner = path.join(full, parts[1]);
if (fs.existsSync(inner) && fs.statSync(inner).isDirectory()) {
results.push(inner);
}
}
} else if (entry.name === name) {
results.push(full);
}
search(full);
});
}

search(baseDir);
return results;
}

function generateLockFile(currencyName, version, testDir, instanaVersion, baseLockFile) {
const safeName = currencyName.replace(/\//g, '-').replace(/^@/, '');
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), `instana-lock-${safeName}-${version}-`));

try {
const dependencies = { [currencyName]: version };
if (instanaVersion) {
dependencies['@instana/collector'] = instanaVersion;
dependencies['@instana/core'] = instanaVersion;
dependencies['@instana/shared-metrics'] = instanaVersion;
}
const pkgJson = {
name: `lock-gen-${safeName}-v${version}`,
dependencies
};
fs.writeFileSync(path.join(tmpDir, 'package.json'), `${JSON.stringify(pkgJson, null, 2)}\n`);

if (baseLockFile && fs.existsSync(baseLockFile)) {
console.log(` Using ${path.basename(baseLockFile)} as base (incremental update)...`);
fs.copyFileSync(baseLockFile, path.join(tmpDir, 'package-lock.json'));
}

console.log(` Generating lock file for ${currencyName}@${version}...`);
execSync('npm install --package-lock-only --no-audit --no-progress', {
cwd: tmpDir,
stdio: 'inherit',
timeout: 5 * 60 * 1000
});

const lockSrc = path.join(tmpDir, 'package-lock.json');
if (!fs.existsSync(lockSrc)) {
console.warn(` WARNING: no package-lock.json generated for ${currencyName}@${version}`);
return;
}

fs.copyFileSync(lockSrc, path.join(testDir, `package-lock.json.v${version}`));
console.log(` Saved → ${path.relative(rootDir, path.join(testDir, `package-lock.json.v${version}`))}`);
} finally {
fs.rmSync(tmpDir, { recursive: true, force: true });
}
}

function removeOldLockFiles(testDir, keepVersions) {
fs.readdirSync(testDir)
.filter(f => f.startsWith('package-lock.json.v') && !keepVersions.includes(f.slice('package-lock.json.v'.length)))
.forEach(f => {
fs.rmSync(path.join(testDir, f));
console.log(` Removed → ${path.relative(rootDir, path.join(testDir, f))}`);
});
}

function generateLockFileFromTemplate(templatePath, instanaVersion) {
const testDir = path.dirname(templatePath);
const safeName = path.relative(collectorTestDir, testDir).replace(/[/@]/g, '-');
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), `instana-lock-tpl-${safeName}-`));

try {
const tpl = JSON.parse(fs.readFileSync(templatePath, 'utf8'));
const dependencies = {};
['dependencies', 'devDependencies', 'optionalDependencies'].forEach(section => {
if (!tpl[section]) return;
Object.entries(tpl[section]).forEach(([name, ver]) => {
if (!ver.startsWith('file:') && !ver.startsWith('{{')) {
dependencies[name] = ver;
}
});
});
if (instanaVersion) {
dependencies['@instana/collector'] = instanaVersion;
dependencies['@instana/core'] = instanaVersion;
dependencies['@instana/shared-metrics'] = instanaVersion;
}
if (Object.keys(dependencies).length === 0) return;

fs.writeFileSync(
path.join(tmpDir, 'package.json'),
`${JSON.stringify({ name: `lock-gen-tpl-${safeName}`, dependencies }, null, 2)}\n`
);

console.log(` Generating lock file for template ${path.relative(rootDir, templatePath)}...`);
execSync('npm install --package-lock-only --no-audit --no-progress', {
cwd: tmpDir,
stdio: 'inherit',
timeout: 5 * 60 * 1000
});

const lockSrc = path.join(tmpDir, 'package-lock.json');
if (!fs.existsSync(lockSrc)) {
console.warn(` WARNING: no package-lock.json generated for ${templatePath}`);
return;
}

fs.copyFileSync(lockSrc, path.join(testDir, 'package-lock.json.template'));
console.log(` Saved → ${path.relative(rootDir, path.join(testDir, 'package-lock.json.template'))}`);
} finally {
fs.rmSync(tmpDir, { recursive: true, force: true });
}
}

function findTemplateDirs(baseDir) {
const results = [];
function search(dir) {
let entries;
try {
entries = fs.readdirSync(dir, { withFileTypes: true });
} catch (_) {
return;
}
entries
.filter(e => e.isDirectory() && e.name !== 'node_modules' && !e.name.startsWith('_v'))
.forEach(e => {
search(path.join(dir, e.name));
});
const tpl = path.join(dir, 'package.json.template');
if (fs.existsSync(tpl)) results.push(tpl);
}
search(baseDir);
return results;
}

function main() {
const instanaVersion = getInstanaVersion();
if (instanaVersion) {
console.log(`Using @instana/collector@${instanaVersion} for lock file generation`);
}

const currencies = JSON.parse(fs.readFileSync(currenciesPath, 'utf8'));

currencies.forEach(currency => {
if (currencyFilter && currency.name !== currencyFilter) return;
if (!currency.versions || currency.versions.length === 0) return;

const testDirs = findTestDirectories(collectorTestDir, currency.name);
if (testDirs.length === 0) return;

console.log(`\n[${currency.name}]`);
const allVersions = currency.versions.map(v => (typeof v === 'string' ? v : v.v));
testDirs.forEach(testDir => {
allVersions.forEach(version => {
if (versionFilter && version !== versionFilter) return;
const baseLockFile = fromVersion
? path.join(testDir, `package-lock.json.v${fromVersion}`)
: null;
generateLockFile(currency.name, version, testDir, instanaVersion, baseLockFile);
});
removeOldLockFiles(testDir, allVersions);
});
});

if (!currencyFilter && !versionFilter) {
console.log('\n[templates]');
findTemplateDirs(collectorTestDir).forEach(tpl => {
generateLockFileFromTemplate(tpl, instanaVersion);
});
}
}

main();
Loading