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

Handle absence of value for --all-or-nothing properly #1296

Merged
merged 1 commit into from
Jan 11, 2023

Conversation

agustingomes
Copy link
Contributor

@agustingomes agustingomes commented Jan 9, 2023

Expected behavior:

Upon specification of the option --all-or-nothing wraps multiple migrations into a transaction

Observed behavior

Specifying --all-or-nothing by itself does not cause the desired effect, as the result of the statement $input->getOption('all-or-nothing') is null, and therefore, in the absence of config, this value is ultimately evaluated to false, therefore not wrapping multiple migrations into a single transaction.

Q A
Type bug
BC Break no
Fixed issues #1279

Summary

@greg0ire
Copy link
Member

greg0ire commented Jan 9, 2023

As stated in #1279 today, this looks to me more like an unintended bug introduced in #1161. Can you take a look and let me know what you think?

@agustingomes
Copy link
Contributor Author

Hi @greg0ire

I will try to add a failing test case if possible. I'll keep you posted.

@agustingomes
Copy link
Contributor Author

@greg0ire I added an extra permutation for the data provider of the allOrNothing test, which confirms that the behavior is not as expected.

What would you advice as next step?

@greg0ire
Copy link
Member

greg0ire commented Jan 9, 2023

  • revert the doc change
  • fix the bug: $allOrNothing = $input->hasOption('all-or-nothing') ? $input->getOption('all-or-nothing') ?? true : null; should IMO do the trick.

@agustingomes
Copy link
Contributor Author

@greg0ire unfortunately your suggestion alone does not seem to do the trick.

I've checked the hasOption method in Symfony and it seems that method is not a reliable way to know if a user passed the command option or not.

In any case, I'll do a small refactor there to stop using hasOption.

@greg0ire
Copy link
Member

greg0ire commented Jan 9, 2023

Indeed! I think by using a default value different than null (like false?) for all-or-nothing, you might be able to tell whether the option was used or not with getOption

@agustingomes
Copy link
Contributor Author

agustingomes commented Jan 9, 2023

I'm not sure @greg0ire

I'll give it some thought over the week, since it seems like relying on the default value of the option may not work, as it can override the Doctrine project configuration.

@greg0ire
Copy link
Member

greg0ire commented Jan 9, 2023

I guess if you set the default to false, you would then have to translate null to true (option provided), and false to null (default value, option not provided), so that the line $allOrNothing = (bool) ($allOrNothing ?? $this->configuration->isAllOrNothing()); continues to work as intended. Bit convoluted, maybe you'll find something more elegant than this. And maybe we should use VALUE_NONE in 4.0, to simplify all this.

@agustingomes
Copy link
Contributor Author

And maybe we should use VALUE_NONE in 4.0, to simplify all this.

That sounds like a good idea.

@greg0ire greg0ire changed the title Correct documentation of --all-or-nothing on config absence Handle absence of value for --all-or-nothing properly Jan 9, 2023
@greg0ire
Copy link
Member

greg0ire commented Jan 9, 2023

You can use vendor/bin/phpcbf to fix the cs issues.

@agustingomes
Copy link
Contributor Author

@greg0ire how do you want to proceed regarding the PHPStan failures? THey seem to be originating from deprecations, and the BC check error I never seen it before.

@greg0ire
Copy link
Member

greg0ire commented Jan 9, 2023

Nice commit messages. I've seen the test failing, so you can squash both commits now, so that all commits pass the build.

@greg0ire
Copy link
Member

greg0ire commented Jan 9, 2023

@greg0ire how do you want to proceed regarding the PHPStan failures? THey seem to be originating from deprecations, and the BC check error I never seen it before.

Don't worry about those, I'll take care of it.

Regarding the BC-check, it seems to have been broken for a while: Nyholm/roave-bc-check-docker#32
Regarding the static analysis issues, I created #1297

@agustingomes agustingomes force-pushed the patch-1 branch 2 times, most recently from e729e54 to 10b6936 Compare January 10, 2023 06:33
return null;
}

return (bool) ($allOrNothingOption ?? true);
Copy link
Member

Choose a reason for hiding this comment

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

If the command does not have the option, the value will default to true, but I guess it does not matter since all-or-nothing is not used when the option is not defined.

Copy link
Contributor

@e-jevdokimovs e-jevdokimovs Jan 17, 2023

Choose a reason for hiding this comment

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

This is a problem, the default value of MigrationConfiguration property allOrNothing is false, these changes always set the value to true if the option isn't passed at all AND the command doesn't have an all-or-nothing option, for example ExecuteCommand.

Copy link
Member

Choose a reason for hiding this comment

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

You mean the option is used although it's not defined in the command? Where?

Copy link
Contributor

Choose a reason for hiding this comment

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

The option itself isn't used, but ConsoleInputMigratorConfigurationFactory->getMigratorConfiguration() is being called in ExecuteCommand->execute() which in turn creates a MigratorConfiguration with allOrNothing set to true because ExecuteCommand doesn't have an all-or-nothing option which results in the value not defaulting to notprovided.

Copy link
Contributor

Choose a reason for hiding this comment

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

Basically this method should look like this:

        if (!$input->hasOption('all-or-nothing')) {
            return null;
        }

        $allOrNothingOption = $input->getOption('all-or-nothing');

        if ($allOrNothingOption === 'notprovided') {
            return null;
        }

        return (bool) ($allOrNothingOption ?? true);

Copy link
Contributor

Choose a reason for hiding this comment

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

Created a PR with the fix: #1308

This test case addition simulates what happens when the
`--all-or-nothing` option is indicated, but no explicit
value is passed.

We'll set a default option, which is retrieved in case the option
has not been provided, allowing us to override the value in case the
option is different than the default value.
@greg0ire greg0ire added this to the 3.5.3 milestone Jan 11, 2023
@greg0ire greg0ire merged commit 01f89a1 into doctrine:3.5.x Jan 11, 2023
@greg0ire
Copy link
Member

Thanks @agustingomes !

@greg0ire
Copy link
Member

And maybe we should use VALUE_NONE in 4.0, to simplify all this.

That sounds like a good idea.

@agustingomes if you want to work on this, you can open a PR on 3.6.x to deprecate passing a value :)

Here is an example:

Deprecation::trigger(
'doctrine/migrations',
'https://github.com/doctrine/migrations/issues/1169',
<<<'DEPRECATION'
Context: trying to commit a transaction
Problem: the transaction is already committed, relying on silencing is deprecated.
Solution: override `AbstractMigration::isTransactional()` so that it returns false.
Automate that by setting `transactional` to false in the configuration.
More details at https://www.doctrine-project.org/projects/doctrine-migrations/en/3.2/explanation/implicit-commits.html
DEPRECATION
);

@agustingomes agustingomes deleted the patch-1 branch January 11, 2023 09:22
@agustingomes
Copy link
Contributor Author

@greg0ire I'll look into it the next days 👍🏼

agustingomes added a commit to agustingomes/doctrine-migrations that referenced this pull request Jan 15, 2023
During the iteration of the PR doctrine#1296 an idea to deprecate passing values to this option was suggested, given how complicated was to handle using that option without any value, which led to a bug and inconsistency with the documentation.

As specified in the deprecation message, using this option from 4.0.x onwards in the CLI will be treated as `true`, and the option itself won't accept values.
agustingomes added a commit to agustingomes/doctrine-migrations that referenced this pull request Jan 16, 2023
During the iteration of the PR doctrine#1296 an idea to deprecate passing values to this option was suggested, given how complicated was to handle using that option without any value, which led to a bug and inconsistency with the documentation.

As specified in the deprecation message, using this option from 4.0.x onwards in the CLI will be treated as `true`, and the option itself won't accept values.
e-jevdokimovs added a commit to e-jevdokimovs/migrations that referenced this pull request Jan 17, 2023
This fixes a bug that was introduced in doctrine#1296 where the configuration
value of allOrNothing got set to true if the command didn't have an
all-or-nothing option. Now the value is set from input options only if
the command that is being executed has an `all-or-nothing` option.
agustingomes added a commit to agustingomes/doctrine-migrations that referenced this pull request Oct 10, 2023
During the iteration of the PR doctrine#1296 an idea to deprecate passing values to this option was suggested, given how complicated was to handle using that option without any value, which led to a bug and inconsistency with the documentation.

As specified in the deprecation message, using this option from 4.0.x onwards in the CLI will be treated as `true`, and the option itself won't accept values.
agustingomes added a commit to agustingomes/doctrine-migrations that referenced this pull request Oct 10, 2023
During the iteration of the PR doctrine#1296 an idea to deprecate passing values to this option was suggested, given how complicated was to handle using that option without any value, which led to a bug and inconsistency with the documentation.

As specified in the deprecation message, using this option from 4.0.x onwards in the CLI will be treated as `true`, and the option itself won't accept values.
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.

3 participants