Skip to content

Conversation

@thijshberg
Copy link
Collaborator

This adds conversion from bpmn to cacao. Bpmn does not have the variables or actions that cacao (or soarca) has, so this is effectively a starting point for real conversion.

These are examples of BPMN playbooks. The only unsupported elements in
there are:
 - "intermediateThrowEvent", "intermediateCatchEvent": these require
   storage/communication between playbooks. We can make a playbook step
   in cacao, but that's not the same thing (and requires context).
 - "inclusiveGateway": usually used for a choice, e.g. "what is the
   course of action". Can be converted using manual steps, but the
   examples lack text in the gateway to give enough data to do this.

The choice for both of these for now is to error and not generate
output. There should be more diagnostic output in general on what needs
to be done for a meaningful conversion.
This metadata should still be changed by the implementer, as this is not
taken from the BPMN playbook.

This also does not manage to please Cymph, which does not find this a valid
playbook, but refuses to explain why.
@thijshberg thijshberg force-pushed the feature/182-playbook-conversion branch from 9442c70 to 6d621ac Compare August 29, 2025 11:32
Copy link
Collaborator

@MaartendeKruijf MaartendeKruijf left a comment

Choose a reason for hiding this comment

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

Nice to see this coming along, some changes are needed but good progress

Comment on lines 13 to 32
func loadPlaybook(t *testing.T, filename string) *cacao.Playbook {
input, err := os.ReadFile(filename)
assert.Nil(t, err)
playbook, err := conversion.NewBpmnConverter().Convert(input, filename)
assert.Nil(t, err)
return playbook
}

func nextSteps(t *testing.T, step cacao.Step, playbook *cacao.Playbook) []cacao.Step {
var steps []cacao.Step
for _, step_name := range step.NextSteps {
steps = append(steps, findStep(t, step_name, playbook))
}
return steps
}
func findStep(t *testing.T, step_name string, playbook *cacao.Playbook) cacao.Step {
step, ok := playbook.Workflow[step_name]
assert.True(t, ok, "Could not find %s", step_name)
return step
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

These functions complicate the testing logic and should be ideally tested aswel. I would make the functions with direct assertions.

Comment on lines +33 to +38
func findStepByName[S ~[]cacao.Step](t *testing.T, step_name string, steps S) *cacao.Step {
for _, step := range steps {
if step.Name == step_name {
return &step
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

step names are used as variables but these apear to be ids so you can just do a lookup in the workflows map

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This function looks up by the name field, not Id's (that's the function above it). This is very convenient to find the converted step knowing only the original name.

This puts both binaries into a simple rule. This does complicate things
if we add other targets in build/, but for now this works fine.
This includes some points where code was put in more correct locations, and some extra testing.
This works for both build/soarca and build/soarca-conversion, and
properly depends on all go files to detect rebuilds. The default build
target always triggers this, as swag will touch api/docs.go; filtering
this out broke the dependency for reasons beyond comprehension, but
since builds are quite quick this is okay for now.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants