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

fix: deep evaluate matrix strategy #964

Merged
merged 7 commits into from
Feb 15, 2022

Conversation

ChristopherHX
Copy link
Contributor

We need to wait for the previous stage to finish, otherwise we don't know how the final strategy will look like.
Then we need to evaluate all expression nodes of the strategy.matrix property, even the mapping keys.

I also added support for the insert directive and array merge operations, both are undocumented features of the github/actions which are available since 2019.

My tests aren't cover all possibilities, but the fixed issue has a test.

Most likely this change collides with @catthehacker plans of rewriting the yaml parser to actionslint, since I use the current yaml.Node types.

I have no idea how big the regressions regarding parallelism are with this change.

Resolves #927

@ChristopherHX ChristopherHX requested a review from a team as a code owner January 23, 2022 22:05
@mergify
Copy link
Contributor

mergify bot commented Jan 23, 2022

@ChristopherHX this pull request has failed checks 🛠

@mergify mergify bot added the needs-work Extra attention is needed label Jan 23, 2022
@codecov
Copy link

codecov bot commented Jan 23, 2022

Codecov Report

Merging #964 (0cce8cb) into master (4f8da0a) will increase coverage by 0.99%.
The diff coverage is 81.37%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #964      +/-   ##
==========================================
+ Coverage   57.50%   58.50%   +0.99%     
==========================================
  Files          32       34       +2     
  Lines        4594     4687      +93     
==========================================
+ Hits         2642     2742     +100     
+ Misses       1729     1715      -14     
- Partials      223      230       +7     
Impacted Files Coverage Δ
pkg/runner/expression.go 87.20% <75.80%> (-3.61%) ⬇️
pkg/runner/runner.go 75.89% <78.00%> (-0.58%) ⬇️
pkg/runner/job_executor.go 81.57% <81.57%> (ø)
pkg/runner/action.go 84.21% <84.21%> (ø)
pkg/runner/step_context.go 85.83% <86.95%> (+4.20%) ⬆️
pkg/runner/run_context.go 80.07% <94.11%> (+0.42%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0fae967...0cce8cb. Read the comment docs.

@mergify mergify bot removed the needs-work Extra attention is needed label Jan 23, 2022
@mergify mergify bot requested a review from a team January 24, 2022 01:43
@mergify
Copy link
Contributor

mergify bot commented Jan 24, 2022

@ChristopherHX this pull request has failed checks 🛠

@mergify mergify bot added the needs-work Extra attention is needed label Jan 24, 2022
@mergify mergify bot removed the needs-work Extra attention is needed label Jan 24, 2022
@ChristopherHX
Copy link
Contributor Author

ChristopherHX commented Jan 24, 2022

I noticed that my first map approuch of evaluateMappingYamlNode failed with yaml validation errors, if I used ${{insert}} as yaml key multiple times. It seems to be a somewhat complex change, loosly based on how actions/runner works internally.
More parts of act should migrate to use EvaluateYamlNode for evaluation e.g.

  • job.strategy itself the whole block is evaluatable
  • job.env the whole block is evaluatable
  • job.defaults the whole block is evaluatable
  • job.runs-on
  • job.steps.*.with the whole block is evaluatable
  • job.steps.*.env the whole block is evaluatable
  • job.steps.*.continue-on-error
  • job.steps.*.timeout-minutes

Edit 2022/2/8
This is low a low priority PR 1, but I think it is complete.

Footnotes

  1. This change is still dead code for my github-act-runner project. Please Test carefully.

Copy link
Contributor

@ZauberNerd ZauberNerd left a comment

Choose a reason for hiding this comment

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

So if I understand it correctly, you take the parsed yaml node, turn it back into its string representation, run Evaluate on that and then encode it as a yaml.Node again?
Feels a bit hack-y to me, but I think it is fine for now until we have refactored the whole workflow parsing to use actionlint and then we can remove this again.

if len(matrixes) > 1 {
rc.Name = fmt.Sprintf("%s-%d", rc.Name, i+1)
stagePipeline := make([]common.Executor, 0)
for i := range plan.Stages {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not for s, stage in range plan.Stages as it was before?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

golang reuses the loop variables s, stage, the linter warns you if you do that after my changes.
So what happens if you reference s

  • you capture the loop variable in a function
  • the loop finishes
  • the callbacks with references to the loop variables get called
  • s, stage are always assigned to the last stage.

I also believed that I can safely reference loop variables in func(){...}

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Member

@KnisterPeter KnisterPeter left a comment

Choose a reason for hiding this comment

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

Looks fine from my side

Copy link
Contributor

@cplee cplee left a comment

Choose a reason for hiding this comment

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

lgtm - thanks

@mergify mergify bot merged commit d1e0216 into nektos:master Feb 15, 2022
@ChristopherHX
Copy link
Contributor Author

you take the parsed yaml node, turn it back into its string representation

I only look for expressions in scalar values could be boolean, number or string. Maybe we could read the Value field directly like in if statements. I just find it myself safer to use the decode function.

run Evaluate on that and then encode it as a yaml.Node again

Everything which isn't an expression is skipped and not encoded again
After evaluate we get a raw boolean, number, string, array or mapping which needs to be encoded as yaml.Node.

For actionslint, we may need to replace all yaml types. I rely much on the current act api with yaml.Node, with a lot of convertion functions to translate job requests of the github actions service into act's layout.

workflow parsing to use actionlint and then we can remove this again.

I doubt we can remove this later without breaking my test cases.

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.

Issue: Dynamic Matrix not working
5 participants