Skip to content

Conversation

pmeier
Copy link
Collaborator

@pmeier pmeier commented Sep 22, 2022

In #6587 we decided to split the transforms tests into three CI steps. This makes it easier to find failing tests, but has one glaring downside that we missed: if the first step fails, the other steps aren't run at all. Imagine the CI is toasted for some external reason and now it won't run the tests your PR touches.

This PR refines the step triggers to run even if the previous tests failed.

@pmeier pmeier marked this pull request as ready for review September 22, 2022 14:54
Copy link
Member

@NicolasHug NicolasHug left a comment

Choose a reason for hiding this comment

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

No opinion from my side, accepting to unblock (let's just make sure this is fine with @YosuaMichael as well before merging)

As a side Q:

In #6587 we decided to split the transforms tests into three CI steps. This makes it easier to find failing tests

Is there a way to tell GA to report the failing tests separately, something like what CircleCI does with a dedicated "failing tests" tab ?

shell: bash
run: pytest --durations=20 test/test_prototype_transforms*.py

- name: Run prototype models tests
if: ${{ success() || steps.datasets.conclusion == 'failure' || steps.transforms.conclusion == 'failure' }}
Copy link
Contributor

@YosuaMichael YosuaMichael Sep 23, 2022

Choose a reason for hiding this comment

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

@pmeier If I understand correctly, since we have:

if: ${{ success() || steps.datasets.conclusion == 'failure' }}

on the transforms test, therefore it will not be skipped and will have state of either success or failure.

In this case, I think we dont need steps.datasets.conclusion == 'failure' conditions here since it is kinda redundant. I might be wrong on this though, could you confirm this @pmeier ?

Just to make it clear, I think the following should be enough:

if: ${{ success() || steps.transforms.conclusion == 'failure' }}

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

therefore it will not be skipped and will have state of either success or failure.

failure is not concrete enough. It will not be skipped in case of failure of the datasets tests. If the failure happens in any other step, e.g. torchvision installation, the step will be skipped.

In this case, I think we dont need steps.datasets.conclusion == 'failure' conditions here since it is kinda redundant.

They are not redundant. If we leave them out, we are left with if: success() which is the default behavior if you don't define if: at all. Meaning, the step will only be run if all previous steps have succeeded.

We need this step to run if all setup steps (everything before the first test step) have succeeded, regardless of the state of the datasets tests. IMO success() || steps.datasets.conclusion == 'failure' is shortest expression that gets us this behavior, but if you can find a better one, I'm all ears.

shell: bash
run: pytest --durations=20 test/test_prototype_transforms*.py

- name: Run prototype models tests
if: ${{ success() || steps.datasets.conclusion == 'failure' || steps.transforms.conclusion == 'failure' }}
Copy link
Member

@NicolasHug NicolasHug Sep 23, 2022

Choose a reason for hiding this comment

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

They are not redundant. If we leave them out, we are left with if: success() which is the default behavior if you don't define if: at all. Meaning, the step will only be run if all previous steps have succeeded.

I don't think @YosuaMichael is suggesting to remove all XYZ == 'failure' checks. From what I understand I think he's suggesting the following change only at this specific line (which I agree seems like it should work):

Suggested change
if: ${{ success() || steps.datasets.conclusion == 'failure' || steps.transforms.conclusion == 'failure' }}
if: ${{ success() || steps.transforms.conclusion == 'failure' }}

In more general terms, step N only needs to check the status of step N - 1; it does not need to check the status of step N - 2 (which is what the PR is currently doing)

Copy link
Member

Choose a reason for hiding this comment

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

Although I guess that

success() || steps.transforms.conclusion == 'failure'

will evaluate to False if transforms passed but datasets failed...? In which case I agree we need the long form.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What if steps.datasets.conclusion == 'failure' and steps.transforms.conclusion == 'success'? success() will be false since we have at least one failure.

In this case success() || steps.transforms.conclusion == 'failure' boils down to false || false -> false and the step is not run.

With my version we get false || true || false -> true and the step will be run.

In general we need an expression that makes sure that the setup has succeeded. This is achieved by checking success() or failure of any of the steps afterwards.

Branching is a pain in CI in general, but I think with these three conditions it is somewhat tolerable. Given that this sparked quite a bit of confusion maybe we can refactor this a little. I see two options there:

  1. Change the condition to if: steps.$LAST_SETUP_STEP.conclusion == 'success'.
  2. Add a another dummy step after the setup that we can check for success

From these two I like 2. better since then we only need to remember to keep it as a last step of the setup but can do whatever we want before it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I've implemented your suggestion in 89f8306: https://github.com/pytorch/vision/actions/runs/3112539248/jobs/5046070450 prototype tests are skipped although they should be run.

Copy link
Contributor

@YosuaMichael YosuaMichael Sep 23, 2022

Choose a reason for hiding this comment

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

Sorry, was otw to the office just now. Yeah, what I meant is like what @NicolasHug suggest, and from @pmeier explanation I can understand why my suggestion doesn't work (I thought that success() only look at the last success, and this is wrong) , thanks for that.

I also saw your changes now using:

success() || ( failure() && steps.setup.conclusion == 'success' )

I think this is good (and avoid chaining)! Thanks for this!

@pmeier
Copy link
Collaborator Author

pmeier commented Sep 23, 2022

Is there a way to tell GA to report the failing tests separately, something like what CircleCI does with a dedicated "failing tests" tab ?

I wondered this myself a few months back and I found three possible options:

  1. https://github.com/dorny/test-reporter
  2. https://github.com/EnricoMi/publish-unit-test-result-action
  3. https://github.com/mikepenz/action-junit-report

Unfortunately all of these options were not exactly what I was looking for. Either they had no real pytest support, i.e. the output looked quite weird for what we want, or they added quite a bit of noise that we also don't want.

I tried to implement my own solution until I realized that I can only use container actions when running on ubuntu. For cross-platform support the action needs to be written in JS, but my skills with that are not good enough to get to a usable state in my limited free time. If you want this, I would be happy to pick it up though during work 😇

@pmeier
Copy link
Collaborator Author

pmeier commented Sep 23, 2022

It seems if: steps.setup.conclusion == 'success' is not sufficient if there is an failure earlier even if the condition is otherwise true. Thus, I went with if: success() || ( failure() && steps.setup.conclusion == 'success' ) which seems to do the job.

A little more complex than I had hoped before, but avoid the condition chain for multiple steps and thus should still be easier than the initial proposal. LMK what you think.

@pmeier
Copy link
Collaborator Author

pmeier commented Sep 23, 2022

The current ongoing prototype datasets breakage illustrates the need for this PR pretty well: In #6627 the breakage in the datasets prevented the transforms tests from running. Thus we needed to manually remove the datasets tests from the CI config there to get a signal from the transforms tests.

In this PR, the breakage is still there, but all other tests are run as well. Thus, we can simply ignore the failing tests and move on.

@pmeier pmeier merged commit 784ee2b into pytorch:main Sep 23, 2022
@pmeier pmeier deleted the if-prototype-ci branch September 23, 2022 12:54
facebook-github-bot pushed a commit that referenced this pull request Sep 29, 2022
Reviewed By: YosuaMichael

Differential Revision: D39885423

fbshipit-source-id: 800f0a996f8aeb6bf02c53cceea231bedf8a7b56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants