Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix dev build script to update dependencies acc to semver #6157

Merged
merged 13 commits into from
Nov 15, 2019
23 changes: 23 additions & 0 deletions eng/tools/versioning/VersionUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,28 @@ async function writePackageJson(filename, contentObject) {
}
}

//This gets the list of rush packages as well as their packageJsons
//This is specifically used in set-dev-dependencies script
const getRushPackageJsons = async repoRoot => {
const rushPath = path.resolve(path.join(repoRoot, "rush.json"));
const baseDir = path.dirname(rushPath);
const rushJson = parse(await readFile(rushPath, "utf8"));
const packageData = {};

for (const proj of rushJson.projects) {
const filePath = path.join(baseDir, proj.projectFolder, "package.json");
const packageJson = parse(await readFile(filePath, "utf8"));
packageData[packageJson.name] = {
src: filePath,
json: packageJson,
versionPolicy: proj.versionPolicyName,
projectFolder: proj.projectFolder,
newVer: undefined
};
}
return packageData;
};

async function getRushSpec(repoRoot) {
const rushPath = path.resolve(path.join(repoRoot, "rush.json"));
return await readFileJson(rushPath);
Expand Down Expand Up @@ -80,3 +102,4 @@ module.exports.writeFile = writeFile;
module.exports.writePackageJson = writePackageJson;
module.exports.getRushSpec = getRushSpec;
module.exports.updatePackageConstants = updatePackageConstants;
module.exports.getRushPackageJsons = getRushPackageJsons;
200 changes: 163 additions & 37 deletions eng/tools/versioning/set-dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,54 +23,180 @@ const path = require("path");
const semver = require("semver");
const versionUtils = require("./VersionUtils");

function getDevVersion(currentVersion, buildId) {
const commitChanges = async (rushPackages, package) => {
// Commit the new version to the JSON document
if (rushPackages[package].newVer) {
rushPackages[package].json.version = rushPackages[package].newVer;
}
try {
// Write out the JSON document to disk
await versionUtils.writePackageJson(
rushPackages[package].src,
rushPackages[package].json
);
console.info(
"File " +
rushPackages[package].src +
" created successfully with Node.js v10 fs/promises!"
);
} catch (e) {
console.error(e);
}
};

const updatePackageVersion = (rushPackages, package, buildId) => {
const currentVersion = rushPackages[package].json.version;
const parsedVersion = semver.parse(currentVersion);
return `${parsedVersion.major}.${parsedVersion.minor}.${parsedVersion.patch}-dev.${buildId}`;
}
rushPackages[package].newVer = `${parsedVersion.major}.${parsedVersion.minor}.${parsedVersion.patch}-dev.${buildId}`;
console.log(`version updated for ${package}`);
for (const pkg of Object.keys(rushPackages)) {
rushPackages = updateOtherProjectDependencySections(rushPackages, pkg,package);
}
return rushPackages;
};

async function main(argv) {
const buildId = argv["build-id"];
const repoRoot = argv["repo-root"];
const service = argv["service"];
const updateDependencySection = (rushPackages, dependencySection, buildId) => {
//console.log(dependencySection);
if (dependencySection) {
for (const [depName, depVersionRange] of Object.entries(
dependencySection
)) {
console.log(`checking ${depName}:${depVersionRange}...`);

var rushSpec = await versionUtils.getRushSpec(repoRoot);
// If the dependency isn't part of the Rush workspace, skip it
if (!rushPackages[depName]) {
continue;
}

console.log(`Updating packages with Build ID ${buildId}`);
// Compare the dependency version range with the package's current version
const packageVersion = rushPackages[depName].json.version;

const scopedPackages = rushSpec.projects.filter(package =>
service ? package.projectFolder.startsWith(`sdk/${service}`) : true
);
console.log(`version in package's dep = ${depVersionRange}`); //^1.0.0
console.log(`dep's version = ${packageVersion}`); //1.0.0

let appropriateVersionedPackages = scopedPackages.filter(
package =>
package.versionPolicyName == "core" ||
package.versionPolicyName == "client"
const parsedPackageVersion = semver.parse(packageVersion);
const parsedDepMinVersion = semver.minVersion(depVersionRange);

if (
parsedDepMinVersion.major == parsedPackageVersion.major &&
parsedDepMinVersion.minor == parsedPackageVersion.minor &&
parsedDepMinVersion.patch == parsedPackageVersion.patch
) {
rushPackages = updatePackageVersion(rushPackages,depName,buildId);
}
}
}
return rushPackages;
};

const updateInternalDependencyVersions = (rushPackages, package, buildId) => {
console.log("updateInternalDep");
console.log(package);
console.log("checking dependencies ..");
rushPackages = updateDependencySection(
rushPackages,
rushPackages[package].json.dependencies,
buildId
);

console.log(appropriateVersionedPackages);
console.log("checking devDependencies ..");
rushPackages = updateDependencySection(
rushPackages,
rushPackages[package].json.devDependencies,
buildId
);

let targetPackages = appropriateVersionedPackages.map(project =>
path.resolve(path.join(repoRoot, project.projectFolder))
console.log("checking peerDependencies ..");
rushPackages = updateDependencySection(
rushPackages,
rushPackages[package].json.peerDependencies,
buildId
);

for (const targetFolder of targetPackages) {
const targetPackageJson = path.join(targetFolder, "package.json");
const packageJsonContents = await versionUtils.readFileJson(
targetPackageJson
);
const newVersion = getDevVersion(packageJsonContents.version, buildId);
console.log(`File ${targetPackageJson} version updated to ${newVersion}`);
const updatedPackageSpec = {
...packageJsonContents,
version: newVersion
};
await versionUtils.writePackageJson(targetPackageJson, updatedPackageSpec);

await versionUtils.updatePackageConstants(
targetFolder,
packageJsonContents,
newVersion
);
return rushPackages;
};

const makeDependencySectionConsistentForPackage = (rushPackages, dependencySection, depName) => {
console.log("Inside make dep");
if (dependencySection && dependencySection[depName]) {
depVersionRange = dependencySection[depName];

console.log(`checking ${depName}:${depVersionRange}...`);

// If the dependency isn't part of the Rush workspace, skip it
if (!rushPackages[depName]) {
return rushPackages;
}

// Compare the dependency version range with the package's current version
const packageVersion = rushPackages[depName].json.version;

console.log(`version in package's dep = ${depVersionRange}`);
console.log(`dep's version = ${packageVersion}`);
const parsedPackageVersion = semver.parse(packageVersion);
const parsedDepMinVersion = semver.minVersion(depVersionRange);
// If the dependency range is satisfied by the package's current version,
// replace it with an exact match to the package's new version
if (
parsedDepMinVersion.major == parsedPackageVersion.major &&
parsedDepMinVersion.minor == parsedPackageVersion.minor &&
parsedDepMinVersion.patch == parsedPackageVersion.patch &&
rushPackages[depName].newVer !== undefined
) {

// Setting version to ^[major.minor.patch]-dev so that this automatically matches
// with the latest dev version published on npm
dependencySection[depName] = `^${parsedPackageVersion.major}.${parsedPackageVersion.minor}.${parsedPackageVersion.patch}-dev`;
}
}
return rushPackages;
};

const updateOtherProjectDependencySections = (rushPackages, package,depName) => {
console.log("updateOtherProjectDependencySections");
console.log("package = "+ package);
console.log("depName="+depName);
console.log("checking dependencies ..");

rushPackages = makeDependencySectionConsistentForPackage(rushPackages, rushPackages[package].json.dependencies,depName);

console.log("checking devDependencies ..");
rushPackages = makeDependencySectionConsistentForPackage(rushPackages, rushPackages[package].json.devDependencies,depName);

console.log("checking peerDependencies ..");
rushPackages = makeDependencySectionConsistentForPackage(rushPackages, rushPackages[package].json.peerDependencies,depName);
return rushPackages;
};

async function main(argv) {
const buildId = argv["build-id"];
const repoRoot = argv["repo-root"];
const service = argv["service"];

var rushPackages = await versionUtils.getRushPackageJsons(repoRoot);

let targetPackages = [];
for (const package of Object.keys(rushPackages)) {
if (
["client", "core"].includes(rushPackages[package].versionPolicy) &&
rushPackages[package].projectFolder.startsWith(`sdk/${service}`)
) {
targetPackages.push(package);
}
}

// Set all the new versions & update any references to internal projects with the new versions
console.log(`Updating packages with build ID ${buildId}`);
for (const package of targetPackages) {
console.log("package updated = ");
console.log(package);
rushPackages = updatePackageVersion(rushPackages, package, buildId);
rushPackages = updateInternalDependencyVersions(rushPackages,package,buildId);
console.log(rushPackages[package].newVer);
}

for (const package of Object.keys(rushPackages)) {
await commitChanges(rushPackages, package);
}
}

Expand Down