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

Support for PHP 8 #467

Merged
merged 18 commits into from
Dec 29, 2020
Merged

Support for PHP 8 #467

merged 18 commits into from
Dec 29, 2020

Conversation

evansims
Copy link
Member

@evansims evansims commented Nov 19, 2020

Description

This branch includes work necessary for the SDK to work with the new release of PHP 8. Most of this PR involves making accommodations for updated dependencies, as the library's own code is compatible with PHP 8.

  • These changes require us to bump our minimum supported PHP version from 7.1 to 7.3.
  • PHPUnit dependency bumped to 9.3 (from 7) as PHP 8 support will not be getting backported.
  • Updated unit tests to support syntax changes in PHPUnit 9. Functionally they are unchanged.
  • Introduced a reflection workaround to accommodate PHPUnit 8+ dropping support for accessing invocation stacks natively.
  • Guzzle dependency bumped to 7.2 as PHP 8 support will not be getting backported. Drops support for Guzzle 6.
  • Overrides our JWT dependency to use a patched repo @ https://github.com/auth0/php-jwt/tree/3.3-php8-compatibility (1)
  • Improvements to code styling/formatting and docblock definitions
  1. PHP 8 introduces changes to the OpenSSL functions which cause the JWT library we depend on to break. The author of the library appears to be working on a major refactoring for a future release (which will require non-trivial effort for us to adapt the SDK to those changes), so I've forked the stable build we currently use and have applied a patch to fix the issues until the upstream package is fixed, and we're able to adapt the SDK to the changes they're making to the library.

Note: Our CircleCI tests will fail for this PR as we are testing against PHP versions that this PR drops support for. PHP 7.1 and 7.2 CI tests have been removed to make way for these changes.

Testing these changes locally

CircleCI is already configured to run our standard tests using PHP 8.0 for this PR; you can review the results in the PR timeline. If you'd like to test these changes locally, you should:

  • Install PHP 8.0; configure your local environment to use it
  • Fork PR branch
  • Run 'composer install' to install dependencies
  • Run 'composer test-unit' to ensure 8.0 compatibility
  • Run 'composer compat' to ensure 7.3+ compatibility

@evansims evansims marked this pull request as ready for review December 7, 2020 15:54
@evansims evansims requested a review from a team as a code owner December 7, 2020 15:54
@evansims evansims added this to the 7.6.0 milestone Dec 7, 2020
@evansims evansims mentioned this pull request Dec 9, 2020
BackEndTea
BackEndTea previously approved these changes Dec 11, 2020
@Nielsvanpach
Copy link

Hi there, what are the remaining steps before this PR can be merged?

@evansims
Copy link
Member Author

Hi there, what are the remaining steps before this PR can be merged?

Hey @Nielsvanpach it's currently going through our internal review process. Hopefully not too much longer.

@johnvandeweghe
Copy link

johnvandeweghe commented Dec 28, 2020

@evansims Heads up that the dependency for lcobucci/jwt at dev-3.3-php8-compatibility#daa6aff67a22bf737504143ae55a6913d9ff484d doesn't seem to exist anymore. Not sure if they cleaned out the branch, or I'm doing something wrong. I ran into this when attempting to point a project at this branch.

@evansims
Copy link
Member Author

evansims commented Dec 28, 2020

Hey @johnvandeweghe 👋 Thanks for the heads up! We're in the process of moving the fixed fork branch you mentioned into the Auth0 org, so things are getting renamed and moved around a bit at the moment. For the moment it's now at https://github.com/evansims/php-jwt and I'll update this PR to reflect that to fix this for you. I'll update it again once the move is complete!

The fork has now come to rest at it's final destination, https://github.com/auth0/php-jwt. I've updated this PR branch to reflect the new location.

"ext-json": "*",
"lcobucci/jwt": "^3.3",
"ext-openssl": "*",
Copy link
Contributor

Choose a reason for hiding this comment

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

is there a minimum version we can require here? better than using "any". Same for ext-json above.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ideally yes, I agree that would be preferred here. The problem with specifying versions in this manner for PHP extensions is that it will block the SDK from installing in environments running in-development/pre-release versions of PHP.

For example, we could specify "ext-json": ^1.7 | ^7.4 | ^8.0, and our SDK would install for all GA versions of PHP we support. However, it would block installation in any forthcoming snapshots, betas or RCs, such as imminent development around 7.5 or 8.1 releases. You'd be surprised how many people run those. We can get around this by specifying development versions but this will lead to a lot of maintenance on our end.

Besides, it isn't really terribly important what version of these extensions a user has installed here, as long as they have one and it's enabled. These extensions will only build and work for appropriate PHP versions, so it's impossible to have an out of date extension on an up to date and supported PHP version.

"require": {
"php": "^7.1",
"guzzlehttp/guzzle": "~6.0 | ~7.0",
"php": "^7.3 | ^8.0",
Copy link
Contributor

Choose a reason for hiding this comment

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

how often do we do these changes, shouldn't these be on a major release instead of a minor?

Copy link
Member Author

Choose a reason for hiding this comment

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

How often do we do these changes
Dropping PHP versions isn't often required, every 2-3 years generally. (Our SDK technically still runs fine on 7.1, but we have to accommodate dependency requirements.)

Moving forward, my goal is for us to follow the official PHP support schedule by deprecating (at year 2) and ultimately dropping (at year 3) support for EOL PHP versions in our SDK, following the official runtime support and security expirations. This would allow us to offer clarity and transparency as to our support windows for customers, and follows best practices in general. It would also have avoided us needing to leapfrog support for two PHP versions at once, as well. But this is a discussion for another day, I suppose.

Shouldn't these be on a major release instead of a minor?
Since there are no public API changes on our end, and therefor no breaking changes, this wouldn't require a major from us according to semver.

As our only supported installation method is, like nearly all PHP libraries, through Composer, the version bump won't break users environments as Composer will simply block them from upgrading.

In general, dropping PHP support isn't considered a breaking change in the PHP community. Here's how Doctrine puts it;

One question we frequently hear is, "isn't dropping support for a PHP version a BC break"? In a nutshell, no. A BC break happens when there is an incompatible change that your package manager can't handle. For example, changing a method signature in a minor version is a no-go, since the composer version constraints mentioned above assume any minor upgrade can safely be used.

However, when we drop support for an older version of PHP, composer will not consider the new version if the PHP version requirement is no longer fulfilled. Thus, you won't end up with a fatal error due to a wrong method signature, you just won't get the new version.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'd treat any requirement change as a breaking change that would require a major release if now the conditions are more restrictive than before.

As our only supported installation method is, like nearly all PHP libraries, through Composer, the version bump won't break users environments as Composer will simply block them from upgrading.

In this particular case, if you can ensure Composer will prevent users from installing this (now incompatible for older PHP setups) new version dependency, then that and the EOL of the previous version is enough to accept this change being released as a minor release.

$this->assertContains( 'per_page=5', $api->getHistoryQuery() );

$query = $api->getHistoryQuery();
$this->assertStringContainsString( 'page=0', $query );
Copy link
Contributor

Choose a reason for hiding this comment

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

As a general comment for all these query string assertions. If you match against page=5 it will also pass, because of the line below "per_page=5". I think it's better to test these individually, parsing the query and extracting each key/val into a dictionary/map structure first. No need to do that now unless that's a quick fix, but would like to see it tracked.

Copy link
Member Author

Choose a reason for hiding this comment

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

That's a good suggestion, but I'd like to avoid getting refactoring tests in this PR. I was just aiming to get these working with minimum viable changes for the purposes of getting PHP 8 support shipped right away. I'll get a ticket going to improve this though, thank you.

@@ -48,6 +49,23 @@ public function getMock(array $args = [])
return $mockStore;
}

/**
* Gain access to PHPUnit's mock invocation stack for analyzing calls.
* PHPUnit 8.4 removed the native getInvocations property, requiring this workaround.
Copy link
Contributor

Choose a reason for hiding this comment

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

what is the official phpunit alternative to this, now removed, method?

Copy link
Member Author

Choose a reason for hiding this comment

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

This test was created around a private API (getInvocations) in PHPUnit, which has since been revoked. Since it was a private API, no direct alternatives were provided. With some effort this test can be rewritten to use public APIs like expects() and exactly(), but rewriting tests felt outside the scope of introducing PHP 8 support so I went this route to accommodate us in the meantime.

Now that we're moving to a modern version of PHPUnit, this will allow us to pursue a goal I've had for awhile: a complete review and restructuring of our test suite, and the introduction of tools like Infection, PHPStan and PHPBench to give us a much more robust testing platform. This cookie test is probably my least favorite part of our current setup, so that will receive a major rework in those efforts.

@lbalmaceda lbalmaceda self-requested a review December 29, 2020 17:40
Copy link
Contributor

@lbalmaceda lbalmaceda left a comment

Choose a reason for hiding this comment

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

LGTM

@evansims evansims merged commit 8f3c28e into master Dec 29, 2020
@evansims evansims deleted the update-php8 branch December 29, 2020 17:53
@github-actions
Copy link
Contributor

This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants