Skip to content

Commit 052e6df

Browse files
committed
(layer compat) Add auto generation update logic to release tools
1 parent ff4e1c5 commit 052e6df

File tree

4 files changed

+633
-507
lines changed

4 files changed

+633
-507
lines changed

build-tools/packages/build-cli/src/handlers/doFunctions.ts

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55

66
import { strict as assert } from "node:assert";
7+
import { readFile, writeFile } from "node:fs/promises";
78
import type { Machine } from "jssm";
89
import chalk from "picocolors";
910

@@ -191,3 +192,109 @@ export const doReleaseGroupBump: StateHandlerFunction = async (
191192
BaseStateHandler.signalSuccess(machine, state);
192193
return true;
193194
};
195+
196+
/**
197+
* Updates the generation used for layer compatibility.
198+
*
199+
* @param state - The current state machine state.
200+
* @param machine - The state machine.
201+
* @param testMode - Set to true to run function in test mode.
202+
* @param log - A logger that the function can use for logging.
203+
* @param data - An object with handler-specific contextual data.
204+
* @returns True if the state was handled; false otherwise.
205+
*/
206+
export const doLayerGenerationUpdate: StateHandlerFunction = async (
207+
state: MachineState,
208+
machine: Machine<unknown>,
209+
testMode: boolean,
210+
log: CommandLogger,
211+
data: FluidReleaseStateHandlerData,
212+
): Promise<boolean> => {
213+
if (testMode) return true;
214+
215+
const { bumpType } = data;
216+
if (bumpType === "patch") {
217+
log.info(`Generation update is not needed for patch release`);
218+
BaseStateHandler.signalSuccess(machine, state);
219+
return true;
220+
}
221+
222+
log.info(`Updating layerGeneration.ts for a ${bumpType} release`);
223+
224+
// eslint-disable-next-line no-warning-comments
225+
// TODO: Is it okay to read a file from this folder?
226+
// The file that stores information of the current generation and release date.
227+
const filename = "packages/common/client-utils/src/layerGeneration.ts";
228+
229+
// eslint-disable-next-line no-warning-comments
230+
// TODO: This should ideally be read from a common location in client utils. What is the best way to do this?
231+
// The minimum compatibility window in months that is supported across all layers.
232+
const minimumCompatWindowMonths = 3;
233+
234+
const today = new Date();
235+
let previousGeneration = -1;
236+
let newGeneration = 1;
237+
238+
let fileContents: string | undefined;
239+
try {
240+
fileContents = await readFile(filename, "utf8");
241+
} catch {
242+
log.info(`File ${filename} doesn't exist yet`);
243+
}
244+
245+
if (fileContents !== undefined) {
246+
const match = fileContents.match(
247+
/.*\nexport const generation = (\d+);[\n\r]*export const releaseDate = "((0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(19|20)\d{2})";.*/m,
248+
);
249+
if (match === null) {
250+
log.errorLog(`${filename} content not as expected`);
251+
BaseStateHandler.signalFailure(machine, state);
252+
return false;
253+
}
254+
255+
previousGeneration = Number(match[1]);
256+
const previousReleaseDateString = match[2];
257+
const previousReleaseDate = new Date(previousReleaseDateString);
258+
const daysBetweenReleases = Math.round(
259+
(today.getTime() - previousReleaseDate.getTime()) / (1000 * 60 * 60 * 24),
260+
);
261+
262+
const monthsBetweenReleases = Math.floor(daysBetweenReleases / 30);
263+
newGeneration =
264+
previousGeneration + Math.min(monthsBetweenReleases, minimumCompatWindowMonths - 1);
265+
266+
log.info(`Previous release date: ${previousReleaseDate}, Today: ${today}`);
267+
log.info(`Days between releases: ${daysBetweenReleases}`);
268+
log.info(`Months between releases: ${monthsBetweenReleases}`);
269+
}
270+
271+
if (newGeneration === previousGeneration) {
272+
log.info(`Generation does not need to be bumped`);
273+
BaseStateHandler.signalSuccess(machine, state);
274+
return true;
275+
}
276+
277+
const yyyy = today.getFullYear();
278+
const mmNumber = today.getMonth() + 1; // Months start at 0!
279+
const ddNumber = today.getDate();
280+
281+
const dd = ddNumber < 10 ? `0${ddNumber}` : ddNumber.toString();
282+
const mm = mmNumber < 10 ? `0${mmNumber}` : mmNumber.toString();
283+
const releaseDateFormatted = `${mm}/${dd}/${yyyy}`;
284+
285+
const output = `/*!
286+
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
287+
* Licensed under the MIT License.
288+
* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY
289+
*/
290+
291+
export const generation = ${newGeneration};
292+
export const releaseDate = "${releaseDateFormatted}";
293+
`;
294+
295+
log.info(`Bumping generation from ${previousGeneration} to ${newGeneration}`);
296+
await writeFile(filename, output);
297+
298+
BaseStateHandler.signalSuccess(machine, state);
299+
return true;
300+
};

build-tools/packages/build-cli/src/handlers/fluidReleaseStateHandler.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ import {
4141
checkTypeTestPrepare,
4242
checkValidReleaseGroup,
4343
} from "./checkFunctions.js";
44-
import { doBumpReleasedDependencies, doReleaseGroupBump } from "./doFunctions.js";
44+
import {
45+
doBumpReleasedDependencies,
46+
doLayerGenerationUpdate,
47+
doReleaseGroupBump,
48+
} from "./doFunctions.js";
4549
import { InitFailedStateHandler } from "./initFailedStateHandler.js";
4650
import {
4751
promptToCommitChanges,
@@ -191,6 +195,7 @@ export class FluidReleaseStateHandler extends InitFailedStateHandler {
191195
["CheckTypeTestPrepare2", checkTypeTestPrepare],
192196
["CheckValidReleaseGroup", checkValidReleaseGroup],
193197
["DoBumpReleasedDependencies", doBumpReleasedDependencies],
198+
["DoLayerGenerationUpdate", doLayerGenerationUpdate],
194199
["DoMajorRelease", handleBumpType],
195200
["DoMinorRelease", handleBumpType],
196201
["DoPatchRelease", handleBumpType],

build-tools/packages/build-cli/src/machines/FluidRelease.fsl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ CheckShouldCommitDeps 'failure'
137137
// Bumps a release group and prompts to push/PR or commit changes
138138

139139
DoReleaseGroupBump 'success'
140+
=> DoLayerGenerationUpdate 'success'
140141
=> CheckShouldCommitBump 'success'
141142
=> PromptToPRBump;
142143

0 commit comments

Comments
 (0)