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(core): require conditional action #866

Merged
merged 13 commits into from
Feb 20, 2025
Merged

feat(core): require conditional action #866

merged 13 commits into from
Feb 20, 2025

Conversation

topher-lo
Copy link
Contributor

@topher-lo topher-lo commented Feb 18, 2025

What changed

  • Created an require action that takes one or more exprs
  • exprs is not entirely accurate, since require functions like reshape (a more accurate argument might be bool, but from the UI perspective might be misleading since what the user sees is the template expression not bool). I went for exprs for user clarity over functional accuracy.
  • Called require because assert is a key variable in python.
  • require is used in Kotlin and Solidity
  • core.require is semantic closest what to what I want it to do in templates (e.g. require URLScan POST result to have a successful status otherwise fail).
  • Also drops "!" in OPERATORS. It wasn't in the grammar anyway.

Bigger changes

  • Extended the grammar to support more operators
  • Note that is not and not in are at the front to avoid is and in being evaluated first
  • Extended OPERATORS infunctions.py

QA

  • Added simple tests in registry/test_core_require.py which just checks bools as inputs (i.e.as post evaluated templates)
  • Added test_expression_binary_ops with a case for each operator to unit/test_expressions.py

Future considerations

  • Maybe support match_any?
  • We should probably test require in a workflow, but I'm just relying on induction: since require is logically equivalent to core.transform.reshape except it supports lists of exprs, which we do test.

Prior art

@topher-lo topher-lo added enhancement New feature or request core-actions Improvements to core Tracecat actions labels Feb 18, 2025
@topher-lo topher-lo requested a review from daryllimyt February 18, 2025 03:52
Copy link
Contributor

@daryllimyt daryllimyt left a comment

Choose a reason for hiding this comment

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

No need to use try-except, just check the value and throw. Also no need return value. Also, is lhs and rhs too rigid? How do we handle container emptiness checks? Would we have to do:

lhs: FN.length(<container>)
rhs: 0
condition: ==

@daryllimyt
Copy link
Contributor

Will document that result from this action shouldn't be used (is falsely None). It's just a gate

Since people might try using this, let's keep returning True in the happy path to distinguish between None that would be returned in the error path.

@topher-lo
Copy link
Contributor Author

Container checks will be a separate action https://www.tines.com/docs/actions/types/trigger/

Tines throws a bunch of stuff all in a single action with a dropdown for options. That's not very user friendly imo.

@topher-lo
Copy link
Contributor Author

topher-lo commented Feb 18, 2025

Also on closer look maybe not too rigid, all of Tines trigger rules are LHS, RHS, or regex

Can you think of any other cases other than is empty which operates on a single value?

@daryllimyt
Copy link
Contributor

daryllimyt commented Feb 18, 2025

Container checks will be a separate action https://www.tines.com/docs/actions/types/trigger/

Tines throws a bunch of stuff all in a single action with a dropdown for options. That's not very user friendly imo.

Aren't in and not in container checks?

@daryllimyt
Copy link
Contributor

daryllimyt commented Feb 18, 2025

Also on closer look maybe not too rigid, tines has a container is empty option for trigger, it really is just check length is 0.

Can you think of any other cases other than is empty which operates on a single value?

Any kind of FN.func() that returns a boolean/truthy or a standalone boolean value, but I suppose you would want users to compare against True or False using is/is not?

@topher-lo
Copy link
Contributor Author

topher-lo commented Feb 18, 2025

Yeah. I think this discussion getting too complicated. Question: is LHS and RHS too rigid? I think it's flexible enough for folks to use FN along with the supported operators to achieve what they need

Following our private discussion, I'll drop lhs and rhs and instead use a if-condition single expression style system

@topher-lo topher-lo requested a review from daryllimyt February 19, 2025 19:24
Copy link
Contributor

@daryllimyt daryllimyt left a comment

Choose a reason for hiding this comment

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

LGTM, i think would be great if you could add an actual action template run to test your main usecase (throwing from template). See test_registry for examples on running template actions

Comment on lines +9 to +31
@pytest.mark.parametrize(
"exprs",
[
True,
[True, True],
[True, True, True],
],
)
def test_require_all(exprs):
assert require(exprs) is True


@pytest.mark.parametrize(
"exprs",
[
False,
[True, False],
[False, True],
],
)
def test_require_all_fail(exprs):
with pytest.raises(AssertionError):
require(exprs)
Copy link
Contributor

Choose a reason for hiding this comment

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

check empty list behavior as well?

@topher-lo topher-lo merged commit dd21ec0 into main Feb 20, 2025
7 checks passed
@topher-lo topher-lo deleted the feat/assert branch February 20, 2025 20:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
core-actions Improvements to core Tracecat actions enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants