-
Notifications
You must be signed in to change notification settings - Fork 557
(compat) Add logic to auto update layer compat generation during release #25670
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds automated layer generation updates to the FluidFramework release process. The layer generation system provides compatibility tracking between different client layers (Loader, Driver, Runtime, Datastore) by incrementing a generation number monthly.
- Adds automated generation update logic during minor/major releases
- Creates auto-generated
layerGeneration.ts
file to track current generation and release date - Implements logic to calculate new generation based on months elapsed with compatibility window constraints
Reviewed Changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 4 comments.
File | Description |
---|---|
FluidRelease.fsl | Adds DoLayerGenerationUpdate step to release workflow after DoReleaseGroupBump |
fluidReleaseStateHandler.ts | Registers the new doLayerGenerationUpdate handler in the state machine |
doFunctions.ts | Implements the core layer generation update logic with file I/O and date calculations |
(today.getTime() - previousReleaseDate.getTime()) / (1000 * 60 * 60 * 24), | ||
); | ||
|
||
const monthsBetweenReleases = Math.floor(daysBetweenReleases / 30); |
Copilot
AI
Oct 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a fixed 30-day month approximation is inaccurate for month calculations. Consider using date arithmetic that accounts for actual month boundaries, such as calculating the difference in months and years between the two dates.
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just use 100 days for 3 months, 200 for six months, and 400 for 12 months, etc?
const match = fileContents.match( | ||
/.*\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, | ||
); |
Copilot
AI
Oct 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The regex pattern is complex and fragile. Consider parsing the TypeScript file using a proper parser or extracting the values using a more robust approach that doesn't rely on exact formatting.
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we control the packages, consider putting the date and time of release in the package itself then we can just read it from the previous version.
// eslint-disable-next-line no-warning-comments | ||
// TODO: This should ideally be read from a common location in client utils. What is the best way to do this? | ||
// The minimum compatibility window in months that is supported across all layers. | ||
const minimumCompatWindowMonths = 3; |
Copilot
AI
Oct 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The minimum compatibility window is hardcoded as a magic number. Consider defining this as a named constant at the module level or reading it from a configuration file to improve maintainability.
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can read config settings from the fluidBuild config. Maybe it makes sense to store this config data there?
// eslint-disable-next-line no-warning-comments | ||
// TODO: Is it okay to read a file from this folder? | ||
// The file that stores information of the current generation and release date. | ||
const filename = "packages/common/client-utils/src/layerGeneration.ts"; |
Copilot
AI
Oct 10, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hardcoded file path makes the code brittle to directory structure changes. Consider using path resolution utilities or making this configurable.
Copilot uses AI. Check for mistakes.
// eslint-disable-next-line no-warning-comments | ||
// TODO: Is it okay to read a file from this folder? | ||
// The file that stores information of the current generation and release date. | ||
const filename = "packages/common/client-utils/src/layerGeneration.ts"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calrify that this is relative to the repo root.
Description
Each layer within a client (Loader, Driver, Runtime and Datastore) has a generation property which should be incremented monthly. It provides a simple way to determine if two layers are compatible with each other by comparing their generations since layer compatibility is expressed in number of months. For example, between the Runtime and Datastore layers, we support a 3 months compatibility. So, they are compatible if the difference in their generation is <3. See #22877 for more details on how this will work.
We would like an automated way to increment the generation of these layers for simplicity and consistency. This change does that by adding logic to the release process which auto generates the generation value. Here is how it works:
New generation = Old generation + no. of months since last release
.New generation = Old generation + min (no. of months since last release, min. compat window between layers across all layer boundaries)
.Reviewer guidance
There are a few open questions:
DoReleaseGroupBump
stage which updates the package.json versions. Is this the right place?doLayerGenerationUpdate
function to return for patch releases. Is this check sufficient or should this be handled by adding it to minor / major release stages.layerGeneration.ts
file is inpackages/common/client-utils/src
and the code reads / writes to it. Is this fine or should the file be in the build-tools folder somewhere? The reason I added it to client-utils is because the generation will be read by the client code.doLayerGenerationUpdate
function asminimumCompatWindowMonths
. Ideally, the client code should provide this. Is there a good pattern for something like this?AB#27054