Do not run the Max PHP jobs when the PHP version is the same as 'current'

Created on 28 October 2024, about 2 months ago

Problem/Motivation

To save resources, there is no reason to run the "Max PHP" variants when the PHP version is no higher than the "current" php version. This is currently the situation with D11 being the new "current" core version. In the variables file we have:

  # The minimum supported version of PHP for the current stable version of Drupal.
  CORE_PHP_MIN: "8.3"

  # The maximum/latest supported version of PHP for the current stable version of Drupal.
  CORE_PHP_MAX: "8.3"

PHP8.3 is the minimum required, and there is no Core version that supports PHP8.4 yet. So the "Max PHP" variants (Composer, PHPStan, PHPUnit and Nightwatch) will run with PHP8.3 thus duplicating what the "current" varaint does, and is therefore unnecessary and a waste of resources.

This issue is a spin-off from #3483075-9: Run on PHP 8.4 when OPT_IN_TEST_MAX_PHP=1 see comments #9-12

Proposed resolution

Add a rule to the "Max PHP" variants which says "If the php version is the same as core_php_min then do not run the job"

Remaining tasks

User interface changes

📌 Task
Status

Active

Component

gitlab-ci

Created by

🇬🇧United Kingdom jonathan1055

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @jonathan1055
  • Pipeline finished with Success
    about 2 months ago
    Total: 53s
    #323049
  • 🇬🇧United Kingdom jonathan1055

    Baseline test without this MR
    https://git.drupalcode.org/project/scheduler/-/pipelines/323144

    Initial test with this MR, and the new rule

    # Rule to check that max PHP variants will do something different from 'current'
    .check-max-php-version-rule: &check-max-php-version-rule
      if: $PHP_VERSION == $CORE_PHP_MIN
      when: never
    

    https://git.drupalcode.org/project/scheduler/-/pipelines/323149
    The composer and PHPStan 'max' variants are still run. The variable values are written out in the composer before_script, and that shows:
    _TARGET_PHP=8.3, PHP_VERSION=8.3, CORE_PHP_MIN=8.3, CORE_PHP_MAX=8.3
    So something is wrong with the new rule.

  • 🇪🇸Spain fjgarlin

    Is this issue "Needs work" or "Needs review"? The code in the MR looks good and #3 has a test with and without the changes.

  • 🇬🇧United Kingdom jonathan1055

    It is 'needs work' because the test with the MR changes did not work. The max variants were still run, so the rule does not work. I've been doing some more investigation and wil report back when I have some answers.

  • 🇪🇸Spain fjgarlin

    100% right. I was quick-reading / catching up on things and my brain just read what it wanted to read, not what it said.

    I left feedback in the MR. I'm sure it didn't work because PHP_VERSION is dynamic and not set globally. rules might run before variables in this case. I suggested a workaround in the MR.

  • 🇬🇧United Kingdom jonathan1055

    Thanks for the feedback on the MR. I had actually already done some more investigation, but did not have the time to post it here earlier. Sorry, I could have saved you some effort and thinking time :-)

    Maybe it's because PHP_VERSION is only available/set dynamically.

    Yes that is partly right, but there is more to it than that. The variable does exist during the rules evaluation, I proved this by using

      if: $PHP_VERSION != null
      when: never
    

    This matched and job was not added. So PHP_VERSION does exist, but is not the value we expect. Echoing the variable prints the expected 8.3 as mentioned in #3. At rules-time the variable does have something, because

      if: $PHP_VERSION == ""
    

    is false and does not match. Hard-coding in the rule did not help:

      if: $PHP_VERSION == "8.3"
    

    is also false. After some experimentation with pattern matching, I found that the value during rules evaluation is the plain text that is specified in the variable definition and this is not further evaluated if it refers to another variable. Thus, in the composer Max PHP variant,

      if: $PHP_VERSION =~ '/CORE_PHP_MAX/'
    

    is true. This is the value defined in the variant's variables:. The text 'CORE_PHP_MAX' is contained in the value, in fact it matches precisely with $PHP_VERSION =~ '/^\$CORE_PHP_MAX$/' showing that it starts with '$' and has nothing more at the end.

    For the PHPStan max PHP variant, the value is different at rules evaluation time. Here, the pattern that matches is if: $PHP_VERSION =~ '/^\$_TARGET_PHP$/'. This is because the PHPStan max job does not have it's own definition for PHP_VERSION, so is taking the original default. At runtime it all resolves correctly.

    I'd just run this check in the composer (max php) job, as all the others depend on it, and I'd just check if $CORE_PHP_MIN == $CORE_PHP_MAX instead.

    That test would work, as both of those variables have actual values, as specified in the hidden variables file. It would mean that if anyone wants to try out the Max PHP jobs before they are fully supported (the reason for Run on PHP 8.4 when OPT_IN_TEST_MAX_PHP=1 Active ) then they would need to hard-code variables: CORE_PHP_MAX: 8.4 in their .gitlab-ci.yml. They would not be able to use the general PHP_VERSION: to customise it, or use $CORE_PHP_NEXT as the value. This may be acceptable though, we'll need to test the implications of altering the hidden variable, and it can be documented easily.

    *check-max-php-version-rule ... This and all of the below ones are not needed

    Unfortunately, the rules are required in each of the Max variant jobs. Our pipeline structure uses needs: to specify job dependencies and flow, etc. When the pipeline is being constructed, if a job is going to be added (becuase no rules prevent it) then if the job that it "needs:" does not exist (because a rule matched to remove that job) we get the build-time error

    'phpstan (max PHP version)' job needs 'composer (max PHP version)' job, but 'composer (max PHP version)' is not in any previous stage
    

    There might be a different way to specify job flow and dependencies, but that's for a separate issue. For this one, we need the rule repeated, just like we have done with all the 'skip' rules.

    I will try out the change to use those two fixed variabes. There may also be a way to use the knowledge of rules evaluation-time variables to make a better rule.

    This has been a long post, and it took a while to work out what was happening. This background knowledge is useful in general, and it has helped me to further understand the mechanics of pipeline creation.

  • 🇪🇸Spain fjgarlin

    Oh wow, I'm surprised by that behaviour. It's amazing that you managed to understand it (I'm sure after a good deal of tries). But yeah, in any case, it's what we have to work with.

    Let's see if the solution is elegant and BC, otherwise I'm thinking we could do something similar as with the variants. Leave the variable empty from our end, and in that case, do not run the job.

  • Pipeline finished with Failed
    about 2 months ago
    Total: 54s
    #326833
  • Pipeline finished with Failed
    about 2 months ago
    Total: 52s
    #326843
  • 🇬🇧United Kingdom jonathan1055

    I have altered the rule to

      if: $CORE_PHP_MIN == $CORE_PHP_MAX && ($PHP_VERSION =~ '/^\$_TARGET_PHP$/' || $PHP_VERSION =~ '/^\$CORE_PHP_MAX$/')
      when: never
    

    There are two parts and both have to be true for the rule to match and prevent the jobs running.

    The first part in words "if the pre-defined php_max is no different to php_min" - this is the basic thing we are checking, the situation right now is that php_max is the same as php_min. As soon as we increase php_max this rule will never be true and the Max jobs will run.

    The second part allows for early testing of the next php version, before gitlab_templates updates php_max. It is saying "If the php_version variable has not been customised from the initial value then do not run the Max jobs". This means that we can test the Max jobs by setting a custom value for PHP_VERSION in the Composer Max and PHPUnit Max jobs. This also avoids the user having to change CORE_PHP_MAX to a higher value. They can just set PHP_VERSION in the required job.

    Tested here with OPT_IN_TEST_MAX_PHP: 1 and the "max" jobs do not run.
    https://git.drupalcode.org/project/scheduler/-/pipelines/326852

  • 🇬🇧United Kingdom jonathan1055

    Added

    variables:
        PHP_VERSION: $CORE_PHP_NEXT
    

    to the composer and phpstan max jobs. These now both run. Note that phpunit does not run as required.
    https://git.drupalcode.org/project/scheduler/-/pipelines/326865

    Now adding the above to phpunit max job, and all three jobs run.
    https://git.drupalcode.org/project/scheduler/-/pipelines/326871

  • 🇪🇸Spain fjgarlin

    Thanks so much for the explanation in #9, it really helps to understand the changes. The code looks good to me.
    Thanks as well for all the tests in #10.

    Running the dowsntream pipelines (https://git.drupalcode.org/issue/gitlab_templates-3484055/-/pipelines/32...). RTBC.

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024