Skip to content

Skip app drift on deploy-only fields when there is no active deployment#5943

Merged
radakam merged 4 commits into
mainfrom
fix-app-config-no-deployment-drift
Jul 22, 2026
Merged

Skip app drift on deploy-only fields when there is no active deployment#5943
radakam merged 4 commits into
mainfrom
fix-app-config-no-deployment-drift

Conversation

@radakam

@radakam radakam commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Changes

Skip drift reporting on the deploy-only app fields source_code_path, config, and git_source whenever the app has no active deployment, unifying all three under a single ActiveDeployment == nil check (reason: no active deployment). Also fix the test server's stop handler to clear the active deployment, matching the real backend, and add a test covering the stopped-app case.

Why

DoRead can only read these fields back from the app's active deployment. An app created without lifecycle.started (the default no_compute case) has none, so the fields read back empty while the bundle sets them — producing a phantom update in bundle plan that can never converge (these fields are excluded from the App Update call and only deploy on start). A stop can also clear the active_deployment for some apps (pending_deployment is always cleared), so the same spurious diff applies to a stopped app that has none; the previous source_code_path-only check and the "no deployment" wording didn't capture that. Verified against a real workspace: a never-started app and a stopped app that cleared its deployment both return active_deployment: null, while a running app returns it, so real out-of-band drift is still reported once a deployment exists. This is a plan-idempotency fix. A config/git_source change made while the app has no active deployment is applied on the next start (see manageLifecycle), not silently lost — it is deferred, not applied while stopped, because the API neither exposes nor accepts deployed config for a non-running app.

Tests

  • config-no-deployment / git-source-no-deployment: no-op plan on a never-started app.
  • config-drift-stopped: drift is detected while running, then skipped after stop.

This gap was found by fuzz testing.

@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 167a01c

Run: 29810311210

Env 💚​RECOVERED 🙈​SKIP ✅​pass 🙈​skip Time
💚​ aws linux 4 4 227 1130 3:02
💚​ aws windows 4 4 229 1128 3:12
💚​ aws-ucws linux 4 4 314 1047 3:42
💚​ aws-ucws windows 4 4 316 1045 4:45
💚​ azure linux 4 4 227 1129 3:05
💚​ azure windows 4 4 229 1127 3:56
💚​ azure-ucws linux 4 4 316 1044 4:13
💚​ azure-ucws windows 4 4 318 1042 4:35
💚​ gcp linux 4 4 226 1131 2:36
💚​ gcp windows 4 4 228 1129 3:03
8 interesting tests: 4 RECOVERED, 4 SKIP
Test Name aws linux aws windows aws-ucws linux aws-ucws windows azure linux azure windows azure-ucws linux azure-ucws windows gcp linux gcp windows
💚​ TestAccept 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
🙈​ TestAccept/bundle/invariant/no_drift 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/bundle/resources/vector_search_indexes/recreate/embedding_dimension 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
🙈​ TestAccept/ssh/connection 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S 🙈​S
💚​ TestFetchRepositoryInfoAPI_FromRepo 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
💚​ TestFetchRepositoryInfoAPI_FromRepo/root 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
💚​ TestFetchRepositoryInfoAPI_FromRepo/subdir 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
Top 5 slowest tests (at least 2 minutes):
duration env testname
3:26 azure windows TestAccept
3:16 aws-ucws windows TestAccept
2:40 azure-ucws windows TestAccept
2:19 gcp windows TestAccept
2:07 aws windows TestAccept

@radakam
radakam force-pushed the fix-app-config-no-deployment-drift branch from 79153bb to 1957de9 Compare July 16, 2026 12:21
The app deploy-only fields (config, git_source) are applied through an app
deployment, which only happens once the app compute is started (manageLifecycle).
Until then DoRead leaves them nil, so an app that set config or git_source
without lifecycle.started=true planned a perpetual update for a field that was
never deployed.

Extend OverrideChangeDesc to skip config and git_source while there is no active
deployment, keying off remote.ActiveDeployment. source_code_path was already
skipped; matching on the top-level field (Prefix(1)) now also catches nested
config diffs. Real out-of-band drift is still reported once a deployment exists.
Adds acceptance tests for the config and git_source cases.
@radakam
radakam force-pushed the fix-app-config-no-deployment-drift branch from 1957de9 to a9a9561 Compare July 16, 2026 12:26
@radakam radakam changed the title Skip app config/git_source drift when the app has no deployment Skip spurious app config/git_source drift when app has no deployment Jul 17, 2026
Unify the deploy-only drift skip (source_code_path, config, git_source) on
ActiveDeployment == nil, which the backend also returns for a stopped app, not
just before the first deploy. Update the reason to "no active deployment" and fix
the test server's stop handler to clear the active deployment so acceptance tests
match cloud behavior. Add config-drift-stopped covering the stopped case.
@radakam radakam changed the title Skip spurious app config/git_source drift when app has no deployment Skip app drift on deploy-only fields when there is no active deployment Jul 17, 2026
The active deployment is cleared on stop only for non-scalable apps; scalable
apps retain it (pending is always cleared). Soften the OverrideChangeDesc and
test-server comments accordingly. Comment-only, no behavior change.
@radakam
radakam marked this pull request as ready for review July 17, 2026 10:51
Comment thread libs/testserver/apps.go Outdated
if remote.ActiveDeployment == nil {
change.Action = deployplan.Skip
change.Reason = "no active deployment"
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@andrewnester Is there impact for the lifecycle block?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

From looks of it the change seems to be correct, the tets coverage for lifecycle seems to be pretty okay so I'd also rely on it to validate

The OverrideChangeDesc and test-server stop comments used an informal
"scalable/non-scalable" distinction that isn't API/SDK terminology and that the
skip logic never branches on (it only checks ActiveDeployment == nil). Reword
both to describe the observable behavior instead. Comment-only, no behavior change.
}
}

=== Stop the app: the backend clears the active deployment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'm not sure stopping actually clears active deployment, could you confirm this with real backend behaviour? I think active is only empty when the app was created but never deployed

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Confirmed against dogfood: a normally stopped app that was previously deployed returns active_deployment: null, so it seems that it's not limited to never-deployed apps.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for confirming!

@radakam
radakam added this pull request to the merge queue Jul 22, 2026
Merged via the queue into main with commit 09d2395 Jul 22, 2026
31 checks passed
@radakam
radakam deleted the fix-app-config-no-deployment-drift branch July 22, 2026 08:42
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.

4 participants