bundle/direct: add a feature-flag list to the direct deployment state#5660
bundle/direct: add a feature-flag list to the direct deployment state#5660shreyas-goenka wants to merge 6 commits into
Conversation
Integration test reportCommit: 38c6f2c
8 interesting tests: 4 SKIP, 3 flaky, 1 RECOVERED
Top 7 slowest tests (at least 2 minutes):
|
663ad08 to
a1b0613
Compare
| for name := range db.Features { | ||
| names = append(names, name) | ||
| } | ||
| slices.Sort(names) |
There was a problem hiding this comment.
makes tests with multiple features deterministic.
a1b0613 to
a550105
Compare
Approval status: pending
|
| // RecordFeature marks the state as depending on the named feature, stamping the | ||
| // minimum CLI version required to read it (from featureMinCLIVersion). It must be | ||
| // called before the WAL is started (UpgradeToWrite) so the change is persisted. | ||
| func (db *DeploymentState) RecordFeature(name string) { |
There was a problem hiding this comment.
Get rid of this function - make this decision at open.
| { | ||
| "state_version": 3, | ||
| "features": { | ||
| "dummy": "1.2.0" |
There was a problem hiding this comment.
talk to Julia, if aligned get rid of versions from state and consider hosting every feature on our docs page.
a550105 to
2d62964
Compare
2d62964 to
e559fca
Compare
e559fca to
c62c873
Compare
c62c873 to
1a7c392
Compare
d6fdd85 to
329e0fc
Compare
This is outdated, right? We discussed that version in the state file cannot work because it's frozen and we might need/want to recommend a more recent one. |
|
|
||
| === a state recording an unknown feature flag is rejected | ||
| >>> errcode [CLI] bundle plan | ||
| Error: the deployment state requires feature "future_feature" which this CLI ([DEV_VERSION]) does not support; upgrade to 9.9.9 or newer and see https://docs.databricks.com/future-feature for more information on how to proceed |
There was a problem hiding this comment.
upgrade to 9.9.9
where does 9.9.9 from from? Can we replace recommendation to "Upgrade to latest CLI version. See URL for more information".
There was a problem hiding this comment.
Just a random version for the test that was persisted in the state file. We can - either message works.
| "features": { | ||
| "dummy": { | ||
| "min_cli_version": "1.2.0", | ||
| "doc_url": "https://docs.databricks.com/dev-tools/bundles/deployment-modes" |
There was a problem hiding this comment.
We don't need the URL here, we can just hard code url with anchor based on feature name:
https://docs.databricks.com/dev-tools/bundles/state-features#dummy
There was a problem hiding this comment.
That is more fragile. This is more forward looking and allows us to change the structure of the URLs if necessary. If we hardcode in the binary we'll be stuck with a format (or would be forced to use the same parent URL)
This is different. I mean like each feature flag having it's own version. Incase we need to make more breaking changes within the context of a single feature flag. We don't need it because we can just introduce new flags. |
329e0fc to
c330241
Compare
c330241 to
4f3a6f8
Compare
Bumps the direct state schema to version 3, adding a per-state feature map (Header.Features) recording each feature flag the state depends on. On load the CLI rejects any state recording a feature it does not know, pointing the user at the feature's documentation (derived from its name), so older CLIs fail with an actionable message instead of silently mishandling the state. Feature flags are defined in a static set (supportedFeatures). A dummy feature exercises the mechanism in tests; no real deployment records one yet. Co-authored-by: Isaac
4f3a6f8 to
2df14e3
Compare
| // docBaseURL is the documentation prefix a feature name is appended to, to form | ||
| // the link shown when a feature is unsupported. The full URL is derived from the | ||
| // feature name (docBaseURL + name), so only the name is recorded in the state. | ||
| const docBaseURL = "https://docs.databricks.com/aws/en/dev-tools/bundles/" |
There was a problem hiding this comment.
Not done yet. We need to update it once teh docs page lands and fix it here to use anchors
Adds a per-state feature map (Header.Features) recording each feature flag a state depends on. The baseline state version stays 2; a state that records a feature is written at version 3 so an older CLI (which reads only up to 2) refuses it instead of silently ignoring the feature. On load, a version-3 state with no features is treated as version 2, so a later release can start writing version 3 unconditionally — the actual version bump — while CLIs with this change already tolerate such states. A CLI that loads a state recording a feature it does not know rejects it and points the user at the feature's documentation (derived from its name). Feature flags are defined in a static set (supportedFeatures); a dummy feature exercises the mechanism in tests, and no real deployment records one yet. Co-authored-by: Isaac
The WAL header now records the state's schema version and feature flags, and recovery restores them. Previously a crash between opening the WAL for write and Finalize would replay the WAL onto the pre-crash state and silently drop the features the interrupted deploy recorded, downgrading the recovered state. Co-authored-by: Isaac
Collapse the currentStateVersion / featureStateVersion "nothing to migrate" checks into one branch. No behavior change. Co-authored-by: Isaac
…l case Adds an acceptance case for a version-3 state with an empty features map (the CLI accepts it, treating it as version 2), so all three feature-flag cases — known, unknown, empty-v3 — are exercised together. Documents that the "version 3 + empty features == version 2" equivalence is special-cased to version 3 only, and renames the unit test to TestEmptyFeatureStateEquivalentToVersion2 as a forcing function: it must be removed when the baseline is actually bumped to 3, so a real v3 state is not silently reinterpreted as v2. Co-authored-by: Isaac
The unsupported-feature error now links to a single fixed documentation page (the state-features section Julia is adding) instead of deriving a per-feature URL from the feature name. There is one docs page for all features, so drop docBaseURL/featureDocURL and use a fixed featuresDocURL constant. Co-authored-by: Isaac
Why
The direct deploy engine records its state on disk with a
state_version. Today, any backwards-incompatible change forces a version bump, which older CLIs reject wholesale. That's too coarse: an additive capability that only some deployments use shouldn't lock every older CLI out of every new state.This adds feature flags to the state: a deployment records the named features it depends on, and an older CLI that doesn't understand a recorded feature refuses that state (pointing at docs) while still reading every state that uses no features.
What
Header.Features— amap[feature-name]FeatureInforecording the features a state depends on.FeatureInfois intentionally empty (presence of the key is what matters); it's a struct so per-feature fields can be added later without reshaping the state.checkSupportedFeaturesrejects a state recording a feature this CLI doesn't know, with an actionable error:upgrade to the latest CLI version and see <doc-url>. The doc URL is derived from the feature name (docBaseURL + name), so only the name lives in the state.supportedFeaturesset. Adummyfeature exercises the mechanism in tests; no real deployment records a feature yet — this PR is the mechanism only.Version handling (the subtle part)
The baseline
currentStateVersionstays 2 — normal deploys are unchanged, so there's no golden churn and no forced upgrade.A state that records a feature is written at
featureStateVersion(3), specifically so an older CLI (which reads only up to 2) refuses it rather than silently ignoring a feature it depends on.On load, a version-3 state with no features is normalized to version 2. This is the deferral hook: a later release can start writing version 3 unconditionally — the real bump — and CLIs carrying this change already tolerate those states instead of rejecting them. We get the mechanism in now and bake it in before flipping the switch.