feat: invoke customActions from deploy hooks and verify (skaffold/v4beta15) - #10067
Open
bogdannazarenko wants to merge 10 commits into
Open
feat: invoke customActions from deploy hooks and verify (skaffold/v4beta15)#10067bogdannazarenko wants to merge 10 commits into
bogdannazarenko wants to merge 10 commits into
Conversation
Contributor
There was a problem hiding this comment.
Code Review
This pull request introduces 'Action hooks,' allowing users to reference custom actions as deployment lifecycle hooks. The implementation includes the ActionInvoker interface to prevent package cycles, updated validation to ensure action names exist, and new documentation and examples. A review comment points out that adding fields to the v4beta14 schema might violate versioning policies if that version is already frozen, suggesting a move to a new schema version.
bogdannazarenko
force-pushed
the
feat/lifecycle-hooks-run-custom-actions
branch
from
April 24, 2026 17:15
6453e17 to
c8d0251
Compare
Contributor
Author
|
Waiting on maintainers to cut new schema version on main branch |
bogdannazarenko
force-pushed
the
feat/lifecycle-hooks-run-custom-actions
branch
from
April 24, 2026 17:37
c8d0251 to
d7e5025
Compare
bogdannazarenko
marked this pull request as draft
April 24, 2026 20:15
Adds a new ActionHook to the deploy lifecycle-hook union so users can
reference an existing customActions entry from
deploy.*.hooks.before / .after instead of re-implementing the
containerized task as a host hook with ad-hoc docker run arguments:
deploy:
kubectl: { ... }
hooks:
before:
- action: { name: pre-deploy-check }
after:
- action: { name: migrate-db }
customActions:
- name: migrate-db
containers: [{ image: myorg/migrator:latest, ... }]
Implementation
* schema: ActionHook{Name} joins HostHook and ContainerHook as a
third oneOf=deploy_hook union member on DeployHookItem.
* hooks: new package-level ActionInvoker interface plus a
SetDefaultActionInvoker setter so deploy hook runners can dispatch
without an import cycle back into pkg/skaffold/actions. The
invoker is registered once in runner.New immediately after
GetActionsRunner succeeds, mirroring how
SetupStaticEnvOptions is wired.
* runner: small actionsRunnerInvoker adapter satisfies the new
interface by delegating to ActionsRunner.Exec with nil artifact
slices (hooks do not themselves build).
* deploy.go: the run() dispatch loop recognises ActionHook and
calls runActionHook, which returns a helpful error if no invoker
is wired (e.g. from tests that stub hooks out).
CloudRunDeployHooks still accepts only []HostHook and is therefore
unaffected; wiring ActionHook into CloudRun is a follow-up once the
CloudRun deployer grows its own union type.
Unit coverage for the new ActionHook dispatch path:
- happy path fires pre then post hooks in declaration order
- first failure aborts the remaining hooks and surfaces both the
phase and the action name in the wrapped error
- a config with ActionHook but no registered invoker returns the
'no custom-actions runner available' sentinel
Also wires a new validateActionHookRefs pass into
ProcessWithRunContext so configs that reference an unknown custom
action fail at load time with a targeted message instead of deep
inside the deploy. Covers the three kubernetes-family deployers
(LegacyHelmDeploy, KubectlDeploy, KptDeploy); CloudRunDeployHooks
is intentionally still HostHook-only in this PR.
Adds a new 'Action hooks' section to docs-v2/docs/lifecycle-hooks.md describing the action: union member, how it relates to customActions, which deployers support it (kubectl, helm, kpt), and that it shares a runtime with skaffold exec (so a single action definition is runnable standalone or wrapped as a deploy hook). Ships a runnable examples/hooks-action/ fixture (mirrored under integration/examples/) with pre-deploy-check + post-deploy-smoke actions and a minimal busybox Pod manifest so maintainers can smoke test the new schema end-to-end.
A verify test case may now set `action: {name: <customAction>}` instead of
an inline `container`. Such test cases are dispatched to the same actions
runner used by `skaffold exec` and deploy action hooks, so the referenced
action runs with its own executionMode, timeout, failFast and runArgs.
verify:
- name: smoke
action:
name: smoke-test
- name: health
container:
name: health
image: alpine:3.20
command: ["/bin/sh", "-c", "wget -qO- http://svc/healthz"]
* GetVerifier skips action-referencing test cases so they are not handed
to the docker/k8s container verifiers.
* SkaffoldRunner.Verify runs them via r.actionsRunner.Exec after the
container verifier completes.
* getVerifyImgs skips them (no inline image to register).
Signed-off-by: Bogdan Nazarenko <bogdan.nazarenko@outlook.com>
Extends validateVerifyTests to require exactly one of `container` or `action` per verify test case and to verify that each `action` reference points to a known customActions entry. Extracts a shared knownActionNames helper reused by the existing validateActionHookRefs. Signed-off-by: Bogdan Nazarenko <bogdan.nazarenko@outlook.com>
* Unit: validation cases for the verify oneOf(container, action) rule and
unknown/empty action references.
* Integration: verify-custom-action fixture mixing an inline container
test case with an action-referencing one, asserting both run.
Signed-off-by: Bogdan Nazarenko <bogdan.nazarenko@outlook.com>
Signed-off-by: Bogdan Nazarenko <bogdan.nazarenko@outlook.com>
The hooks-action example demonstrates the `action:` deploy hook, which is a skaffold/v4beta15 feature. `examples/` must use the latest released schema version, so a v4beta14 copy cannot parse the unreleased field and fails TestParseExamples. Keep the example only under integration/examples (latest version) until v4beta15 is released; check-samples permits integration-only examples. Signed-off-by: Bogdan Nazarenko <bogdan.nazarenko@outlook.com>
Signed-off-by: Bogdan Nazarenko <bogdan.nazarenko@outlook.com>
bogdannazarenko
force-pushed
the
feat/lifecycle-hooks-run-custom-actions
branch
from
June 26, 2026 21:38
d7e5025 to
e53fb80
Compare
Signed-off-by: Bogdan Nazarenko <bogdan.nazarenko@outlook.com>
bogdannazarenko
force-pushed
the
feat/lifecycle-hooks-run-custom-actions
branch
from
June 26, 2026 22:00
e53fb80 to
a0f8009
Compare
bogdannazarenko
marked this pull request as ready for review
July 7, 2026 00:31
Contributor
Author
|
Hi @Darien-Lin @menahyouyeah could you take a look please when you get a chance? Thank you |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Invoke
customActionsfrom deploy hooks andverifyA
customActionis a reusable, containerized task. Today it can only be run standalone viaskaffold exec. This PR lets the same action definition be invoked from two more places, so users don't have to re-implement the task in each shape:deploy.*.hooks.before/after: [action: {name: ...}]verify[].action: {name: ...}instead of an inlinecontainerBoth reuse the existing
customActionsruntime (the same oneskaffold execdrives), so an action runs identically — including its ownexecutionMode,timeout,failFast, and (once #10066 lands)runArgs— regardless of where it's triggered from.Hooks (
action:deploy hook)action:union member onDeployHookItem, alongsidehost:/container:.hooks.ActionInvokerinterface +SetDefaultActionInvoker, wired once inrunner.NewafterGetActionsRunner. The hooks package stays free of anypkg/skaffold/actionsimport (no new cycle); a smallactionsRunnerInvokeradapter inpkg/skaffold/runnerbridges the two.validateActionHookRefs: unknown / empty action references fail at load time across kubectl, helm, and kpt deployers.Verify (
verify[].action)actionfield onVerifyTestCase;containeris now conditionally required (validation enforces exactly one ofcontainer/action).GetVerifierskips action-referencing test cases (they aren't container verifiers);SkaffoldRunner.Verifydispatches them tor.actionsRunner.Execafter the container verifier completes.knownActionNameshelper (also used by the hook validator) to reject unknown references.verify.md; integration fixtureintegration/testdata/verify-custom-actionmixes an inline container test case with an action-referencing one.Schema:
skaffold/v4beta15(final commit)v4beta14is released, so the new fields required cuttingv4beta15(frozenv4beta14package + upgrade path). Per the schema-last convention, the whole generated cut —v4beta15.json, CLI reference, docs version, and the apiVersion bump of the unreleasedintegration/{examples,testdata}— is isolated in the last commit, keeping the hand-written feature diff reviewable. The cut also correctsv4beta14.json(an earlier WIP had captured a strayActionHookinto the released schema).Notes
examples/hooks-action/was removed; an example using the unreleasedaction:field can't satisfy the released-version constraint onexamples/, so it lives only underintegration/examples/until v4beta15 ships.Out of scope
[]HostHookonly), pre/post-delete hooks, render/build action hooks.Tests
go build ./...,go test ./pkg/skaffold/hooks/... ./pkg/skaffold/schema/... ./pkg/skaffold/runner/... ./pkg/skaffold/verify/... ./cmd/...,hack/schemas,./hack/check-samples.sh— all green locally.TestLocalVerifyWithCustomActionRef, hook examples) defer to CI.