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

Set 250 as an upper limit for retries #27797

Closed

Conversation

MuazOthman
Copy link
Contributor

This PR sets an upper limit of 250 (inclusive) for all config values specifying the number of retries in the cloud, including:

  • retries when set to a number
  • retries.runMode
  • retries.openMode
  • retries.experimentalOptions.maxRetries
  • experimentalBurnIn.default
  • experimentalBurnIn.flaky

PR Tasks

@cypress
Copy link

cypress bot commented Sep 12, 2023

24 flaky tests on run #51044 ↗︎

0 28100 1345 0 Flakiness 24

Details:

Fixed unit tests
Project: cypress Commit: 558447fe6d
Status: Passed Duration: 18:05 💡
Started: Sep 15, 2023 1:45 AM Ended: Sep 15, 2023 2:03 AM
Flakiness  commands/net_stubbing.cy.ts • 1 flaky test • 5x-driver-firefox

View Output Video

Test Artifacts
network stubbing > waiting and aliasing > can spy on a 304 not modified image response Output
Flakiness  e2e/origin/commands/assertions.cy.ts • 1 flaky test • 5x-driver-firefox

View Output Video

Test Artifacts
cy.origin assertions > #consoleProps > .should() and .and() Output
Flakiness  cypress/cypress.cy.js • 3 flaky tests • 5x-driver-firefox

View Output Video

Test Artifacts
... > correctly returns currentRetry Output
... > correctly returns currentRetry Output
... > correctly returns currentRetry Output
Flakiness  runs.cy.ts • 1 flaky test • app-e2e

View Output Video

Test Artifacts
... > displays each run with correct information Test Replay Output Screenshots
Flakiness  specs_list_latest_runs.cy.ts • 1 flaky test • app-e2e

View Output Video

Test Artifacts
App/Cloud Integration - Latest runs and Average duration > when no runs are recorded > shows placeholders for all visible specs Test Replay Output Screenshots

The first 5 flaky specs are shown, see all 12 specs in Cypress Cloud.

Review all test suite changes for PR #27797 ↗︎

Copy link
Contributor

@AtofStryker AtofStryker left a comment

Choose a reason for hiding this comment

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

any idea how this behaves when retries is set on the describe or test level? I wonder if its worth while to add a test to verify an error is thrown when the following happens. I'd think a system-test in retries_spec is sufficient?

describe('foo', { retries: 260 }, () => {
  it('tests', () => {
    expect(true).to.be.false
  })
})

@mabela416
Copy link
Contributor

mabela416 commented Sep 13, 2023

The error message should mention the limit of retries
image

image

@MuazOthman
Copy link
Contributor Author

@AtofStryker I'm not sure we have any example of such test. We don't even test validating retries at the test level.

@MuazOthman
Copy link
Contributor Author

@mabela416 I pushed an update refactoring validation and providing more detailed error messaging

Copy link
Contributor

@mabela416 mabela416 left a comment

Choose a reason for hiding this comment

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

The new validation allows me to set runMode and openMode to a boolean without setting anything else when that shouldn't be the case. This is the error we should be getting
image

@MuazOthman
Copy link
Contributor Author

@mabela416 I believe setting runMode or openMode or both as booleans should be a valid state. If I understand it correctly, these boolean values mean "enable retries in that mode", and we do have defaults for all other values that can be utilized in that case.
Can you verify if this is makes sense, @ryanpei?

@mabela416
Copy link
Contributor

@mabela416 I believe setting runMode or openMode or both as booleans should be a valid state. If I understand it correctly, these boolean values mean "enable retries in that mode", and we do have defaults for all other values that can be utilized in that case. Can you verify if this is makes sense, @ryanpei?

If you check develop or even the feature/test-burn-in branch, if you try to just do, you'll get an error

{
 retries: {
  runMode: true
  openMode: true
 }
}

@MuazOthman
Copy link
Contributor Author

@mabela416 correct, using a boolean for these fields is a new option added within this initiative. See: https://github.com/cypress-io/cypress/pull/27412/files#diff-9fde1fb2f7eaba5ea49b585c811461495bfbba88e614e900a96863ecfe6b980aR2842

@mabela416
Copy link
Contributor

@mabela416 correct, using a boolean for these fields is a new option added within this initiative. See: https://github.com/cypress-io/cypress/pull/27412/files#diff-9fde1fb2f7eaba5ea49b585c811461495bfbba88e614e900a96863ecfe6b980aR2842

I believe that is only the case IF experimentalStrategy is going to be set, otherwise it defaults to the current api which doesn't allow for booleans. Tagging @AtofStryker as well since he implemented this logic
"The config validation for this is a bit wonky in order to support the currently supported config of runMode and openMode. If none of the experimental keys are present, runMode and openMode can be the current API. However, if experimentalStrategy is provided, runMode and openMode MUST be booleans. Additionally, if the experimentalStrategy is valid, and experimentalOptions are provided, both keys MUST be present."
#27412

@AtofStryker AtofStryker self-requested a review September 15, 2023 20:21
@AtofStryker
Copy link
Contributor

@mabela416 I believe setting runMode or openMode or both as booleans should be a valid state. If I understand it correctly, these boolean values mean "enable retries in that mode", and we do have defaults for all other values that can be utilized in that case. Can you verify if this is makes sense, @ryanpei?

If you check develop or even the feature/test-burn-in branch, if you try to just do, you'll get an error

{
 retries: {
  runMode: true
  openMode: true
 }
}

@mabela416 this is expected since there is no experimentalStrategy defined, which means runMode and openMode either need to be unset, numbers, or be null.

@AtofStryker
Copy link
Contributor

@AtofStryker I'm not sure we have any example of such test. We don't even test validating retries at the test level.

@MuazOthman We do test this is it just isn't obvious. I am working on a review description to help point you in the correct place, but we might want to change the way we approach this PR. More details soon!

Copy link
Contributor

@AtofStryker AtofStryker left a comment

Choose a reason for hiding this comment

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

Sorry it has taken me so long to re-review this PR.

I think there is quite a bit going on in this PR and it is trying to accomplish two things:

  1. set the retries limit to 250, inclusive of burn and other properties
  2. refactor the messaging/validation logic for experimental retries.

What I think we might want to do here, since some might view the 250 limit on retries a breaking change, is PR the validation update for current GA retries to 250 into develop and create a CHANGELOG entry as a bugfix. This would also be a more refined changed, and we can add the config tests and system test in testConfigOverrides, which we would just need a test in testConfigOverrides cypress specs that tests the retries threshold. A current example is this system test, which runs this spec and fails since the override is invalid. Either myself or someone on the app team can help you with this since sometimes getting this set up isn't exactly obvious.

Then, when that change goes in, merge it into feature/test-burn-in feature branch, and create a PR that goes into feature/test-burn-in that sets the limits mentioned in the PR descriptions and refactors the messaging validation logic to handle default merging when no value is present. Technically the later can be done independently if we think that is a better option.

Does that sound like an OK plan moving forward?

@@ -883,29 +883,29 @@ describe('lib/config', () => {
})

context('retries', () => {
const retriesError = 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy'
// const retriesError = 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy'
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// const retriesError = 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy'

'type': 'a positive number or null or an object with keys "openMode" and "runMode" with values of numbers, booleans, or nulls, or experimental configuration with key "experimentalStrategy" with value "detect-flake-but-always-fail" or "detect-flake-and-pass-on-threshold" and key "experimentalOptions" to provide a valid configuration for your selected strategy',
'key': 'mockConfigKey.experimentalStrategy',
'value': 'foo',
'type': 'one of "detect-flake-but-always-fail", "detect-flake-and-pass-on-threshold"',
Copy link
Contributor

@AtofStryker AtofStryker Sep 19, 2023

Choose a reason for hiding this comment

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

These errors on config validation are way more readable and thank you for cleaning them up!

The one thing that is a bit critical here though is making sure that defaults get applied into the config so the app can access them through the client/server, which was one of the reasons it was an 'all or nothing' approach originally. For example:

openMode: true,
experimentalStrategy: 'detect-flake-but-always-fail'

Is a valid end user config, but we need to add defaults to the object in the app so they can be globally available. This needs to be transformed into:

openMode: true,
runMode: false,
experimentalStrategy: 'detect-flake-but-always-fail'.
experimentalOptions: {
   maxRetries: 2,
   stopIfAnyPassed: false,
}

defaultValue can take a function, but it doesn't expose the values present in the config at time of invocation.

The only thing I can think to accomplish this without adding a new mechanism, is to add defaults in the object when validation occurs since these happen by reference. Which means the validate function would have side effects ☹️


if (!isValidStopIfAnyPasses) {
return false
return errMsg(`${key}.stopIfAnyPassed`, value.stopIfAnyPassed, 'null or boolean')
Copy link
Contributor

Choose a reason for hiding this comment

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

stopIfAnyPassed I believe can either be a boolean or undefined but null is not an option based on 1137. If this has changed, we need to update the typings definition in the app in cypress.d.ts (which we might need to do anyway since the current implementation forces a user to specify it if they provide experimentalOptions on detect-flake-but-always-fail

@mabela416
Copy link
Contributor

mabela416 commented Sep 19, 2023

@mabela416 I believe setting runMode or openMode or both as booleans should be a valid state. If I understand it correctly, these boolean values mean "enable retries in that mode", and we do have defaults for all other values that can be utilized in that case. Can you verify if this is makes sense, @ryanpei?

If you check develop or even the feature/test-burn-in branch, if you try to just do, you'll get an error

{
 retries: {
  runMode: true
  openMode: true
 }
}

@mabela416 this is expected since there is no experimentalStrategy defined, which means runMode and openMode either need to be unset, numbers, or be null.

So you're expected to get an error right? Something in this PR is allowing the user to set runMode and openMode as booleans without experimentalStrategy and that shouldn't be the case, it should be an error. @AtofStryker

@AtofStryker
Copy link
Contributor

@mabela416 I believe setting runMode or openMode or both as booleans should be a valid state. If I understand it correctly, these boolean values mean "enable retries in that mode", and we do have defaults for all other values that can be utilized in that case. Can you verify if this is makes sense, @ryanpei?

If you check develop or even the feature/test-burn-in branch, if you try to just do, you'll get an error

{
 retries: {
  runMode: true
  openMode: true
 }
}

@mabela416 this is expected since there is no experimentalStrategy defined, which means runMode and openMode either need to be unset, numbers, or be null.

So you're expected to get an error right? Something in this PR is allowing the user to set runMode and openMode as booleans without experimentalStrategy and that shouldn't be the case, it should be an error. @AtofStryker

I think I read this as the inverse. You are correct that configuration should error. It might be due to some of the reasons I outlined in #27797 (comment). We might want to treat the configuration changes as a separate PR.

@MuazOthman
Copy link
Contributor Author

As previously discussed, we don't need this new limit of 250 anymore. I extracted the enhanced validation to a new PR #28214.
Closing this one.

@MuazOthman MuazOthman closed this Nov 1, 2023
@MuazOthman MuazOthman deleted the muaz/validate-retries-upper-limit branch January 4, 2024 16:42
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.

4 participants