Skip to content

Commit a1b837f

Browse files
[dependencies] Add shadow dependency audit option (#234)
* [dependencies] Add shadow dependency audit option * Update wiki submodule pointer for PR #234 * [ci] Dispatch tests after wiki pointer commits --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
1 parent cdf59bc commit a1b837f

13 files changed

Lines changed: 238 additions & 8 deletions

File tree

.github/wiki

Submodule wiki updated from 13a8152 to 005922a

.github/workflows/wiki-preview.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ jobs:
3737
name: Update Wiki Preview
3838
runs-on: ubuntu-latest
3939
permissions:
40+
actions: write
4041
contents: write
4142
pull-requests: read
4243

@@ -110,6 +111,13 @@ jobs:
110111
pull: "--rebase --autostash"
111112
push: true
112113

114+
- name: Dispatch tests for wiki pointer commit
115+
if: steps.submodule_status.outputs.changed == 'true'
116+
env:
117+
GH_TOKEN: ${{ github.token }}
118+
HEAD_REF: ${{ github.event.pull_request.head.ref }}
119+
run: gh workflow run tests.yml --ref "${HEAD_REF}" -f max-outdated=-1
120+
113121
- uses: ./.dev-tools-actions/.github/actions/summary/write
114122
with:
115123
markdown: |
@@ -118,3 +126,4 @@ jobs:
118126
- Preview branch: `${{ env.WIKI_PREVIEW_BRANCH }}`
119127
- Submodule pointer changed: `${{ steps.submodule_status.outputs.changed }}`
120128
- Parent repository pointer commit result: `${{ steps.submodule_status.outputs.changed == 'true' && 'updated' || 'unchanged' }}`
129+
- Tests dispatch result: `${{ steps.submodule_status.outputs.changed == 'true' && 'requested' || 'not needed' }}`

.github/workflows/wiki.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ concurrency:
1111
jobs:
1212
preview:
1313
permissions:
14+
actions: write
1415
contents: write
1516
pull-requests: read
1617
uses: ./.github/workflows/wiki-preview.yml

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Fixed
1111

1212
- Keep required PHPUnit matrix checks reporting after workflow-managed `.github/wiki` pointer commits by running the pull-request test workflow without top-level path filters and aligning the packaged consumer test wrapper (#230)
13+
- Ignore intentional Composer Dependency Analyser shadow dependency findings by default while adding `dependencies --show-shadow-dependencies` for audits (#233)
14+
- Dispatch the required test workflow after wiki preview automation updates a pull-request `.github/wiki` pointer, avoiding permanently pending required checks on bot-authored pointer commits (#230)
1315

1416
## [1.21.0] - 2026-04-24
1517

docs/advanced/branch-protection-and-bot-commits.rst

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,15 @@ updates on PR branches while keeping ``main`` protected.
9999
Required test checks must still report for workflow-managed pointer commits.
100100
The tests workflow therefore triggers on every pull request update without
101101
top-level path filters. This ensures GitHub always creates the required
102-
``Run Tests`` matrix checks for the latest pull request head, including bot
103-
commits that only refresh ``.github/wiki``. Test workflow concurrency cancels
104-
older in-progress runs for the same pull request so the newest commit owns the
102+
``Run Tests`` matrix checks for ordinary pull request updates.
103+
104+
Workflow-managed ``.github/wiki`` pointer commits need one extra step. GitHub
105+
does not start another ``pull_request`` or ``push`` workflow run for commits
106+
pushed with the built-in workflow token. After the wiki preview workflow commits
107+
a parent-repository pointer update, it explicitly dispatches ``tests.yml`` for
108+
the pull request head branch so the newest bot-authored commit receives the
109+
required ``Run Tests`` matrix checks. Test workflow concurrency cancels older
110+
in-progress runs for the same pull request so the newest commit owns the
105111
required check contexts.
106112

107113
At a high level, the workflows need permission to read repository contents,
@@ -128,8 +134,9 @@ distinguish open pull requests from closed or merged ones before deleting
128134

129135
``wiki.yml`` is now preview-only, so its called workflow keeps
130136
``contents: write`` for wiki preview commits and parent-repository submodule
131-
pointer updates, while retaining ``pull-requests: read`` to inspect pull
132-
request metadata safely.
137+
pointer updates, ``actions: write`` to dispatch ``tests.yml`` after bot-authored
138+
pointer commits, and ``pull-requests: read`` to inspect pull request metadata
139+
safely.
133140

134141
``wiki-maintenance-entry.yml`` and ``wiki-maintenance.yml`` keep
135142
``contents: write`` for wiki publication and cleanup tasks, and

docs/commands/dependencies.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,16 @@ Options
5555
Asks ``composer-dependency-analyser`` to dump usages for the given package
5656
or wildcard pattern and enables ``--show-all-usages`` automatically.
5757

58+
``--show-shadow-dependencies`` (optional)
59+
Reports shadow dependencies instead of applying the Fast Forward default
60+
ignore for intentional dependency groups.
61+
62+
By default, DevTools hides ``SHADOW_DEPENDENCY`` findings because Fast
63+
Forward packages may intentionally require ecosystem bundles, meta packages,
64+
or convenience packages that install related dependencies for consumers.
65+
Use this flag when auditing whether a package has accidental shadow
66+
dependencies that should be removed or documented more precisely.
67+
5868
``--json``
5969
Emit a structured machine-readable payload instead of the normal terminal
6070
output.
@@ -95,6 +105,12 @@ Dump all matched usages for one package:
95105
96106
composer dependencies --dump-usage=symfony/console
97107
108+
Audit shadow dependencies:
109+
110+
.. code-block:: bash
111+
112+
composer dependencies --show-shadow-dependencies
113+
98114
Apply the upgrade workflow and then analyze dependencies:
99115

100116
.. code-block:: bash
@@ -135,6 +151,8 @@ Behavior
135151
consumer repositories can extend the baseline instead of copying it whole
136152
- ``--dump-usages <package>`` and ``--show-all-usages`` when ``--dump-usage``
137153
is passed to the DevTools command
154+
- the ``FAST_FORWARD_DEV_TOOLS_SHOW_SHADOW_DEPENDENCIES`` process environment
155+
flag, which is enabled when ``--show-shadow-dependencies`` is passed
138156
- ``jack breakpoint`` maps ``--max-outdated`` to Jack's ``--limit`` option.
139157
- ``--max-outdated=-1`` keeps ``jack breakpoint`` in the workflow for reporting,
140158
but its failure is ignored so only missing or unused dependency findings fail

docs/configuration/overriding-defaults.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,13 @@ consumers can extend the default configuration using the
141141
This approach keeps the Fast Forward baseline while letting consumer
142142
repositories add project-specific ignores or scan rules.
143143

144+
The baseline ignores ``SHADOW_DEPENDENCY`` findings by default because Fast
145+
Forward packages may intentionally require dependency groups, ecosystem bundles,
146+
or meta packages that install related dependencies for consumers. Run
147+
``composer dependencies --show-shadow-dependencies`` when you want to audit
148+
those findings and decide whether a package should keep, document, or remove a
149+
direct dependency.
150+
144151
What Is Not Overwritten Automatically
145152
--------------------------------------
146153

docs/running/specialized-commands.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ Analyzes missing, unused, misplaced, and outdated Composer dependencies.
7777
composer dependencies --max-outdated=-1
7878
composer dependencies --dev
7979
composer dependencies --dump-usage=symfony/console
80+
composer dependencies --show-shadow-dependencies
8081
composer dependencies --upgrade --dev
8182
8283
Important details:
@@ -88,6 +89,10 @@ Important details:
8889
override locally;
8990
- ``--dump-usage=<package>`` forwards to
9091
``composer-dependency-analyser --dump-usages <package> --show-all-usages``;
92+
- ``--show-shadow-dependencies`` keeps shadow dependency findings visible for
93+
audits; without it, DevTools hides intentional Fast Forward dependency-group
94+
shadows so CI does not fail on ecosystem or meta packages that deliberately
95+
install related dependencies for consumers;
9196
- it uses ``jack breakpoint --limit=<max-outdated>`` to fail when too many
9297
outdated dependencies accumulate;
9398
- ``--max-outdated=-1`` keeps the Jack outdated report in the output but

resources/github-actions/wiki.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
types: [opened, synchronize, reopened]
66

77
permissions:
8+
actions: write
89
contents: write
910
pull-requests: read
1011

@@ -15,6 +16,7 @@ concurrency:
1516
jobs:
1617
preview:
1718
permissions:
19+
actions: write
1820
contents: write
1921
pull-requests: read
2022
# Pull-request wiki previews live here. Publication and preview cleanup are

src/Config/ComposerDependencyAnalyserConfig.php

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
*/
4242
final class ComposerDependencyAnalyserConfig
4343
{
44+
public const string ENV_SHOW_SHADOW_DEPENDENCIES = 'FAST_FORWARD_DEV_TOOLS_SHOW_SHADOW_DEPENDENCIES';
45+
4446
/**
4547
* Dependencies that are only required by the packaged DevTools distribution itself.
4648
*
@@ -90,6 +92,10 @@ public static function configure(?callable $customize = null): Configuration
9092
{
9193
$configuration = new Configuration();
9294

95+
if (! self::shouldShowShadowDependencies()) {
96+
self::applyIgnoresShadowDependencies($configuration);
97+
}
98+
9399
if (DevToolsPathResolver::isRepositoryCheckout()) {
94100
self::applyPackagedRepositoryIgnores($configuration);
95101
}
@@ -101,12 +107,39 @@ public static function configure(?callable $customize = null): Configuration
101107
return $configuration;
102108
}
103109

110+
/**
111+
* The default configuration ignores shadow dependencies because Fast
112+
* Forward packages MAY intentionally require dependency groups. For example,
113+
* ecosystem or meta packages can require related PSR or framework packages
114+
* so consumers do not need to install every package one by one.
115+
*
116+
* @param Configuration $configuration the analyser configuration to customize
117+
*
118+
* @return Configuration the modified configuration with shadow dependencies ignored
119+
*/
120+
public static function applyIgnoresShadowDependencies(Configuration $configuration): Configuration
121+
{
122+
$configuration->ignoreErrors([ErrorType::SHADOW_DEPENDENCY]);
123+
124+
return $configuration;
125+
}
126+
127+
/**
128+
* Determines whether shadow dependency reports SHOULD remain visible.
129+
*
130+
* @return bool
131+
*/
132+
public static function shouldShowShadowDependencies(): bool
133+
{
134+
return '1' === getenv(self::ENV_SHOW_SHADOW_DEPENDENCIES);
135+
}
136+
104137
/**
105138
* Applies the ignores required only by the packaged DevTools repository.
106139
*
107140
* @param Configuration $configuration the analyser configuration to customize
108141
*
109-
* @return void
142+
* @return Configuration the modified configuration with packaged repository ignores applied
110143
*/
111144
public static function applyPackagedRepositoryIgnores(Configuration $configuration): Configuration
112145
{

0 commit comments

Comments
 (0)