Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cron): cronworkflows when clause #13474

Merged
merged 22 commits into from
Sep 17, 2024

Conversation

isubasinghe
Copy link
Member

@isubasinghe isubasinghe commented Aug 15, 2024

Motivation

Modifications

This supersedes #13365 allowing for the evaluation of expr-lang expressions before running a CronWorkflow.

The scope of variables in this PR is quite limited, but can be further extended in later PRs when variable scoping is properly defined/formalised.

Verification

Added some tests for the evaluation function.

@isubasinghe isubasinghe force-pushed the feature-cronworkflows-when branch from f3e4011 to ebb7225 Compare August 16, 2024 05:39
@isubasinghe isubasinghe changed the title Feature cronworkflows when feat(cron): cronworkflows when clause Aug 16, 2024
@isubasinghe isubasinghe marked this pull request as ready for review August 16, 2024 08:20
@isubasinghe isubasinghe requested a review from Joibel August 16, 2024 08:27
Copy link
Member

@Joibel Joibel left a comment

Choose a reason for hiding this comment

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

This needs documenting, with examples and the variables we can use.

I'd also like to bring across the documentation from #13365 regarding how to do the various things mentioned there but using this new technique. I'm happy to contribute that, but the basic docs need to be in here first I think.

workflow/cron/operator.go Outdated Show resolved Hide resolved
workflow/cron/operator.go Outdated Show resolved Hide resolved
workflow/cron/operator_test.go Outdated Show resolved Hide resolved
workflow/controller/operator.go Outdated Show resolved Hide resolved
util/template/replace.go Show resolved Hide resolved
@agilgur5 agilgur5 added area/cron-workflows area/templating Templating with `{{...}}` labels Aug 17, 2024
@agilgur5
Copy link

This needs documenting, with examples and the variables we can use.

See also the "Variables" page

Copy link

@agilgur5 agilgur5 left a comment

Choose a reason for hiding this comment

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

Mainly reviewed the docs and examples below, but that also lends itself to some usage concerns I have about some of the variables

docs/variables.md Outdated Show resolved Hide resolved
docs/variables.md Outdated Show resolved Hide resolved
docs/variables.md Outdated Show resolved Hide resolved
docs/variables.md Outdated Show resolved Hide resolved
docs/variables.md Outdated Show resolved Hide resolved
examples/cron-when-limit-concurrency.yaml Outdated Show resolved Hide resolved
examples/cron-when.yaml Outdated Show resolved Hide resolved
pkg/apis/workflow/v1alpha1/cron_workflow_types.go Outdated Show resolved Hide resolved
pkg/apis/workflow/v1alpha1/cron_workflow_types.go Outdated Show resolved Hide resolved
docs/variables.md Outdated Show resolved Hide resolved
@agilgur5 agilgur5 added this to the v3.6.0 milestone Aug 19, 2024
@isubasinghe isubasinghe marked this pull request as draft August 19, 2024 07:14
@isubasinghe isubasinghe marked this pull request as ready for review August 19, 2024 08:16
docs/variables.md Outdated Show resolved Hide resolved
docs/variables.md Outdated Show resolved Hide resolved
docs/variables.md Show resolved Hide resolved
workflow/cron/operator.go Outdated Show resolved Hide resolved
workflow/cron/operator.go Show resolved Hide resolved
workflow/cron/operator_test.go Outdated Show resolved Hide resolved
workflow/cron/operator_test.go Outdated Show resolved Hide resolved
workflow/cron/operator_test.go Outdated Show resolved Hide resolved
@Joibel Joibel requested a review from agilgur5 September 3, 2024 14:08
@JPZ13
Copy link
Member

JPZ13 commented Sep 3, 2024

Hey @agilgur5 - Hope you had a good holiday weekend. I believe all of the changes you requested have been updated. I might have missed one, so please verify that. Could you remove the change request or request more changes so that we can keep moving forward on this? We'd like to roll out the when clause soon and recommend it to some of our customers

@isubasinghe
Copy link
Member Author

isubasinghe commented Sep 4, 2024

Note: This uses the deprecated govaluate library. This is very intentional and done to keep the logic similiar to the other When fields. Initially I implemented this using purely expr but after a chat with @Joibel we decided it was best to keep the logic as similiar as possible.

This field is intended to be deprecated and replaced with a whenExpression field in the future.

I will create another issue to unify the logic used in the When fields and to also use expr there instead, after this PR is merged in.

@agilgur5
Copy link

agilgur5 commented Sep 5, 2024

context, changed direction should be discussed

For context, Isitha followed up with me on Slack and I repeated my concern about using deprecated govaluate above. The examples here do use embedded expr though, which is part of the "soft" deprecation I outlined in #9529 (comment) / #7576 (comment). However, it's still concerning to add a new feature using a deprecated feature / library.
I said that such usage actually makes me more strongly consider whenExpression of #7831, which I left open as an option, but isn't part of the same plan linked above.

Isitha explained that he talked to Alan and decided to use whenExpression instead, to which I said there was no context for in the PR, which Isitha then added above.
With no rationale, adding a field that uses deprecated govaluate goes directly against Isitha, mine, and Alex C's stated intents in #13471 and #9529.

I'm not necessarily opposed to using whenExpression instead (I did leave it open after all), but a change in direction should really be discussed in the open, especially before being implemented in a PR.
Making a PR that goes directly against stated intentions in multiple issues without any discussion is, at best, confusing. (and even more so for users who may have been following along -- "I thought govaluate was planned for deprecation, why does this new field still use it?" is a very valid question)

when vs. whenExpression

This field is intended to be deprecated and replaced with a whenExpression field in the future.

I wouldn't release a new field that uses a deprecated library and itself will be shortly deprecated.

If anything, if we want to keep the logic identical -- we should just release this as whenExpression and skip creating a new when field that will be deprecated for CronWorkflows.
The Workflow resource will then have a new field that does the same and its when field would be the only one to need deprecation. I.e. we would not add more fields to deprecate

expression usage

To be clear, per #9529 (comment), when is the only outlier that uses govaluate. Everything else uses "expressions", which the docs describe as using expr (and which I unified/consolidated in #12617), sometimes with fields explicitly named expression.

There is also fasttemplate and text/template for "simple"/"plain" substitutions (those are terms the docs use), which are also planned to be replaced, but are inherently not as confusing to users as govaluate since they're not expression engines (they are much more confusing internally in the code vs externally to users). #9529 (comment) goes over this as well.

I will create another issue to unify the logic used in the When fields and to also use expr there instead, after this PR is merged in.

This was already described in #9529 and was partly duplicated in #13471. We can continue using #9529 for that. I've renamed both of those for specificity now.

@JPZ13
Copy link
Member

JPZ13 commented Sep 9, 2024

Thank you for the feedback @agilgur5. It's a bit hard for me to parse through the entire comment given I haven't been following all of the discussions and am strapped for time. Could you concisely give us a couple bullet points of:

  • where you feel there has been an inappropriate closed discussion, and
  • examples of a technical solution you would consider to be acceptable?

Our goal is to maintain consensus, keep our customers on mainline Argo Workflows expressions, and move quickly but thoroughly. I think working off of more concrete examples of what a when or whenExpression will look like will help move us forward

Edit: Upon re-reading the comment, another interpretation would be that you're objecting to the plan of matching the implementation of when with hooks that uses govaluate under the hood and then planning to migrate them both away from govaluate in one swoop. That or you feel that there should be more documentation/guidance around it. Either way, could you clarify?

@terrytangyuan
Copy link
Member

I think it's okay to use govaluate for new feature even if it will be deprecated in the future. It's already widely adopted in the code base and the syntax is familiar to existing users. I recommend using it for this feature, work on consistency in future versions, and then provide a very detailed migration guideline to users who'd like to upgrade.

This PR has been here for a month and I hope my comment breaks the tie if any and helps unblock adoption. @agilgur5 - could you let us know if this sounds good within the next two days? I'll merge it on Thursday. We can continue discuss migration path and work on consistency in a follow-up issue.

@agilgur5
Copy link

agilgur5 commented Sep 10, 2024

This PR has been here for a month

Alan only approved it 2 weeks ago, which was shortly after I noticed the govaluate usage and shortly before your own review comments.

@agilgur5 - could you let us know if this sounds good within the next two days?

I still have another unresolved comment as well

It's already widely adopted in the code base and the syntax is familiar to existing users.

Neither of these are true:

  • To repeat, govaluate is used in a single place, when, whereas every other usage of expressions uses expr. In fact, the term "expression" in field names and in the docs always refers to expr.
  • Likely in part due to its lack of usage in the codebase, govaluate is actually very poorly documented by Argo: Expand documentation on conditional expressions (govaluate) #7382. You can also embed expr expressions inside of when, to add to the confusion, per Confusingly, when _kind of_ supports expr expressions #7576
    • The very confusing error messages from govaluate and our wrapper of it are one of the single most common questions by users (e.g. Slack question from this week, which I actually don't know how to answer because the error gives no details)
  • We in fact generally tell users to use embedded expr expressions within when statements, which is also what this PR's own docs do.

of matching the implementation of when with hooks that uses govaluate under the hood

Since a couple contributors and maintainers in this very thread have said that govaluate is used elsewhere, like in hooks (it is not, to be clear), this also suggests the lack of consistency is poorly understood by maintainers as well.

That is all the more reason to not increase inconsistency and to actually properly discuss this.

We can continue discuss migration path and work on consistency in a follow-up issue.

Again, these exist and they predate me, and Isitha previously expressed agreement with this in the open prior to this PR.

None of the above options mention adding another when field that uses deprecated govaluate.

@agilgur5
Copy link

agilgur5 commented Sep 10, 2024

  • where you feel there has been an inappropriate closed discussion,

Initially I implemented this using purely expr but after a chat with @Joibel we decided it was best to keep the logic as similiar as possible.

@JPZ13 ^The above was not in the open. Isitha only wrote this after I specifically asked about it and mentioned whenExpression. The open discussions are in #9529, #13471, #7831, and their duplicates, none of which say to further extend usage of govaluate and precedent is actually to use expr for all new fields (that's why when is the odd one out).

that you're objecting to the plan of matching the implementation of when with hooks that uses govaluate

when with when, not hooks, which do not use govaluate, per my above comments.

Otherwise, yes, this is correct. To be clear, this was not previously discussed, but I'd rather add a whenExpression field immediately than introducing another govaluate-based when which is immediately deprecated. In fact, we can add whenExpression to plain workflows simultaneously as well to keep them consistent.

I think adding whenExpression is a superior option to adding a deprecated when and has also been previously discussed and fits in with prior plans and precedent (no further usage of govaluate).
Adding an already confusing, deprecated field -- with docs that embed expr no less -- that users would have to migrate off of sounds like it would add even more confusion.

@agilgur5 agilgur5 changed the title feat(cron): cronworkflows when clause feat(cron): cronworkflows when clause Sep 10, 2024
isubasinghe and others added 14 commits September 17, 2024 09:51
Co-authored-by: Anton Gilgur <[email protected]>
Signed-off-by: Isitha Subasinghe <[email protected]>
Co-authored-by: Anton Gilgur <[email protected]>
Signed-off-by: Isitha Subasinghe <[email protected]>
Co-authored-by: Anton Gilgur <[email protected]>
Signed-off-by: Isitha Subasinghe <[email protected]>
Signed-off-by: isubasinghe <[email protected]>
Signed-off-by: isubasinghe <[email protected]>
Signed-off-by: isubasinghe <[email protected]>
Signed-off-by: isubasinghe <[email protected]>
Signed-off-by: isubasinghe <[email protected]>
Signed-off-by: isubasinghe <[email protected]>
Signed-off-by: isubasinghe <[email protected]>
Signed-off-by: isubasinghe <[email protected]>
@isubasinghe isubasinghe force-pushed the feature-cronworkflows-when branch from c02b828 to d0b033f Compare September 16, 2024 23:56
@terrytangyuan terrytangyuan merged commit 196aeab into argoproj:main Sep 17, 2024
27 checks passed
@agilgur5
Copy link

@isubasinghe @Joibel Could any of you create a follow-up issue?

Regarding when -> whenExpression, I would propose we add to the existing #7831.

Should the templating syntax and docs here be unified with stopStrategy of #12305 ?

For instance, the variables there may make sense to prefix with cronworkflow.. and the docs could be moved to a subheading under this PR's docs

This might require a separate issue -- we should get any of these variable name consistency changes in before 3.6.0

@tooptoop4
Copy link
Contributor

@isubasinghe could this be used to run first monday of the month or last friday of the month?

@agilgur5
Copy link

agilgur5 commented Sep 18, 2024

You can use arbitrary expressions, so you might be able to workaround it for #8348 with pure date/time manipulation.

For instance, if you use now().Day(), you can get the day of the month (as in today is "the 18th").
So if you have a schedule weekly on Fridays and a when with now().Day() > 23 (day of the month is a bit coarse to use ofc), that might get you close to "last Friday of the month".
expr uses the time package for those functions, so you can potentially find a more accurate manipulation therein

@isubasinghe
Copy link
Member Author

isubasinghe commented Sep 18, 2024

You can also get the weekday it seems in expr-lang: https://expr-lang.org/docs/language-definition#date-functions
So you can probably use @agilgur5 's solution above along with this to get the behaviour @tooptoop4

Probably a little bit hacky, but dates are always at least a little bit hacky :)

@isubasinghe
Copy link
Member Author

Perhaps another feature could be stored functions to help with more complex expressions, that way you could reference these stored functions instead of having to write your expressions inline.

@Joibel Joibel deleted the feature-cronworkflows-when branch September 26, 2024 16:34
Joibel added a commit that referenced this pull request Oct 4, 2024
Issues #13474 and #12305 both introduced expressions into
CronWorkflows as new features for 3.6.

Motivation

The expressions for `when` include the prefix `cronworkflow.`. Those
for `stopStrategy.condition` do not.

Unify both of these under `cronworkflow.` and allow both sets of
variables to be used in both expressions. This simplifies the
documentation and is less surprising.

stopExpression's `condition` is mostly not a field name used, so in
agreement with @agilgur5 I've renamed it to `expression`.

Modifications

Renamed `stopStrategy.condition` to `stopStrategy.expression`

Created a single function to generate all the variables for both
expressions and use that instead of the two disparate mechanisms.

Modified some code comments to be godoc compliant.

Verification

Existing tests still pass with appropriate amendments to the test cases

Note

This is a breaking change vs 3.6-rc1 and rc2 for users of stopStrategy
only.

Signed-off-by: Alan Clucas <[email protected]>
Joibel added a commit that referenced this pull request Oct 4, 2024
Issues #13474 and #12305 both introduced expressions into
CronWorkflows as new features for 3.6.

Motivation

The expressions for `when` include the prefix `cronworkflow.`. Those
for `stopStrategy.condition` do not.

Unify both of these under `cronworkflow.` and allow both sets of
variables to be used in both expressions. This simplifies the
documentation and is less surprising.

stopExpression's `condition` is mostly not a field name used, so in
agreement with @agilgur5 I've renamed it to `expression`.

Modifications

Renamed `stopStrategy.condition` to `stopStrategy.expression`

Created a single function to generate all the variables for both
expressions and use that instead of the two disparate mechanisms.

Modified some code comments to be godoc compliant.

Verification

Existing tests still pass with appropriate amendments to the test cases

Note

This is a breaking change vs 3.6-rc1 and rc2 for users of stopStrategy
only.

Signed-off-by: Alan Clucas <[email protected]>
@agilgur5
Copy link

agilgur5 commented Oct 4, 2024

Should the templating syntax and docs here be unified with stopStrategy of #12305 ?
For instance, the variables there may make sense to prefix with cronworkflow.. and the docs could be moved to a subheading under this PR's docs

This might require a separate issue -- we should get any of these variable name consistency changes in before 3.6.0

Alan and I discussed this in the Oct 1st Contributor Meeting and agreed on this. See #13702 as a follow-up

Joibel added a commit that referenced this pull request Oct 4, 2024
Issues #13474 and #12305 both introduced expressions into
CronWorkflows as new features for 3.6.

Motivation

The expressions for `when` include the prefix `cronworkflow.`. Those
for `stopStrategy.condition` do not.

Unify both of these under `cronworkflow.` and allow both sets of
variables to be used in both expressions. This simplifies the
documentation and is less surprising.

stopExpression's `condition` is mostly not a field name used, so in
agreement with agilgur5 I've renamed it to `expression`.

Modifications

Renamed `stopStrategy.condition` to `stopStrategy.expression`

Created a single function to generate all the variables for both
expressions and use that instead of the two disparate mechanisms.

Modified some code comments to be godoc compliant.

Verification

Existing tests still pass with appropriate amendments to the test cases

Note

This is a breaking change vs 3.6-rc1 and rc2 for users of stopStrategy
only.

Signed-off-by: Alan Clucas <[email protected]>
@agilgur5
Copy link

agilgur5 commented Oct 7, 2024

I'd also like to bring across the documentation from #13365 regarding how to do the various things mentioned there but using this new technique. I'm happy to contribute that, but the basic docs need to be in here first I think.

This has been added in #13723

Joibel added a commit that referenced this pull request Oct 11, 2024
Issues #13474 and #12305 both introduced expressions into
CronWorkflows as new features for 3.6.

Motivation

The expressions for `when` include the prefix `cronworkflow.`. Those
for `stopStrategy.condition` do not.

Unify both of these under `cronworkflow.` and allow both sets of
variables to be used in both expressions. This simplifies the
documentation and is less surprising.

stopExpression's `condition` is mostly not a field name used, so in
agreement with agilgur5 I've renamed it to `expression`.

Modifications

Renamed `stopStrategy.condition` to `stopStrategy.expression`

Created a single function to generate all the variables for both
expressions and use that instead of the two disparate mechanisms.

Modified some code comments to be godoc compliant.

Verification

Existing tests still pass with appropriate amendments to the test cases

Note

This is a breaking change vs 3.6-rc1 and rc2 for users of stopStrategy
only.

Signed-off-by: Alan Clucas <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants