Skip to content

Commit b1cf195

Browse files
committed
[dependencies] Support report-only outdated threshold (#135)
1 parent c214a57 commit b1cf195

6 files changed

Lines changed: 97 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Changed
1111

12-
- Consolidate dependency analysis on `composer-dependency-analyser`, add a reusable packaged analyzer config, remove the redundant `composer-unused` dependency, and expose `--dump-usage` passthrough support (#135)
12+
- Consolidate dependency analysis on `composer-dependency-analyser`, add a reusable packaged analyzer config, remove the redundant `composer-unused` dependency, and expose `--dump-usage` plus report-only `--max-outdated=-1` support (#135)
1313

1414
## [1.14.0] - 2026-04-20
1515

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ composer dev-tools tests
6363
# Analyze missing, unused, misplaced, and outdated Composer dependencies
6464
composer dependencies
6565
composer dependencies --max-outdated=8
66+
composer dependencies --max-outdated=-1
6667
composer dependencies --dev
6768
composer dependencies --dump-usage=symfony/console
6869
composer dependencies --upgrade --dev

docs/commands/dependencies.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ Options
3434

3535
Default: ``5``.
3636

37+
Use ``-1`` to keep the outdated dependency report in the output while
38+
ignoring Jack failures in the final command status.
39+
3740
``--upgrade`` (optional)
3841
Applies the Jack upgrade workflow before the analyzers:
3942

@@ -67,6 +70,12 @@ Allow up to 10 outdated packages:
6770
6871
composer dependencies --max-outdated=10
6972
73+
Report outdated packages without failing on their count:
74+
75+
.. code-block:: bash
76+
77+
composer dependencies --max-outdated=-1
78+
7079
Preview the upgrade workflow:
7180

7281
.. code-block:: bash
@@ -120,6 +129,9 @@ Behavior
120129
- ``--dump-usages <package>`` and ``--show-all-usages`` when ``--dump-usage``
121130
is passed to the DevTools command
122131
- ``jack breakpoint`` maps ``--max-outdated`` to Jack's ``--limit`` option.
132+
- ``--max-outdated=-1`` keeps ``jack breakpoint`` in the workflow for reporting,
133+
but its failure is ignored so only missing or unused dependency findings fail
134+
the command.
123135
- ``--upgrade`` applies Jack's ``raise-to-installed`` and ``open-versions``
124136
commands before ``composer update -W`` and ``composer normalize``.
125137
- Returns a non-zero exit code when missing, unused, misplaced, or too many

docs/running/specialized-commands.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Analyzes missing, unused, misplaced, and outdated Composer dependencies.
5656
5757
composer dependencies
5858
composer dependencies --max-outdated=10
59+
composer dependencies --max-outdated=-1
5960
composer dependencies --dev
6061
composer dependencies --dump-usage=symfony/console
6162
composer dependencies --upgrade --dev
@@ -71,6 +72,8 @@ Important details:
7172
``composer-dependency-analyser --dump-usages <package> --show-all-usages``;
7273
- it uses ``jack breakpoint --limit=<max-outdated>`` to fail when too many
7374
outdated dependencies accumulate;
75+
- ``--max-outdated=-1`` keeps the Jack outdated report in the output but
76+
ignores Jack's failure so only dependency-analyser findings fail the command;
7477
- it previews ``jack raise-to-installed`` and ``jack open-versions`` before
7578
the analyzers;
7679
- ``--upgrade`` runs ``jack raise-to-installed``, ``jack open-versions``,

src/Console/Command/DependenciesCommand.php

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ final class DependenciesCommand extends BaseCommand
4747
{
4848
private const string ANALYSER_CONFIG = 'composer-dependency-analyser.php';
4949

50+
private const int DISABLE_OUTDATED_THRESHOLD = -1;
51+
5052
/**
5153
* @param ProcessBuilderInterface $processBuilder creates analyzer and upgrade processes
5254
* @param ProcessQueueInterface $processQueue executes queued processes
@@ -69,7 +71,7 @@ protected function configure(): void
6971
->addOption(
7072
name: 'max-outdated',
7173
mode: InputOption::VALUE_REQUIRED,
72-
description: 'Maximum number of outdated packages allowed by jack breakpoint.',
74+
description: 'Maximum number of outdated packages allowed by jack breakpoint. Use -1 to keep the report but ignore Jack failures.',
7375
default: '5',
7476
)
7577
->addOption(
@@ -118,7 +120,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
118120
$output->writeln('<info>Running dependency analysis...</info>');
119121

120122
$this->processQueue->add($this->getComposerDependencyAnalyserCommand($input));
121-
$this->processQueue->add($this->getJackBreakpointCommand($input, $maximumOutdated));
123+
$this->processQueue->add(
124+
$this->getJackBreakpointCommand($input, $maximumOutdated),
125+
$this->shouldIgnoreOutdatedFailures($maximumOutdated),
126+
);
122127

123128
return $this->processQueue->run($output);
124129
}
@@ -162,7 +167,9 @@ private function getJackBreakpointCommand(InputInterface $input, int $maximumOut
162167
$command .= ' --dev';
163168
}
164169

165-
$command .= ' --limit ' . $maximumOutdated;
170+
if (! $this->shouldIgnoreOutdatedFailures($maximumOutdated)) {
171+
$command .= ' --limit ' . $maximumOutdated;
172+
}
166173

167174
return $this->processBuilder->build($command);
168175
}
@@ -252,10 +259,22 @@ private function resolveMaximumOutdated(InputInterface $input): int
252259

253260
$maximumOutdated = (int) $maximumOutdated;
254261

255-
if (0 > $maximumOutdated) {
256-
throw new InvalidArgumentException('The --max-outdated option MUST be zero or greater.');
262+
if (self::DISABLE_OUTDATED_THRESHOLD > $maximumOutdated) {
263+
throw new InvalidArgumentException('The --max-outdated option MUST be -1 or greater.');
257264
}
258265

259266
return $maximumOutdated;
260267
}
268+
269+
/**
270+
* Determines whether Jack outdated failures SHOULD be ignored for the given threshold.
271+
*
272+
* @param int $maximumOutdated the validated outdated threshold option
273+
*
274+
* @return bool true when the outdated threshold is explicitly disabled
275+
*/
276+
private function shouldIgnoreOutdatedFailures(int $maximumOutdated): bool
277+
{
278+
return self::DISABLE_OUTDATED_THRESHOLD === $maximumOutdated;
279+
}
261280
}

tests/Console/Command/DependenciesCommandTest.php

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ public function executeWillReturnSuccessWhenPreviewAndAnalyzersSucceed(): void
121121
->shouldBeCalledOnce();
122122
$this->processQueue->add($this->processDepAnalyser->reveal())
123123
->shouldBeCalledOnce();
124-
$this->processQueue->add($this->processBreakpoint->reveal())
124+
$this->processQueue->add($this->processBreakpoint->reveal(), false)
125125
->shouldBeCalledOnce();
126126
$this->processQueue->run($this->output->reveal())
127127
->willReturn(ProcessQueueInterface::SUCCESS)
@@ -148,7 +148,7 @@ public function executeWillReturnFailureWhenProcessQueueFails(): void
148148
->shouldBeCalledOnce();
149149
$this->processQueue->add($this->processDepAnalyser->reveal())
150150
->shouldBeCalledOnce();
151-
$this->processQueue->add($this->processBreakpoint->reveal())
151+
$this->processQueue->add($this->processBreakpoint->reveal(), false)
152152
->shouldBeCalledOnce();
153153
$this->processQueue->run($this->output->reveal())
154154
->willReturn(ProcessQueueInterface::FAILURE)
@@ -179,7 +179,7 @@ public function executeWillQueueUpgradeWorkflowBeforeAnalysisWhenUpgradeIsReques
179179
->shouldBeCalledOnce();
180180
$this->processQueue->add($this->processDepAnalyser->reveal())
181181
->shouldBeCalledOnce();
182-
$this->processQueue->add($this->processBreakpoint->reveal())
182+
$this->processQueue->add($this->processBreakpoint->reveal(), false)
183183
->shouldBeCalledOnce();
184184
$this->processQueue->run($this->output->reveal())
185185
->willReturn(ProcessQueueInterface::SUCCESS)
@@ -206,6 +206,21 @@ public function executeWillFailWhenMaxOutdatedIsNotNumeric(): void
206206
self::assertSame(DependenciesCommand::FAILURE, $this->executeCommand());
207207
}
208208

209+
/**
210+
* @return void
211+
*/
212+
#[Test]
213+
public function executeWillFailWhenMaxOutdatedIsLowerThanMinusOne(): void
214+
{
215+
$this->input->getOption('max-outdated')
216+
->willReturn('-2');
217+
$this->output->writeln('<error>The --max-outdated option MUST be -1 or greater.</error>')
218+
->shouldBeCalledOnce();
219+
$this->processQueue->run(Argument::cetera())->shouldNotBeCalled();
220+
221+
self::assertSame(DependenciesCommand::FAILURE, $this->executeCommand());
222+
}
223+
209224
/**
210225
* @return void
211226
*/
@@ -221,7 +236,34 @@ public function executeWillDumpPackageUsagesAndShowAllMatchesWhenRequested(): vo
221236
->shouldBeCalledOnce();
222237
$this->processQueue->add($this->processDepAnalyser->reveal())
223238
->shouldBeCalledOnce();
224-
$this->processQueue->add($this->processBreakpoint->reveal())
239+
$this->processQueue->add($this->processBreakpoint->reveal(), false)
240+
->shouldBeCalledOnce();
241+
$this->processQueue->run($this->output->reveal())
242+
->willReturn(ProcessQueueInterface::SUCCESS)
243+
->shouldBeCalledOnce();
244+
245+
$this->output->writeln('<info>Running dependency analysis...</info>')
246+
->shouldBeCalledOnce();
247+
248+
self::assertSame(DependenciesCommand::SUCCESS, $this->executeCommand());
249+
}
250+
251+
/**
252+
* @return void
253+
*/
254+
#[Test]
255+
public function executeWillIgnoreJackFailuresWhenMaxOutdatedIsDisabled(): void
256+
{
257+
$this->configureBaseExecution(maxOutdated: '-1', upgrade: false, dev: false, dumpUsage: null);
258+
$this->configurePreviewBuilders(dev: false, maxOutdated: '-1', dumpUsage: null);
259+
260+
$this->processQueue->add($this->processRaiseToInstalled->reveal())
261+
->shouldBeCalledOnce();
262+
$this->processQueue->add($this->processOpenVersions->reveal())
263+
->shouldBeCalledOnce();
264+
$this->processQueue->add($this->processDepAnalyser->reveal())
265+
->shouldBeCalledOnce();
266+
$this->processQueue->add($this->processBreakpoint->reveal(), true)
225267
->shouldBeCalledOnce();
226268
$this->processQueue->run($this->output->reveal())
227269
->willReturn(ProcessQueueInterface::SUCCESS)
@@ -291,7 +333,11 @@ private function configurePreviewBuilders(bool $dev, string $maxOutdated, ?strin
291333
->willReturn($this->processDepAnalyser->reveal());
292334
$this->processBuilder
293335
->build(
294-
$dev ? 'vendor/bin/jack breakpoint --dev --limit ' . $maxOutdated : 'vendor/bin/jack breakpoint --limit ' . $maxOutdated
336+
'-1' === $maxOutdated
337+
? ($dev ? 'vendor/bin/jack breakpoint --dev' : 'vendor/bin/jack breakpoint')
338+
: ($dev
339+
? 'vendor/bin/jack breakpoint --dev --limit ' . $maxOutdated
340+
: 'vendor/bin/jack breakpoint --limit ' . $maxOutdated)
295341
)
296342
->willReturn($this->processBreakpoint->reveal());
297343
}
@@ -345,7 +391,11 @@ private function configureUpgradeBuilders(bool $dev, string $maxOutdated, ?strin
345391
->willReturn($this->processDepAnalyser->reveal());
346392
$this->processBuilder
347393
->build(
348-
$dev ? 'vendor/bin/jack breakpoint --dev --limit ' . $maxOutdated : 'vendor/bin/jack breakpoint --limit ' . $maxOutdated
394+
'-1' === $maxOutdated
395+
? ($dev ? 'vendor/bin/jack breakpoint --dev' : 'vendor/bin/jack breakpoint')
396+
: ($dev
397+
? 'vendor/bin/jack breakpoint --dev --limit ' . $maxOutdated
398+
: 'vendor/bin/jack breakpoint --limit ' . $maxOutdated)
349399
)
350400
->willReturn($this->processBreakpoint->reveal());
351401
}

0 commit comments

Comments
 (0)