composer-normalize: Make "paths that should not be sorted" configurable

Some elements of composer.json are highly sensitive to order, such as extra.patches with https://github.com/cweagans/composer-patches, which applies patches in the order specified and can therefore fail if it changes. See another example #699. I need a way to exclude arbitrary paths from sorting. I see that the current exclusions are hardcoded in \Ergebnis\Json\Normalizer\Vendor\Composer\ConfigHashNormalizer::PROPERTY_PATHS_THAT_SHOULD_NOT_BE_SORTED. I would like this value to be configurable like the other options. I could take a stab at a PR. Alternatively, a few specific additions to the current hardcoded list would temporarily unblock my customers. I would gladly send a PR for that, too.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 4
  • Comments: 25 (13 by maintainers)

Most upvoted comments

Yes, it’s safe to sort children of extra.patches, but not their children. That’s to say that grandchildren of extra.patches should retain their order.

I also am experiencing problems with this in the “scripts” section - I define various commands to be run via the install and update hooks (via the “auto-scripts” block shown below), but these commands need to be in a specific order, whereas when normalized they are placed in alphabetical order which is not what we want!

"scripts": {
    "post-install-cmd": [
      "@auto-scripts"
    ],
    "post-update-cmd": [
      "@auto-scripts"
    ],
    "auto-scripts": {
      "cache:clear": "symfony-cmd",
      "doctrine:migrations:migrate -v": "symfony-cmd",
      "bazinga:js-translation:dump assets --merge-domains --format=json": "symfony-cmd",
      "assets:install %PUBLIC_DIR%": "symfony-cmd"
    }
  }

When normalized changes the order and becomes:

"scripts": {
    "post-install-cmd": [
      "@auto-scripts"
    ],
    "post-update-cmd": [
      "@auto-scripts"
    ],
    "auto-scripts": {
      "assets:install %PUBLIC_DIR%": "symfony-cmd",
      "bazinga:js-translation:dump assets --merge-domains --format=json": "symfony-cmd",
      "cache:clear": "symfony-cmd",
      "doctrine:migrations:migrate -v": "symfony-cmd"
    }
  }

Hello,

About composer-patches, a workaround is to use put number at the beginning of the description like in

            "drupal/core": {
                "1 - BrowserTestBase::setUp() must be compatible with PHPUnit\\Framework\\TestCase::setUp() - https://www.drupal.org/project/drupal/issues/3182103": "https://git.drupalcode.org/project/drupal/-/merge_requests/28.patch"
            }

Best regards,

@localheinz Which property paths should be added to the hardcoded exclusions? Off the top of my head I know of the following order-dependent paths:

Hi,

@localheinz, about https://github.com/ergebnis/composer-normalize/issues/704#issuecomment-1346841515, I confirm, direct children of extra.patches can be sorted (and I like to sort it) but not their own children.

So ok with you comment result.

extra is arbitrary data that can be “virtually anything”. I don’t think a generic tool can make assumptions about its structure. At most, sort direct subkeys.

Regarding scripts, my own use case is like:

    "scripts": {
        "start": [
            "Composer\\Config::disableProcessTimeout",
            "php -S localhost:8080 -t public public/index.php"
        ],
        "phpstan": "phpstan analyse .",
        "phpcs": "phpcs",
        "phpcbf": "phpcbf",
        "rector-lint": "vendor/bin/rector process --dry-run",
        "rector-fix": "vendor/bin/rector process"
    },

Scripts are listed in logical blocks (build actions first, linters last). Linters are shown in order of importance/preference for the project. Each linter displays lint command first, fix command second. Order conveys information, I’m not fond of having it discarded blindly.

On the other side, composer list itself couldn’t care less and alphabetises scripts nonetheless.

Would some generic opt-in/opt-out setting be a solution? Can it be flexible enough without adding too much complexity?

{
  "extra": {
    "composer-normalize": {
      "skip-keys": ["scripts", "scripts-descriptions", "extra.patches"]
    }
  }
}

Hi,

@localheinz don’t blame yourself, this tool is amazing! Thanks for providing it in open source with free usage possible!

Thanks for your efforts - it really is appreciated a lot!

One point to consider - I see in the PR you are referring to auto-scripts but this is just what I have called the group - I think you can call it anything (this is just a Symfony convention IIRC).

In the scripts block at least, it is OK to sort the first level of children, but anything past that should not be sorted.

Cheers!

@benr77 Working on this!

Also using https://github.com/cweagans/composer-patches and experiencing the same issue: patches are re-ordered, but some of them need to be applied in a specific order. I’m currently working around this issue by defining my patches in a separate file (explained @ https://github.com/cweagans/composer-patches#using-an-external-patch-file).