Skip to content

Conversation

agarwal-navin
Copy link
Contributor

@agarwal-navin agarwal-navin commented Oct 10, 2025

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:

  • An auto-generated file called "layerGeneration.ts" contains the last generation and the last release date.
  • On every minor or major release, the generation and release date are read from the file and are used to determine the new generation. New generation = Old generation + no. of months since last release.
    • An important requirement is that in between two subsequent releases, the generation should not be incremented by more than the minimum compat window between 2 layers across all layers boundaries. For example, say compat window between Loader / Runtime is 12 months but between Runtime / Datastore it is only 3 months. Then between 2 subsequent releases, generation should not increment by more than 2. If that happens, it doesn't give customers enough time to upgrade their packages and saturate a release before upgrading to the next one. Layer compatiility will break as soon they upgrade.
    • So, the logic for new generation is updated to: New generation = Old generation + min (no. of months since last release, min. compat window between layers across all layer boundaries).
    • The limitation here is that generation may be less that the actual number of months between releases. So, we end up supporting more than promised. But that is fine since it is necessary and since there were no releases for a long time, there shouldn't be any breaking changes in that time, i.e., if breaking changes were needed, we would likely have had a release in between to stage them.

Reviewer guidance

There are a few open questions:

  • The generation update should happen once we realize that the release is successful. So, I added it to the DoReleaseGroupBump stage which updates the package.json versions. Is this the right place?
  • The generation update should only happen for minor and major releases. I added a check to the doLayerGenerationUpdate function to return for patch releases. Is this check sufficient or should this be handled by adding it to minor / major release stages.
  • The layerGeneration.ts file is in packages/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.
  • The minimum compatibility between all FF layers is hard coded in the doLayerGenerationUpdate function as minimumCompatWindowMonths. Ideally, the client code should provide this. Is there a good pattern for something like this?

AB#27054

@github-actions github-actions bot added area: build Build related issues base: main PRs targeted against main branch labels Oct 10, 2025
Copy link
Contributor

@Copilot Copilot AI left a 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);
Copy link

Copilot AI Oct 10, 2025

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.

Copy link
Member

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?

Comment on lines +246 to +248
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,
);
Copy link

Copilot AI Oct 10, 2025

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.

Copy link
Member

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;
Copy link

Copilot AI Oct 10, 2025

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.

Copy link
Member

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";
Copy link

Copilot AI Oct 10, 2025

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.

@agarwal-navin agarwal-navin changed the title (layer compat) All logic to auto update layer compat generation during release (compat) All logic to auto update layer compat generation during release Oct 10, 2025
@agarwal-navin agarwal-navin changed the title (compat) All logic to auto update layer compat generation during release (compat) Add logic to auto update layer compat generation during release Oct 13, 2025
// 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";
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: build Build related issues base: main PRs targeted against main branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants