Skip to content

Commit

Permalink
Build script with repo package manifest and release ordering (microso…
Browse files Browse the repository at this point in the history
…ft#3658)

Co-authored-by: Sumedh Bhattacharya <[email protected]>
  • Loading branch information
sumedhb1995 and Sumedh Bhattacharya authored Sep 17, 2020
1 parent 7e7d08d commit 680dcc6
Show file tree
Hide file tree
Showing 16 changed files with 236 additions and 121 deletions.
39 changes: 39 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,44 @@
"rimraf": "^2.6.2",
"run-script-os": "^1.0.7",
"typescript": "~3.7.4"
},
"fluidBuild": {
"repoPackages": {
"client": [
{
"directory": "common"
},
{
"directory": "tools/generator-fluid"
}
],
"server": {
"required": [
{
"directory": "server/tinylicious"
}
],
"optional": [
{
"directory": "server",
"ignoredDirs": [
"routerlicious"
]
}
]
}
},
"serverPath": "server/routerlicious",
"releaseOrder": {
"preRepo": [
["@fluidframework/eslint-config-fluid", "@fluidframework/build-common"],
["@fluidframework/common-definitions"],
["@fluidframework/common-utils"]
],
"postRepo": [
["generator-fluid", "tinylicious"]
]
},
"generatorName": "generator-fluid"
}
}
62 changes: 41 additions & 21 deletions tools/build-tools/src/bumpVersion/bumpVersion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@
import * as path from "path";
import { commonOptions, commonOptionString, parseOption } from "../common/commonOptions";
import { Timer } from "../common/timer";
import { getResolvedFluidRoot } from "../common/fluidUtils";
import { FluidRepoBase } from "../common/fluidRepoBase";
import { getResolvedFluidRoot, getPackageManifest } from "../common/fluidUtils";
import { FluidRepo, IPackageManifest } from "../common/fluidRepo";
import { MonoRepo, MonoRepoKind } from "../common/monoRepo";
import * as semver from "semver";
import { Package } from "../common/npmPackage";
import { logVerbose } from "../common/logging";
import { GitRepo, fatal, exec, execNoError } from "./utils";
import * as os from "os";
import { assert } from "console";

function printUsage() {
console.log(
Expand Down Expand Up @@ -46,8 +47,6 @@ let paramVersion: semver.SemVer | undefined;
let paramBumpName: string | undefined;
let paramBumpVersion: VersionChangeType | undefined;

const generatorFluidPackageName = "generator-fluid";

function parseNameVersion(arg: string | undefined) {
let name = arg;
let extra = false;
Expand Down Expand Up @@ -442,10 +441,11 @@ class ReferenceVersionBag extends VersionBag {

class BumpVersion {
private readonly timer: Timer;
private readonly repo: FluidRepoBase;
private readonly repo: FluidRepo;
private readonly fullPackageMap: Map<string, Package>;
private readonly generatorPackage: Package;
private readonly templatePackage: Package;
private readonly packageManifest: IPackageManifest;
private readonly newBranches: string[] = [];
private readonly newTags: string[] = [];

Expand All @@ -457,14 +457,16 @@ class BumpVersion {
this.timer = new Timer(commonOptions.timer);

// Load the package
this.repo = new FluidRepoBase(this.gitRepo.resolvedRoot, false);
this.repo = new FluidRepo(this.gitRepo.resolvedRoot, false);
this.timer.time("Package scan completed");

this.fullPackageMap = this.repo.createPackageMap();
this.packageManifest = getPackageManifest(this.repo.resolvedRoot);

// TODO: Is there a way to generate this automatically?
const generatorPackage = this.fullPackageMap.get(generatorFluidPackageName);
if (!generatorPackage) { fatal(`Unable to find ${generatorFluidPackageName} package`) };
if (!this.packageManifest.generatorName) { fatal(`Unable to find generator package name in package.json`)}
const generatorPackage = this.fullPackageMap.get(this.packageManifest.generatorName);
if (!generatorPackage) { fatal(`Unable to find ${this.packageManifest.generatorName} package`) };
this.generatorPackage = generatorPackage;
this.templatePackage = new Package(path.join(generatorPackage.directory, "app", "templates", "package.json"));
}
Expand Down Expand Up @@ -563,7 +565,8 @@ class BumpVersion {
if (releaseName === MonoRepoKind[MonoRepoKind.Client]) {
processMonoRepo(this.repo.clientMonoRepo);
} else if (releaseName === MonoRepoKind[MonoRepoKind.Server]) {
processMonoRepo(this.repo.serverMonoRepo);
assert(this.repo.serverMonoRepo, "Attempted to collect server info on a Fluid repo with no server directory");
processMonoRepo(this.repo.serverMonoRepo!);
} else {
const pkg = this.fullPackageMap.get(releaseName);
if (!pkg) {
Expand Down Expand Up @@ -648,7 +651,8 @@ class BumpVersion {
if (name === MonoRepoKind[MonoRepoKind.Client]) {
await processMonoRepo(this.repo.clientMonoRepo);
} else if (name === MonoRepoKind[MonoRepoKind.Server]) {
await processMonoRepo(this.repo.serverMonoRepo);
assert(this.repo.serverMonoRepo, "Attempted show server versions on a Fluid repo with no server directory");
await processMonoRepo(this.repo.serverMonoRepo!);
} else {
pkg = this.fullPackageMap.get(name);
if (!pkg) {
Expand Down Expand Up @@ -679,7 +683,8 @@ class BumpVersion {

if (serverNeedBump) {
console.log(" Bumping server version");
await bumpMonoRepo(this.repo.serverMonoRepo);
assert(this.repo.serverMonoRepo, "Attempted server version bump on a Fluid repo with no server directory");
await bumpMonoRepo(this.repo.serverMonoRepo!);
}

for (const pkg of packageNeedBump) {
Expand Down Expand Up @@ -1006,13 +1011,13 @@ class BumpVersion {
}

/**
* Create release branch based on the repo state, bump minor version immediately
* Create release branch based on the repo state, bump minor version immediately
* and push it to `main` and the new release branch to remote
*/
public async createReleaseBranch() {
// Create release branch based on client version
const releaseName = MonoRepoKind[MonoRepoKind.Client];

const depVersions = await this.collectBumpInfo(releaseName);
const releaseVersion = depVersions.repoVersions.get(releaseName);
if (!releaseVersion) {
Expand Down Expand Up @@ -1115,13 +1120,27 @@ class BumpVersion {
await this.createBranch(pendingReleaseBranch);
}

// TODO: Don't hard code order
await this.releasePackage(depVersions, ["@fluidframework/eslint-config-fluid", "@fluidframework/build-common"]);
await this.releasePackage(depVersions, ["@fluidframework/common-definitions"]);
await this.releasePackage(depVersions, ["@fluidframework/common-utils"]);
await this.releaseMonoRepo(depVersions, this.repo.serverMonoRepo);
const preRepoPromises: Promise<void>[] = [];
if (this.packageManifest.releaseOrder?.preRepo !== undefined) {
this.packageManifest.releaseOrder.preRepo.forEach(async packages =>
preRepoPromises.push(this.releasePackage(depVersions, packages))
);
}
await Promise.all(preRepoPromises);

if (this.repo.serverMonoRepo) {
await this.releaseMonoRepo(depVersions, this.repo.serverMonoRepo);
}

await this.releaseMonoRepo(depVersions, this.repo.clientMonoRepo);
await this.releasePackage(depVersions, [generatorFluidPackageName, "tinylicious"]);

const postRepoPromises: Promise<void>[] = [];
if (this.packageManifest.releaseOrder?.postRepo !== undefined) {
this.packageManifest.releaseOrder.postRepo.forEach(async packages =>
postRepoPromises.push(this.releasePackage(depVersions, packages))
);
}
await Promise.all(postRepoPromises);

// ------------------------------------------------------------------------------------------------------------------
// Create the minor version bump for development in a temporary merge/<original branch> on top of the release commit
Expand Down Expand Up @@ -1173,7 +1192,8 @@ class BumpVersion {
}
} else if (name === MonoRepoKind[MonoRepoKind.Server]) {
serverNeedBump = true;
const ret = await this.repo.serverMonoRepo.install();
assert(this.repo.serverMonoRepo, "Attempted to bump server version on a Fluid repo with no server directory");
const ret = await this.repo.serverMonoRepo!.install();
if (ret.error) {
fatal("Install failed");
}
Expand Down Expand Up @@ -1241,7 +1261,7 @@ class BumpVersion {
if (updateLockPackage.length !== 0) {
if (updateLock) {
// Fix package lock
if (!await FluidRepoBase.ensureInstalled(updateLockPackage, false)) {
if (!await FluidRepo.ensureInstalled(updateLockPackage, false)) {
fatal("Install Failed");
}
} else {
Expand Down
113 changes: 113 additions & 0 deletions tools/build-tools/src/common/fluidRepo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*!
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/

import * as path from "path";
import { Package, Packages } from "./npmPackage";
import { MonoRepo, MonoRepoKind } from "./monoRepo";
import { getPackageManifest } from "./fluidUtils";
import { assert } from "console";

export interface IPackageManifest {
repoPackages: {
client: IFluidRepoPackage[],
server: {
required: IFluidRepoPackage[],
optional?: IFluidRepoPackage[],
}
},
serverPath?: string,
releaseOrder?: {
preRepo?: string[][],
postRepo?: string[][]
},
generatorName?: string
}

export interface IFluidRepoPackage {
directory: string,
ignoredDirs?: string[]
}

export class FluidRepo {
public readonly clientMonoRepo: MonoRepo;
public readonly serverMonoRepo?: MonoRepo;

public readonly packages: Packages;
constructor(public readonly resolvedRoot: string, services: boolean) {
const packageManifest = getPackageManifest(resolvedRoot);
this.clientMonoRepo = new MonoRepo(MonoRepoKind.Client, this.resolvedRoot);
if (packageManifest.serverPath) {
this.serverMonoRepo = new MonoRepo(MonoRepoKind.Server, path.join(this.resolvedRoot, packageManifest.serverPath));
}

let additionalPackages: Package[] = [];

packageManifest.repoPackages.client.forEach((fluidPackage: IFluidRepoPackage) => {
additionalPackages = [
...additionalPackages,
...Packages.loadDir(path.join(resolvedRoot, fluidPackage.directory), undefined, fluidPackage.ignoredDirs)
]
});

if (services) {
assert(packageManifest.repoPackages.server.optional, "Requested optional server packages without passing parameters in package.json");
packageManifest.repoPackages.server.optional!.forEach((fluidPackage: IFluidRepoPackage) => {
additionalPackages = [
...additionalPackages,
...Packages.loadDir(path.join(resolvedRoot, fluidPackage.directory), undefined, fluidPackage.ignoredDirs)
]
});
} else {
packageManifest.repoPackages.server.required.forEach((fluidPackage: IFluidRepoPackage) => {
additionalPackages = [
...additionalPackages,
...Packages.loadDir(path.join(resolvedRoot, fluidPackage.directory), undefined, fluidPackage.ignoredDirs)
]
});
}

this.packages = new Packages(
[
...this.clientMonoRepo.packages,
...(this.serverMonoRepo?.packages || []),
...additionalPackages,
]
);
}

public createPackageMap() {
return new Map<string, Package>(this.packages.packages.map(pkg => [pkg.name, pkg]));
}

public reload() {
this.packages.packages.forEach(pkg => pkg.reload());
}

public static async ensureInstalled(packages: Package[], check: boolean = true) {
const installedMonoRepo = new Set<MonoRepo>();
const installPromises: Promise<any>[] = [];
for (const pkg of packages) {
if (!check || !await pkg.checkInstall(false)) {
if (pkg.monoRepo) {
if (!installedMonoRepo.has(pkg.monoRepo)) {
installedMonoRepo.add(pkg.monoRepo);
installPromises.push(pkg.monoRepo.install());
}
} else {
installPromises.push(pkg.install());
}
}
}
const rets = await Promise.all(installPromises);
return !rets.some(ret => ret.error);
}

public async install(nohoist: boolean = false) {
if (nohoist) {
return this.packages.noHoistInstall(this.resolvedRoot);
}
return FluidRepo.ensureInstalled(this.packages.packages);
}
};
65 changes: 0 additions & 65 deletions tools/build-tools/src/common/fluidRepoBase.ts

This file was deleted.

Loading

0 comments on commit 680dcc6

Please sign in to comment.