-
Notifications
You must be signed in to change notification settings - Fork 560
Add CheckCompatLayerGeneration to release prepare command #25911
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
Closed
+229
−116
Closed
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
805129e
Initial plan
Copilot e4e64e5
Add CheckCompatLayerGeneration to release prepare command
Copilot 05fec9f
Fix CheckCompatLayerGeneration function signature and return statement
Copilot 3b4a3db
Remove unnecessary eslint-disable comment
Copilot 7571073
Mark unused releaseGroupOrPackage parameter with underscore prefix
Copilot 2197af7
Use direct function calls instead of running pnpm command for layer g…
Copilot 3b76f2c
Remove trailing whitespace and clarify comment
Copilot 5d87e28
Extract minimumCompatWindowMonths constant
Copilot 804c2aa
Add missing log method to noop logger and clarify comment
Copilot 10cf5c4
Add onlyConfiguredPackages parameter to filter packages by metadata c…
Copilot a1a4052
Document how to set up unconfigured packages for layer compatibility
Copilot 7bc2409
Remove unused onlyConfiguredPackages parameter to simplify implementa…
Copilot 4541d93
Move layer compatibility functions to library and update imports
Copilot 157bbd0
Update build-tools/packages/build-cli/src/handlers/checkFunctions.ts
tylerbutler ef2a5a9
Refactor layer compatibility functions based on code review feedback
Copilot afa24cf
Fix layer generation check to scope to release group/package and upda…
Copilot ce6cf23
Merge branch 'main' of https://github.com/microsoft/FluidFramework in…
Copilot 03714cf
format
tylerbutler 45ab3c3
build
tylerbutler 43b8af4
Update comments to reference compatLayerGeneration command name
Copilot 276a999
Merge branch 'main' into copilot/update-release-prepare-command
tylerbutler File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
113 changes: 113 additions & 0 deletions
113
build-tools/packages/build-cli/src/library/layerCompatibility.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| /*! | ||
| * Copyright (c) Microsoft Corporation and contributors. All rights reserved. | ||
| * Licensed under the MIT License. | ||
| */ | ||
|
|
||
| import type { IFluidCompatibilityMetadata, Logger } from "@fluidframework/build-tools"; | ||
| import { formatISO, isDate, isValid, parseISO } from "date-fns"; | ||
| import { diff, parse } from "semver"; | ||
|
|
||
| /** | ||
| * Approximate month as 33 days to add some buffer and avoid over-counting months in longer spans. | ||
| */ | ||
| export const DAYS_IN_MONTH_APPROXIMATION = 33; | ||
|
|
||
| /** | ||
| * The default minimum compatibility window in months for layer generation. | ||
| * This matches the default value used in the compatLayerGeneration command. | ||
| */ | ||
| export const DEFAULT_MINIMUM_COMPAT_WINDOW_MONTHS = 3; | ||
|
|
||
| /** | ||
| * Determines if the current package version represents a patch release. | ||
| * | ||
| * @param pkgVersion - The semantic version of the package (e.g., "2.0.1") | ||
| * @returns True if the version is a patch release, false otherwise | ||
| * | ||
| * @throws Error When the provided version string is not a valid semantic version | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * isCurrentPackageVersionPatch("2.0.1"); // returns true | ||
| * isCurrentPackageVersionPatch("2.1.0"); // returns false | ||
| * isCurrentPackageVersionPatch("3.0.0"); // returns false | ||
| * ``` | ||
| */ | ||
| export function isCurrentPackageVersionPatch(pkgVersion: string): boolean { | ||
| const parsed = parse(pkgVersion); | ||
| if (parsed === null) { | ||
| throw new Error(`Package version ${pkgVersion} is not a valid semver`); | ||
| } | ||
| return parsed.patch > 0; | ||
| } | ||
|
|
||
| /** | ||
| * Determines if a new generation should be generated based on package version changes and time since | ||
| * the last release. | ||
| * | ||
| * This function parses an existing layer generation file and decides whether to increment the generation | ||
| * number based on: | ||
| * 1. Whether the package version has changed since the last update | ||
| * 2. How much time has elapsed since the previous release date | ||
| * 3. The minimum compatibility window constraints | ||
| * | ||
| * The generation increment is calculated as the number of months since the previous release, | ||
| * but capped at (minimumCompatWindowMonths - 1) to maintain compatibility requirements. | ||
| * | ||
| * @param currentPkgVersion - The current package version to compare against the stored version | ||
| * @param fluidCompatMetadata - The existing Fluid compatibility metadata from the previous generation | ||
| * @param minimumCompatWindowMonths - The maximum number of months of compatibility to maintain across layers | ||
| * @param log - Optional logger instance for verbose output about the calculation process | ||
| * @param currentDate - Optional current date for testing purposes. Defaults to new Date() | ||
| * @returns The new generation number if an update is needed, or undefined if no update is required | ||
| * | ||
| * @throws Error When the generation file content doesn't match the expected format | ||
| * @throws Error When the current date is older than the previous release date | ||
| */ | ||
| export function maybeGetNewGeneration( | ||
tylerbutler marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| currentPkgVersion: string, | ||
| fluidCompatMetadata: IFluidCompatibilityMetadata, | ||
| minimumCompatWindowMonths: number, | ||
| log?: Logger, | ||
| currentDate: Date = new Date(), | ||
| ): number | undefined { | ||
| // Only "minor" or "major" version changes trigger generation updates. | ||
| const result = diff(currentPkgVersion, fluidCompatMetadata.releasePkgVersion); | ||
| if (result === null || (result !== "minor" && result !== "major")) { | ||
| log?.verbose(`No minor or major release since last update; skipping generation update.`); | ||
| return undefined; | ||
| } | ||
|
|
||
| log?.verbose( | ||
| `Previous package version: ${fluidCompatMetadata.releasePkgVersion}, Current package version: ${currentPkgVersion}`, | ||
| ); | ||
|
|
||
| const previousReleaseDate = parseISO(fluidCompatMetadata.releaseDate); | ||
| if (!isValid(previousReleaseDate) || !isDate(previousReleaseDate)) { | ||
| throw new Error( | ||
| `Previous release date "${fluidCompatMetadata.releaseDate}" is not a valid date.`, | ||
| ); | ||
| } | ||
|
|
||
| const timeDiff = currentDate.getTime() - previousReleaseDate.getTime(); | ||
| if (timeDiff < 0) { | ||
| throw new Error("Current date is older that previous release date"); | ||
| } | ||
| const daysBetweenReleases = Math.round(timeDiff / (1000 * 60 * 60 * 24)); | ||
| const monthsBetweenReleases = Math.floor(daysBetweenReleases / DAYS_IN_MONTH_APPROXIMATION); | ||
| log?.verbose(`Previous release date: ${previousReleaseDate}, Today: ${currentDate}`); | ||
| log?.verbose( | ||
| `Time between releases: ${daysBetweenReleases} day(s) or ~${monthsBetweenReleases} month(s)`, | ||
| ); | ||
|
|
||
| const newGeneration = | ||
| fluidCompatMetadata.generation + | ||
| Math.min(monthsBetweenReleases, minimumCompatWindowMonths - 1); | ||
| if (newGeneration === fluidCompatMetadata.generation) { | ||
| log?.verbose( | ||
| `Generation remains the same (${newGeneration}); skipping generation update.`, | ||
| ); | ||
| return undefined; | ||
| } | ||
| return newGeneration; | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.