Skip to content

Commit

Permalink
[FEATURE] Detect CI to avoid removal of outdated patches (#60)
Browse files Browse the repository at this point in the history
Cleaning up patches while running in CI is normally undesirable by default. This patch introduces automatic CI detection and new configuration options to refine the behavior of removing outdated patches.

fixes #57
fixes #59

---------

Co-authored-by: Simon Gilli <[email protected]>
  • Loading branch information
jpmschuler and gilbertsoft authored May 28, 2023
1 parent d616cae commit 41a5aa2
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 5 deletions.
1 change: 1 addition & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ env:
COMPOSER_FLAGS: --ansi --no-interaction --no-progress
COMPOSER_INSTALL_FLAGS: --prefer-dist
COMPOSER_UPDATE_FLAGS: ''
GS_CI: 0

jobs:
validation:
Expand Down
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,14 +136,36 @@ composer config extra.gilbertsoft/typo3-core-patches.ignore-branch true
When running `composer update` or `composer install`, the plugin detects changes
that already exist in the version being installed and suggests removing them. If
you run Composer with the `--no-interaction` option, the patches are always
removed.
preserved. This can be changed by the config `force-tidy-patches` see bellow.

Errors may occur if you use the source-dist of packages, which can be solved by
adding the `config.discard-changes` configuration option to your `composer.json`,
see <https://getcomposer.org/doc/06-config.md#discard-changes>. Run e.g.
`composer config discard-changes true` to add the configuration to your
`composer.json`.

If a CI environment is detected, the detection of merged changes is skipped by
default. To change this behavior and enable the detection again, run:

```bash
composer config extra.gilbertsoft/typo3-core-patches.force-tidy-patches true
```

To disable the detection of merged changes completely, run:

```bash
composer config extra.gilbertsoft/typo3-core-patches.disable-tidy-patches true
```

## CI detection

The plugin tries to detect CI environments and changes its default behavior
while running in a CI pipeline. It's possible to override the detection by
setting an environment variable:

- Set `GS_CI=1` to force CI mode
- Set `GS_CI=0` to disable CI mode

## Feedback / Bug reports / Contribution

Bug reports, feature requests and pull requests are welcome in the [GitHub
Expand Down
68 changes: 67 additions & 1 deletion src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,16 @@ final class Config implements PersistenceInterface
*/
private const PLUGIN_IGNORE_BRANCH = 'ignore-branch';

/**
* @var string
*/
private const PLUGIN_DISABLE_TIDY_PATCHES = 'disable-tidy-patches';

/**
* @var string
*/
private const PLUGIN_FORCE_TIDY_PATCHES = 'force-tidy-patches';

private JsonFile $jsonFile;

private ConfigSourceInterface $configSource;
Expand All @@ -91,6 +101,10 @@ final class Config implements PersistenceInterface

private bool $ignoreBranch = \false;

private bool $disableTidyPatches = \false;

private bool $forceTidyPatches = \false;

public function __construct(
?JsonFile $jsonFile = null,
?ConfigSourceInterface $configSource = null
Expand Down Expand Up @@ -152,6 +166,30 @@ public function getPatches(): Patches
return $this->patches;
}

public function getDisableTidyPatches(): bool
{
return $this->disableTidyPatches;
}

public function setDisableTidyPatches(bool $disableTidyPatches): self
{
$this->disableTidyPatches = $disableTidyPatches;

return $this;
}

public function getForceTidyPatches(): bool
{
return $this->forceTidyPatches;
}

public function setForceTidyPatches(bool $forceTidyPatches): self
{
$this->forceTidyPatches = $forceTidyPatches;

return $this;
}

private function isEmpty(): bool
{
if (!$this->changes->isEmpty()) {
Expand All @@ -166,7 +204,15 @@ private function isEmpty(): bool
return false;
}

return !$this->ignoreBranch;
if ($this->ignoreBranch) {
return false;
}

if ($this->disableTidyPatches) {
return false;
}

return !$this->forceTidyPatches;
}

public function load(): self
Expand Down Expand Up @@ -259,6 +305,14 @@ public function jsonSerialize(): array
$config[self::PLUGIN_IGNORE_BRANCH] = $this->ignoreBranch;
}

if ($this->disableTidyPatches) {
$config[self::PLUGIN_DISABLE_TIDY_PATCHES] = $this->disableTidyPatches;
}

if ($this->forceTidyPatches) {
$config[self::PLUGIN_FORCE_TIDY_PATCHES] = $this->forceTidyPatches;
}

return $config;
}

Expand Down Expand Up @@ -318,6 +372,18 @@ public function jsonUnserialize(array $json): self

$this->ignoreBranch = $ignoreBranch;

if (!is_bool($disableTidyPatches = $packageConfig[self::PLUGIN_DISABLE_TIDY_PATCHES] ?? null)) {
$disableTidyPatches = false;
}

$this->disableTidyPatches = $disableTidyPatches;

if (!is_bool($forceTidyPatches = $packageConfig[self::PLUGIN_FORCE_TIDY_PATCHES] ?? null)) {
$forceTidyPatches = false;
}

$this->forceTidyPatches = $forceTidyPatches;

return $this;
}
}
19 changes: 19 additions & 0 deletions src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,25 @@
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\DependencyResolver\Transaction;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Factory;
use Composer\Installer\InstallerEvent;
use Composer\Installer\InstallerEvents;
use Composer\IO\IOInterface;
use Composer\Json\JsonFile;
use Composer\Plugin\Capability\CommandProvider as ComposerCommandProvider;
use Composer\Plugin\Capable;
use Composer\Plugin\PluginInterface;
use Composer\Script\Event;
use Composer\Script\ScriptEvents;
use GsTYPO3\CorePatches\Utility\ComposerUtils;
use GsTYPO3\CorePatches\Utility\Utils;

final class Plugin implements PluginInterface, Capable, EventSubscriberInterface
{
private ComposerUtils $composerUtils;

private Config $config;

/**
* @var array<int, string>
*/
Expand All @@ -43,6 +48,10 @@ final class Plugin implements PluginInterface, Capable, EventSubscriberInterface
public function activate(Composer $composer, IOInterface $io): void
{
$this->composerUtils = new ComposerUtils($composer, $io);
$this->config = new Config(
new JsonFile(Factory::getComposerFile(), Factory::createHttpDownloader($io, $composer->getConfig()), $io),
$composer->getConfig()->getConfigSource()
);

$composer->getConfig()->getConfigSource()->addConfigSetting('allow-plugins.cweagans/composer-patches', true);
}
Expand Down Expand Up @@ -100,6 +109,16 @@ public function checkForObsoletePatches(InstallerEvent $installerEvent): void
return;
}

$this->config->load();

if (Utils::isCI() && !$this->config->getForceTidyPatches()) {
return;
}

if ($this->config->getDisableTidyPatches()) {
return;
}

$installerEvent->getIO()->write('<info>Checking for obsolete patches, this may take a while...</info>');

foreach ($installerEvent->getTransaction()->getOperations() as $operation) {
Expand Down
2 changes: 1 addition & 1 deletion src/Utility/ComposerUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ private function askRemoval(int $changeId): bool
' Should the patch for this change be removed?</info> [<comment>Y,n</comment>] ',
$changeId
),
true
$this->config->load()->getForceTidyPatches()
);
}

Expand Down
36 changes: 36 additions & 0 deletions src/Utility/Utils.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

/*
* This file is part of TYPO3 Core Patches.
*
* (c) Gilbertsoft LLC (gilbertsoft.org)
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace GsTYPO3\CorePatches\Utility;

final class Utils
{
/**
* Detects if running in CI.
*
* based on https://github.com/watson/ci-info/blob/HEAD/index.js
*/
public static function isCI(): bool
{
return (
// GitHub Actions, Travis CI, CircleCI, Cirrus CI, GitLab CI, AppVeyor, CodeShip, dsari
\getenv('CI') !== false ||
// Jenkins, TeamCity
\getenv('BUILD_NUMBER') !== false ||
// TaskCluster, dsari
\getenv('RUN_ID') !== false ||
// For testing
\getenv('GS_CI') === '1'
) && \getenv('GS_CI') !== '0';
}
}
1 change: 1 addition & 0 deletions tests/Unit/Command/ApplyCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
* @uses \GsTYPO3\CorePatches\Plugin
* @uses \GsTYPO3\CorePatches\Utility\ComposerUtils
* @uses \GsTYPO3\CorePatches\Utility\PatchUtils
* @uses \GsTYPO3\CorePatches\Utility\Utils
*/
final class ApplyCommandTest extends CommandTestCase
{
Expand Down
1 change: 1 addition & 0 deletions tests/Unit/Command/RemoveCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
* @uses \GsTYPO3\CorePatches\Gerrit\RestApi
* @uses \GsTYPO3\CorePatches\Utility\ComposerUtils
* @uses \GsTYPO3\CorePatches\Utility\PatchUtils
* @uses \GsTYPO3\CorePatches\Utility\Utils
*/
final class RemoveCommandTest extends CommandTestCase
{
Expand Down
1 change: 1 addition & 0 deletions tests/Unit/Command/UpdateCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
* @uses \GsTYPO3\CorePatches\Gerrit\RestApi
* @uses \GsTYPO3\CorePatches\Utility\ComposerUtils
* @uses \GsTYPO3\CorePatches\Utility\PatchUtils
* @uses \GsTYPO3\CorePatches\Utility\Utils
*/
final class UpdateCommandTest extends CommandTestCase
{
Expand Down
30 changes: 28 additions & 2 deletions tests/Unit/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ public function testLoadWorksProperly(
int $expectedAppliedChangesCount,
int $expectedPreferredInstallChangedCount,
string $expectedPatchDirectory,
bool $expectedIgnoreBranch
bool $expectedIgnoreBranch,
bool $expectedDisableTidyPatches,
bool $expectedForceTidyPatches
): void {
$jsonFileProphecy = $this->prophesize(JsonFile::class);
$jsonFileProphecy->read()->willReturn($configuration);
Expand All @@ -60,6 +62,8 @@ public function testLoadWorksProperly(
self::assertCount($expectedPreferredInstallChangedCount, $config->getPreferredInstallChanged());
self::assertSame($expectedPatchDirectory, $config->getPatchDirectory());
self::assertSame($expectedIgnoreBranch, $config->getIgnoreBranch());
self::assertSame($expectedDisableTidyPatches, $config->getDisableTidyPatches());
self::assertSame($expectedForceTidyPatches, $config->getForceTidyPatches());
}

/**
Expand All @@ -70,7 +74,9 @@ public function testLoadWorksProperly(
* expectedAppliedChangesCount: int,
* expectedPreferredInstallChangedCount: int,
* expectedPatchDirectory: string,
* expectedIgnoreBranch: bool
* expectedIgnoreBranch: bool,
* expectedDisableTidyPatches: bool,
* expectedForceTidyPatches: bool
* }>
*/
public function configurationLoadProvider(): Iterator
Expand Down Expand Up @@ -115,6 +121,8 @@ public function configurationLoadProvider(): Iterator
'preferred-install-changed' => ['package1', 'package2'],
'patch-directory' => 'patch-dir',
'ignore-branch' => true,
'disable-tidy-patches' => true,
'force-tidy-patches' => true,
],
],
],
Expand All @@ -124,6 +132,8 @@ public function configurationLoadProvider(): Iterator
'expectedPreferredInstallChangedCount' => 2,
'expectedPatchDirectory' => 'patch-dir',
'expectedIgnoreBranch' => true,
'expectedDisableTidyPatches' => true,
'expectedForceTidyPatches' => true,
];
yield 'empty configuration' => [
'configuration' => null,
Expand All @@ -133,6 +143,8 @@ public function configurationLoadProvider(): Iterator
'expectedPreferredInstallChangedCount' => 0,
'expectedPatchDirectory' => 'patches',
'expectedIgnoreBranch' => false,
'expectedDisableTidyPatches' => false,
'expectedForceTidyPatches' => false,
];
yield 'empty extra' => [
'configuration' => ['extra' => []],
Expand All @@ -142,6 +154,8 @@ public function configurationLoadProvider(): Iterator
'expectedPreferredInstallChangedCount' => 0,
'expectedPatchDirectory' => 'patches',
'expectedIgnoreBranch' => false,
'expectedDisableTidyPatches' => false,
'expectedForceTidyPatches' => false,
];
}

Expand Down Expand Up @@ -402,6 +416,8 @@ public function configurationSaveProvider(): Iterator
],
'patch-directory' => 'patch-dir',
'ignore-branch' => true,
'disable-tidy-patches' => true,
'force-tidy-patches' => true,
],
],
],
Expand Down Expand Up @@ -447,6 +463,8 @@ public function configurationSaveProvider(): Iterator
],
'patch-directory' => 'patch-dir',
'ignore-branch' => true,
'disable-tidy-patches' => true,
'force-tidy-patches' => true,
],
],
],
Expand Down Expand Up @@ -497,5 +515,13 @@ public function testGettersAndSetters(): void
self::assertTrue($config->getIgnoreBranch());

self::assertSame($config->getPatches(), $config->getPatches());

self::assertFalse($config->getDisableTidyPatches());
self::assertSame($config, $config->setDisableTidyPatches(true));
self::assertTrue($config->getDisableTidyPatches());

self::assertFalse($config->getForceTidyPatches());
self::assertSame($config, $config->setForceTidyPatches(true));
self::assertTrue($config->getForceTidyPatches());
}
}
1 change: 1 addition & 0 deletions tests/Unit/Utility/ComposerUtilsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
* @uses \GsTYPO3\CorePatches\Gerrit\Entity\IncludedInInfo
* @uses \GsTYPO3\CorePatches\Gerrit\RestApi
* @uses \GsTYPO3\CorePatches\Utility\PatchUtils
* @uses \GsTYPO3\CorePatches\Utility\Utils
*/
final class ComposerUtilsTest extends TestCase
{
Expand Down
Loading

0 comments on commit 41a5aa2

Please sign in to comment.