[steps] Support local composite functions in hook steps - #4062
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## szymonswierk/eng-22387-steps-unify-no-if-gating-policy #4062 +/- ##
==========================================================================================
+ Coverage 62.22% 62.23% +0.01%
==========================================================================================
Files 995 995
Lines 44754 44764 +10
Branches 9412 9415 +3
==========================================================================================
+ Hits 27845 27855 +10
Misses 15462 15462
Partials 1447 1447 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
ccd27cf to
88b25ed
Compare
e118ae0 to
5a88848
Compare
88b25ed to
afe2ad9
Compare
afe2ad9 to
de031b5
Compare
642f105 to
40b60f7
Compare
73ece96 to
be7ec02
Compare
fd5922a to
44fec11
Compare
0236cea to
f14d4f6
Compare
44fec11 to
56907d3
Compare
f14d4f6 to
fb5d85f
Compare
56907d3 to
a107305
Compare
fb5d85f to
0a629b7
Compare
a107305 to
95e91de
Compare
0a629b7 to
32f79bd
Compare
79cbcd4 to
ccd5926
Compare
9358a14 to
073ad5d
Compare
073ad5d to
98ef96f
Compare
hSATAC
left a comment
There was a problem hiding this comment.
A few non-blocking nits. Most of them are about composite behaviour that predates this PR rather than anything it introduces, so they are all fine to split out into a separate PR if you would rather keep this one focused.
hSATAC
left a comment
There was a problem hiding this comment.
One thing I noticed while reviewing this: I don’t think this PR is doing anything wrong, but it does make an existing behavior difference more likely to surface for users.
Today, when a single hook entry expands into multiple steps, the later steps are gated differently depending on which side the hook runs on:
- In a
before_*hook, if an earlier step fails, later steps without anif:are skipped. - In an
after_*hook, later steps still run.
This PR preserves that existing behavior. The difference is that, until now, multi-step hook entries could only come from function groups that we own. We don’t have many function groups, and users are also unlikely to use them inside hooks, so this difference probably hasn’t been very visible in practice.
With composite functions, users can now define and reuse the same multi-step unit themselves:
# .eas/functions/publish/function.yml
runs:
steps:
- run: ./login.sh
- run: ./push.shWhen used in steps:, ./push.sh is skipped if ./login.sh fails. When the same composite is used in after_build, ./push.sh still runs. I verified this behavior on the branch.
I think this could be surprising because the author of a composite may not know where it will eventually be used, so the behavior isn’t something they can fully account for inside the composite itself.
I don’t think this needs to block the PR, but I wanted to flag it so we can decide whether we want to document the difference, align the default behavior for after_* hooks, or keep it as-is.
One related detail if we document it: success() and failure() inside a composite reflect the overall job status, not the result of the previous step. That means if: ${{ success() }} is not a reliable fail-fast guard inside an after_* hook, since the hook may already be running after the job has failed.
To express “only run if the previous step succeeded,” users would need to pass that state explicitly, for example:
- id: login
run: |
./login.sh
set-output ok true
outputs: [ok]
- run: ./push.sh
if: ${{ steps.login.outputs.ok == 'true' }}The same behavior applies to function groups, so whatever we decide here could cover both.
336986e to
bfe042d
Compare
98ef96f to
ff9cb50
Compare
|
@hSATAC Thank you for noting that, and yes, this was done like that for the sake of consistency. But taking a step back, as a user I'd expect composite functions/function groups to fast-fail within them even in the Corrected the behavior for both composite functions and function groups. |
ff9cb50 to
4a56ee2
Compare
bfe042d to
c692851
Compare
4a56ee2 to
70ce854
Compare
c692851 to
f9f51cc
Compare
70ce854 to
3702906
Compare
f9f51cc to
e693624
Compare
…er hooks, but continue after hook execution after entry failure
3702906 to
7136a56
Compare
|
⏩ The changelog entry check has been skipped since the "no changelog" label is present. |

Why
Hook steps currently reject
uses: ./...local composite functions. Users should be able to reuse the same composites in hooks as in the main workflow.How
A composite function used in a hook is expanded into its inner steps at parse time, the same way it is in the main workflow, and the whole expansion becomes a single hook entry. The step's
if:gates the expansion as a whole.Hook construction now takes a catalog of composite functions. Without it, referencing a composite fails with a missing-function error instead of the previous "not supported in hooks" error.
Wiring reading the composite functions files will be added in follow-up PRs in the stack.
Test Plan
Added unit tests.