Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/wiki
Submodule wiki updated from 3db92d to b86337
3 changes: 3 additions & 0 deletions .github/workflows/reports.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ jobs:
- name: Add .nojekyll
run: touch "${REPORTS_TARGET}/.nojekyll"

- name: Remove repository-local caches from published output
run: rm -rf "${REPORTS_TARGET}/cache"

- name: Restore previews from gh-pages
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
uses: actions/checkout@v6
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- Consolidate repository-local DevTools caches under `.dev-tools/cache`, keep published reports free of cache directories, and audit managed artifact path defaults across commands, workflows, and documentation (#151)

## [1.17.1] - 2026-04-22

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion docs/commands/docs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Options

``--cache-dir`` (optional)
Path to the cache directory for phpDocumentor.
Default: ``tmp/cache/phpdoc``.
Default: ``.dev-tools/cache/phpdoc``.

``--progress``
Enable progress output from phpDocumentor.
Expand Down
2 changes: 1 addition & 1 deletion docs/commands/phpdoc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Options
Automatically fix PHPDoc issues. Without this option, runs in dry-run mode.

``--cache-dir`` (optional)
Path to the cache directory for PHP-CS-Fixer. Default: ``tmp/cache/php-cs-fixer``.
Path to the cache directory for PHP-CS-Fixer. Default: ``.dev-tools/cache/php-cs-fixer``.

``--progress``
Enable progress output from PHP-CS-Fixer and the Rector phase.
Expand Down
2 changes: 1 addition & 1 deletion docs/commands/tests.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Options
Path to the bootstrap file. Default: ``./vendor/autoload.php``.

``--cache-dir`` (optional)
Path to the PHPUnit cache directory. Default: ``./tmp/cache/phpunit``.
Path to the PHPUnit cache directory. Default: ``.dev-tools/cache/phpunit``.

``--no-cache``
Disable PHPUnit caching.
Expand Down
2 changes: 1 addition & 1 deletion docs/commands/wiki.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Options

``--cache-dir`` (optional)
Path to the cache directory for phpDocumentor.
Default: ``tmp/cache/phpdoc``.
Default: ``.dev-tools/cache/phpdoc``.

``--init``
Initialize the configured wiki target as a Git submodule.
Expand Down
6 changes: 4 additions & 2 deletions docs/configuration/tooling-defaults.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ Generated and Cache Directories
directories kept in place by the ``skills`` command.
- ``.agents/agents/`` contains symlinked packaged project agents or
consumer-owned directories kept in place by the ``agents`` command.
- ``tmp/cache/phpdoc``, ``tmp/cache/phpunit``, ``tmp/cache/rector``, and
``tmp/cache/.php-cs-fixer.cache`` store tool caches.
- ``.dev-tools/cache/phpdoc``, ``.dev-tools/cache/phpunit``,
``.dev-tools/cache/rector``, and
``.dev-tools/cache/php-cs-fixer/.php-cs-fixer.cache`` store repository-local
tool caches.

Local Versus Packaged Files
---------------------------
Expand Down
2 changes: 1 addition & 1 deletion docs/running/specialized-commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Important details:
- ``--progress`` re-enables PHPUnit progress output in text mode;
- ``--json`` and ``--pretty-json`` still suppress PHPUnit progress output
automatically;
- ``--no-cache`` disables ``tmp/cache/phpunit``;
- ``--no-cache`` disables ``.dev-tools/cache/phpunit``;
- the packaged configuration registers the DevTools PHPUnit extension.

``dependencies``
Expand Down
1 change: 1 addition & 0 deletions docs/usage/github-actions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ The ``reports.yml`` workflow is responsible for generating technical documentati
* **Main Branch**: Runs all checks and deploys the final reports to the root of the ``gh-pages`` branch.
* Runs a post-deploy health check against the published reports index and coverage URLs with retry/backoff to account for Pages propagation.
* Resolves the workflow PHP version from ``composer.lock`` or ``composer.json`` before installing dependencies.
* Removes ``.dev-tools/cache`` from the publish directory before deployment so repository-local tool caches never leak into GitHub Pages output.
* **Pull Requests**:
* Generates a **Preview** of the documentation, coverage, and metrics.
* Deploys the preview to ``gh-pages`` under ``previews/pr-{number}/``.
Expand Down
2 changes: 1 addition & 1 deletion docs/usage/testing-and-coverage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ When you run ``tests``, DevTools:
- resolves ``phpunit.xml`` from the consumer root first and falls back to the
packaged default;
- uses ``vendor/autoload.php`` as the default bootstrap file;
- stores cache data in ``tmp/cache/phpunit`` unless ``--no-cache`` is used;
- stores cache data in ``.dev-tools/cache/phpunit`` unless ``--no-cache`` is used;
- can generate HTML coverage, Testdox, Clover, and raw PHP coverage output
when ``--coverage`` is provided.

Expand Down
4 changes: 2 additions & 2 deletions resources/phpdocumentor.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
{% endfor %}
</source>
<ignore hidden="true" symlinks="true">
<path>tests/**/*</path>
<path>.dev-tools/**/*</path>
<path>resources/**/*</path>
<path>tmp/**/*</path>
<path>tests/**/*</path>
<path>vendor/**/*</path>
</ignore>
<extensions>
Expand Down
17 changes: 11 additions & 6 deletions src/Config/ComposerDependencyAnalyserConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ final class ComposerDependencyAnalyserConfig
*
* @var array<int, string>
*/
private const array PACKAGED_UNUSED_DEPENDENCIES = [
public const array DEFAULT_PACKAGED_UNUSED_DEPENDENCIES = [
'ergebnis/composer-normalize',
'fakerphp/faker',
'fast-forward/phpdoc-bootstrap-template',
Expand All @@ -75,7 +75,7 @@ final class ComposerDependencyAnalyserConfig
*
* @var array<int, string>
*/
private const array PACKAGED_PROD_ONLY_IN_DEV_DEPENDENCIES = [
public const array DEFAULT_PACKAGED_PROD_ONLY_IN_DEV_DEPENDENCIES = [
'phpspec/prophecy',
'phpspec/prophecy-phpunit',
'symfony/var-exporter',
Expand All @@ -93,7 +93,7 @@ public static function configure(?callable $customize = null): Configuration
$configuration = new Configuration();

if (self::isDevToolsRepository(__DIR__)) {
self::configurePackagedRepositoryIgnores($configuration);
self::applyPackagedRepositoryIgnores($configuration);
}

if (null !== $customize) {
Expand All @@ -110,14 +110,19 @@ public static function configure(?callable $customize = null): Configuration
*
* @return void
*/
private static function configurePackagedRepositoryIgnores(Configuration $configuration): void
public static function applyPackagedRepositoryIgnores(Configuration $configuration): Configuration
{
$configuration->ignoreErrorsOnExtension('ext-pcntl', [ErrorType::SHADOW_DEPENDENCY]);
$configuration->ignoreErrorsOnPackages(self::PACKAGED_UNUSED_DEPENDENCIES, [ErrorType::UNUSED_DEPENDENCY]);
$configuration->ignoreErrorsOnPackages(
self::PACKAGED_PROD_ONLY_IN_DEV_DEPENDENCIES,
self::DEFAULT_PACKAGED_UNUSED_DEPENDENCIES,
[ErrorType::UNUSED_DEPENDENCY]
);
$configuration->ignoreErrorsOnPackages(
self::DEFAULT_PACKAGED_PROD_ONLY_IN_DEV_DEPENDENCIES,
[ErrorType::PROD_DEPENDENCY_ONLY_IN_DEV],
);

return $configuration;
}

/**
Expand Down
132 changes: 106 additions & 26 deletions src/Config/ECSConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

namespace FastForward\DevTools\Config;

use FastForward\DevTools\Path\WorkingProjectPathResolver;
use PhpCsFixer\Fixer\Import\GlobalNamespaceImportFixer;
use PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocAnnotationRemoveFixer;
use PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer;
Expand Down Expand Up @@ -46,41 +47,120 @@
*/
final class ECSConfig
{
/**
* @var array{symfony: bool, symfonyRisky: bool, auto: bool, autoRisky: bool} the PHP-CS-Fixer sets applied by default
*/
public const array DEFAULT_PHP_CS_FIXER_SETS = [
'symfony' => true,
'symfonyRisky' => true,
'auto' => true,
'autoRisky' => true,
];

/**
* @var array{psr12: bool, common: bool, symplify: bool, strict: bool, cleanCode: bool} the prepared ECS sets applied by default
*/
public const array DEFAULT_PREPARED_SETS = [
'psr12' => true,
'common' => true,
'symplify' => true,
'strict' => true,
'cleanCode' => true,
];

/**
* @var list<class-string> the ECS/CS Fixer rules that SHOULD be skipped by default
*/
public const array DEFAULT_SKIPPED_RULES = [
PhpdocToCommentFixer::class,
NoSuperfluousPhpdocTagsFixer::class,
NoEmptyPhpdocFixer::class,
PhpdocNoEmptyReturnFixer::class,
GlobalNamespaceImportFixer::class,
GeneralPhpdocAnnotationRemoveFixer::class,
];

/**
* @var array<class-string, array<string, mixed>> the configured ECS rules applied by default
*/
public const array DEFAULT_CONFIGURED_RULES = [
PhpdocAlignFixer::class => [
'align' => 'left',
],
PhpUnitTestCaseStaticMethodCallsFixer::class => [
'call_type' => 'self',
],
PhpdocAddMissingParamAnnotationFixer::class => [
'only_untyped' => false,
],
];

/**
* Creates the default ECS configuration.
*
* @param callable|null $customize optional callback to customize the configuration builder
*
* @return ECSConfigBuilder the configured ECS configuration builder
*/
public static function configure(): ECSConfigBuilder
public static function configure(?callable $customize = null): ECSConfigBuilder
{
$cwd = getcwd();
$workingDirectory = getcwd();
$config = new ECSConfigBuilder();

self::applyDefaultPathsAndSkips($config, $workingDirectory);
self::applyDefaultRulesAndSets($config);

if (null !== $customize) {
$customize($config);
}

return $config;
}

/**
* Applies the default repository paths and skipped rules to an ECS builder.
*
* @param ECSConfigBuilder $config
* @param string $workingDirectory
*/
public static function applyDefaultPathsAndSkips(
ECSConfigBuilder $config,
string $workingDirectory
): ECSConfigBuilder {
$skipPaths = WorkingProjectPathResolver::getToolingExcludedDirectories($workingDirectory);

return $config
->withPaths([$cwd])
->withSkip([
$cwd . '/.dev-tools',
$cwd . '/resources',
$cwd . '/vendor',
$cwd . '/tmp',
PhpdocToCommentFixer::class,
NoSuperfluousPhpdocTagsFixer::class,
NoEmptyPhpdocFixer::class,
PhpdocNoEmptyReturnFixer::class,
GlobalNamespaceImportFixer::class,
GeneralPhpdocAnnotationRemoveFixer::class,
])
->withPaths([$workingDirectory])
->withSkip([...$skipPaths, ...self::DEFAULT_SKIPPED_RULES]);
}

/**
* Applies the default ECS sets, root files, and configured rules to an ECS builder.
*
* @param ECSConfigBuilder $config
*/
public static function applyDefaultRulesAndSets(ECSConfigBuilder $config): ECSConfigBuilder
{
$config
->withRootFiles()
->withPhpCsFixerSets(symfony: true, symfonyRisky: true, auto: true, autoRisky: true)
->withPreparedSets(psr12: true, common: true, symplify: true, strict: true, cleanCode: true)
->withConfiguredRule(PhpdocAlignFixer::class, [
'align' => 'left',
])
->withConfiguredRule(PhpUnitTestCaseStaticMethodCallsFixer::class, [
'call_type' => 'self',
])
->withConfiguredRule(PhpdocAddMissingParamAnnotationFixer::class, [
'only_untyped' => false,
]);
->withPhpCsFixerSets(
symfony: self::DEFAULT_PHP_CS_FIXER_SETS['symfony'],
symfonyRisky: self::DEFAULT_PHP_CS_FIXER_SETS['symfonyRisky'],
auto: self::DEFAULT_PHP_CS_FIXER_SETS['auto'],
autoRisky: self::DEFAULT_PHP_CS_FIXER_SETS['autoRisky'],
)
->withPreparedSets(
psr12: self::DEFAULT_PREPARED_SETS['psr12'],
common: self::DEFAULT_PREPARED_SETS['common'],
symplify: self::DEFAULT_PREPARED_SETS['symplify'],
strict: self::DEFAULT_PREPARED_SETS['strict'],
cleanCode: self::DEFAULT_PREPARED_SETS['cleanCode'],
);

foreach (self::DEFAULT_CONFIGURED_RULES as $rule => $configuration) {
$config->withConfiguredRule($rule, $configuration);
}

return $config;
}
}
Loading
Loading