这是indexloc提供的服务,不要输入任何密码
Skip to content

feat: opt into breaking changes and pre-stable features early with turbo.json configuration #10590

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

Merged
merged 9 commits into from
Jun 29, 2025

Conversation

anthonyshew
Copy link
Contributor

@anthonyshew anthonyshew commented Jun 21, 2025

Description

We want to smooth migration paths for users when we introduce functionality with breaking changes. This can be difficult with point-in-time majors that might force a user to make many breaking changes at once.

Instead, we can introduce the concept of "future flags" to allow you to opt into breaking changes early. As a user, you get to have more control over when you adopt breaking changes. As a core team, we get more freedom to iterate, resulting in faster feedback cycles with users.

This PR only introduces the flag to the parser, not adding any flags quite yet. This key is only allowed in root turbo.jsons.

Testing Instructions

Added some tests. I also tried it out manually (and trivially). It worked how I'd hoped.

@anthonyshew anthonyshew requested a review from a team as a code owner June 21, 2025 12:01
Copy link

vercel bot commented Jun 21, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
examples-basic-web ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2025 7:02pm
examples-designsystem-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2025 7:02pm
examples-gatsby-web ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2025 7:02pm
examples-kitchensink-blog ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2025 7:02pm
examples-native-web ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2025 7:02pm
examples-nonmonorepo ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2025 7:02pm
examples-svelte-web ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2025 7:02pm
examples-tailwind-web ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2025 7:02pm
examples-vite-web ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2025 7:02pm
turbo-site ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jun 28, 2025 7:02pm

@anthonyshew anthonyshew changed the title feat(turbo.json): opt into features with configuration" feat(turbo.json): opt into features with turbo.json configuration Jun 21, 2025
@anthonyshew anthonyshew changed the title feat(turbo.json): opt into features with turbo.json configuration feat: opt into breaking changes early with turbo.json configuration Jun 21, 2025
@anthonyshew anthonyshew changed the title feat: opt into breaking changes early with turbo.json configuration feat: opt into breaking changes and pre-stable features early with turbo.json configuration Jun 21, 2025
@@ -164,6 +164,9 @@ pub struct RawTurboJson {
#[serde(skip_serializing_if = "Option::is_none")]
pub concurrency: Option<String>,

#[serde(skip_serializing_if = "Option::is_none", rename = "futureFlags")]
pub future_flags: Option<Spanned<serde_json::Value>>,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to change the key name if we like something else better! Was the first thing that came to mind.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

experimental to match Next.js?

Copy link
Contributor Author

@anthonyshew anthonyshew Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant to nest keys into this futureFlags key and forgot. I intended to do:

{
  "futureFlags": {
    "beta: {},
    "experimental": {}
  }
}

What do you think of that? Notably, experimental is the name of one of our release phases, so I don't want to create confusion by ending up with some experimental.foo, while foo is actually in Beta.

Copy link
Member

@chris-olszewski chris-olszewski Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just flags then? e.g. flags.experimental.foo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach would mean we would have to consciously promote a feature through its phases, though, and I don't know if we would want that. That would mean breaking changes within this flag since it would break parsing when a flag moves between phases in a user's codebase. (I am okay with this, but I could see opposition.)

Copy link
Contributor Author

@anthonyshew anthonyshew Jun 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That felt too close to application feature flags (e.g. https://flags-sdk.dev/) which worries me.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This approach would mean we would have to consciously promote a feature through its phases

Not necessarily. I'll do a quick PoC to show how we could have stablebetaexperimental "for free" so users don't need to change flag declaration as they get stabilized.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That feels confusing as well. I might be on a version of Turborepo where Boundaries are Beta, but then we would accept the flag in the experimental key? I guess we could warn?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel pretty strongly that we need to support reading beta flags from experimental path. Even with a warning it is easy enough to miss and a user not realize by upgrading turbo they unintentionally opted out of an experimental flag they had enabled because it is now in beta.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say in that case we don't need to have the nested keys for phases at all. The idea there was to make things explicit so users would know what phase a feature is in, but if we accept them anywhere, then that explicitness is lost and its a layer of nesting that expresses effectively nothing.

Stick with futureFlags: {}?

Copy link
Member

@chris-olszewski chris-olszewski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good, only blocker is updating @turbo/types.

I did push up a commit to switch to using a FeatureFlags struct instead of a Value. This lets us rely on Biome validating the types of the flags instead of handrolling it ourselves. (Noop now since we don't have any flags in here)

Comment on lines +564 to +572

// `futureFlags` key is only allowed in root turbo.json
let is_workspace_config = raw_turbo.extends.is_some();
if is_workspace_config {
if let Some(future_flags) = raw_turbo.future_flags {
let (span, text) = future_flags.span_and_text("turbo.json");
return Err(Error::FutureFlagsInPackage { span, text });
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was trying to find how we prevent root level field usage outside of the root and suggest using that mechanism instead of this check. We don't prevent it 🙃

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can make a utility out of this in a separate PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah, nothing to do in this PR. Just future work

@anthonyshew anthonyshew merged commit 84180e1 into main Jun 29, 2025
56 of 61 checks passed
@anthonyshew anthonyshew deleted the shew/a8c0d branch June 29, 2025 18:43
anthonyshew added a commit that referenced this pull request Jun 29, 2025
### Description

In #10590, I edited the JSON
schema directly, which [isn't the right
way](#10590 (comment)).

This PR introduces a CI check that I (and others) can't make this sort
of mistake in the future.

### Testing Instructions

[This
commit](3108ad0)
shows a failure because I added a `test` key to the schema (and
malformatted it in the process).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants