Skip to content

feat: persistent deployer in func.yaml, block incompatible deployer switch, func delete removes f.Deploy values to match reality#3953

Open
gauron99 wants to merge 1 commit into
knative:mainfrom
gauron99:push-oymlnoorklvq
Open

feat: persistent deployer in func.yaml, block incompatible deployer switch, func delete removes f.Deploy values to match reality#3953
gauron99 wants to merge 1 commit into
knative:mainfrom
gauron99:push-oymlnoorklvq

Conversation

@gauron99

Copy link
Copy Markdown
Contributor

global deployer

  • make deployer as a globally configurable -- mirror builder -> its now always persisted in func.yaml
  • this makes it so its easier to work with deployers.X value instead of hardcoded values
  • for backwards compat if we hit deployer == "" (as it was before) we default to Knative as that was the default all along
  • note: I wouldnt be opposed to removing the "backwards compat" the only time you hit this is you deployed function with older binary, then you fetch new binary and try to "redeploy" again... its adding extra machinery which is ugly 😄 but I suppose it is the "standard upgrade path"

deployer switch

  • second part is blocking switch re-deploy early -- we now have 3 distinct deployers of which most dont share resources.
  • we dont want to make deployers aware of other deployers resources therefore stop this early.
  • the only documented compatible switch right now is raw -> keda because keda deployer embeds the raw deployer -- eg same resources.

func delete change

  • on successful undeploy -- func delete now actually removes the f.Deploy.Namespace and f.Deploy.Deployer values so that func.yaml correctly represents the state of the function on cluster (only when deleting by project! not name since theres no local files for that flow)

@knative-prow
knative-prow Bot requested review from dsimansk and jrangelramos July 17, 2026 15:16
@gauron99
gauron99 requested review from Copilot and lkingland and removed request for Copilot, dsimansk and jrangelramos July 17, 2026 15:16
@knative-prow

knative-prow Bot commented Jul 17, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: gauron99

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@knative-prow knative-prow Bot added approved 🤖 PR has been approved by an approver from all required OWNERS files. size/XL 🤖 PR changes 500-999 lines, ignoring generated files. labels Jul 17, 2026
@gauron99
gauron99 requested review from Copilot and matejvasek July 17, 2026 15:16
@gauron99
gauron99 force-pushed the push-oymlnoorklvq branch from 91da09f to 88f644d Compare July 17, 2026 15:21

Copilot AI left a comment

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.

Pull request overview

This PR makes deployer selection a first-class, globally configurable setting that is persisted into func.yaml, adds a safety guard to prevent redeploying an already-deployed function with an incompatible deployer (to avoid orphaning resources), and updates delete-by-project to clear deployed markers from local state after a successful undeploy.

Changes:

  • Introduce canonical deployer names (pkg/deployers) and use them across deployer implementations and config defaults.
  • Persist deployer into func.yaml via global config/application and block incompatible deployer switches on redeploy (except raw -> keda).
  • Improve raw deployer trigger-sync behavior to tolerate forbidden trigger RBAC only when no subscriptions are declared; update docs/tests and clear deploy markers on successful project delete.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
pkg/knative/deployer.go Switch knative deployer name constant to canonical deployers package.
pkg/keda/deployer.go Switch keda deployer name constant to canonical deployers package.
pkg/k8s/deployer.go Use canonical raw deployer name; add forbidden-tolerant trigger-sync choke point.
pkg/k8s/triggers_test.go Add unit tests covering forbidden trigger-sync behavior and warnings.
pkg/deployers/deployers.go New package defining canonical deployer names + default.
pkg/config/config.go Add global Deployer field/default and apply/configure propagation to functions.
pkg/config/config_test.go Ensure global config key listing includes deployer.
cmd/deploy.go Add globally configurable --deployer flag defaulting chain + guard against incompatible redeploy deployer switches.
cmd/deploy_test.go Add tests for deployer persistence, global seeding, and switch-guard behavior.
cmd/delete.go After successful delete-by-project, clear deployed markers and write updated func.yaml.
cmd/delete_test.go Add tests verifying deployed markers are cleared only for delete-by-project.
docs/reference/func_deploy.md Update deploy help text to reflect deployer behavior/default.
docs/reference/func_delete.md Document that delete-by-project updates local func.yaml on success.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread cmd/delete.go
Comment thread cmd/deploy.go Outdated
Comment thread docs/reference/func_deploy.md Outdated

Copilot AI left a comment

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.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Comment thread cmd/deploy.go Outdated
Comment thread cmd/deploy.go
@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.53846% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 54.31%. Comparing base (d93ceec) to head (02b00b7).

Files with missing lines Patch % Lines
pkg/deployer/testing/integration_test_helper.go 0.00% 8 Missing ⚠️
pkg/mock/deployer.go 0.00% 8 Missing ⚠️
pkg/config/config.go 42.85% 3 Missing and 1 partial ⚠️
cmd/delete.go 66.66% 2 Missing and 1 partial ⚠️
pkg/functions/client.go 89.47% 2 Missing ⚠️
pkg/remover/testing/integration_test_helper.go 0.00% 2 Missing ⚠️
cmd/deploy.go 90.90% 1 Missing ⚠️
pkg/describer/testing/integration_test_helper.go 0.00% 1 Missing ⚠️
pkg/lister/testing/integration_test_helper.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3953      +/-   ##
==========================================
+ Coverage   54.19%   54.31%   +0.11%     
==========================================
  Files         203      204       +1     
  Lines       23858    23905      +47     
==========================================
+ Hits        12931    12983      +52     
+ Misses       9688     9680       -8     
- Partials     1239     1242       +3     
Flag Coverage Δ
e2e 34.14% <55.17%> (+0.01%) ⬆️
e2e go 29.21% <20.45%> (-0.04%) ⬇️
e2e node 25.52% <20.45%> (-0.04%) ⬇️
e2e python 29.54% <20.45%> (-0.04%) ⬇️
e2e quarkus 25.65% <20.45%> (-0.04%) ⬇️
e2e rust 25.07% <20.45%> (-0.04%) ⬇️
e2e springboot 23.79% <20.45%> (-0.04%) ⬇️
e2e typescript 25.64% <20.45%> (-0.04%) ⬇️
e2e-config-ci 26.79% <20.45%> (-0.04%) ⬇️
integration 15.66% <20.00%> (+0.04%) ⬆️
unit macos-14 43.72% <51.66%> (+0.15%) ⬆️
unit macos-latest 43.72% <51.66%> (+0.15%) ⬆️
unit ubuntu-24.04-arm 44.00% <53.84%> (+0.16%) ⬆️
unit ubuntu-latest 44.57% <51.66%> (+0.15%) ⬆️
unit windows-latest 43.77% <51.66%> (+0.15%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gauron99 gauron99 changed the title feat: persistent deployer in func.yaml + block incompatible deployer switch re-deploy feat: persistent deployer in func.yaml, block incompatible deployer switch, func delete removes f.Deploy values to match reality Jul 20, 2026

@lkingland lkingland left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice! My only suggestion is to move most of that logic into core from the CLI pkg

Comment thread cmd/delete.go Outdated
Comment on lines +95 to +102
// Successful undeploy: clear live-deployment state so func.yaml
// reflects reality. Deploy-section config (image, options, etc.) is kept.
f.Deploy.Namespace = ""
f.Deploy.Deployer = ""
if err = f.Write(); err != nil {
return fmt.Errorf("function was undeployed from the cluster, but updating the local configuration failed: %w", err)
}
return nil

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This might actually be part of the implementation of client.Remove

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.

ah thanks this is good feedback! for this to be in client some further code work was required first... Im addressing after rebase

Comment thread cmd/delete_test.go
// path-based delete clears both Deploy.Namespace and Deploy.Deployer -
// live-deployment state that's stale once undeployed. The next flagless
// deploy correctly falls back to the global config's deployer default.
func TestDelete_ByProjectClearsDeployedMarker(t *testing.T) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Likewise, this could be a test in core, because it would be doing this clearing for every deployer (even the mock on the test)

Comment thread cmd/delete_test.go Outdated
// redeploy with a different deployer blocked by the deployer-switch
// guard - the guard only fires on an already-deployed function, and
// undeploy should've cleared up that function & func.yaml.
func TestDelete_ByProjectThenRedeployWithDifferentDeployerNotBlocked(t *testing.T) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This might also be a feature/test for core: two mock deployers, different names, ensure the guard fires correctly.

Comment thread cmd/delete_test.go Outdated
// reads or writes the func.yaml in the current directory, even when one
// exists there - the deployed-marker clearing added for path-based delete
// is scoped to that branch only.
func TestDelete_ByNameDoesNotTouchLocalFuncYaml(t *testing.T) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The cmd package should have no knowledge of the fact func.yaml even exists.

The test is implemented correctly, but the comment is misleading.

Comment thread cmd/deploy.go Outdated
Comment on lines +302 to +304
if from != to && !safeSwitch {
return fmt.Errorf("function %q was deployed with the %q deployer; redeploying with %q would orphan the old deployer's resources on the cluster - run func delete first to remove them, then redeploy", f.Name, from, to)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is an interesting case.

My first thought is that the if from != to check would be part of core, but the part which makes a "safeSwitch" could be a backwards-compatibility if statement here in the CLI which just sets f.Deploy.Deployer to knative if it is deployed but no value was recorded.

So, essentially splitting this whole block into two pieces 1) the assertion in core and 2) the back-compat default in the cli (where implementation names are expected).

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.

The "safe switch check" needs to live in the CLI because the to is a cfg.Deployer value. The only way we can check for already deployed deployer value is from cluster running service - we'd need to determine what the service is, get its annotations and check.

OR we could add f.Deployer type of "what to deploy with" and f.Deploy.Deployer "what is deployed with"...

Comment thread cmd/deploy_test.go
Comment thread pkg/config/config.go
@gauron99

Copy link
Copy Markdown
Contributor Author

to resolve the tension between unclear boundaries of func.yaml purpose in terms of "half status/ half declared intention" we introduced different means to interpret some keys. usually having one yaml key represent both is fine but sometimes its not. Sometime the current state is a dependency for some action.

Knowing if a function was deployed is essential to deliver "was the deployer changed". We can determine if function was deployed by checking the f.Depoy.Namespace because we intentionally created 2 keys for this (the other f.Namespace`) Now we need to introduce the same for deployer because the difference between intent and current state requires it.

@gauron99
gauron99 force-pushed the push-oymlnoorklvq branch from 7430589 to 02b00b7 Compare July 22, 2026 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved 🤖 PR has been approved by an approver from all required OWNERS files. size/XL 🤖 PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants