Skip to content
Merged
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 20540e to f1a8bc
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Add a configurable DevTools generated artifact workspace through `--workspace-dir` and `FAST_FORWARD_WORKSPACE_DIR`, keeping explicit output/cache command options authoritative (#274)
- Add a standalone DevTools `self-update` command plus global `--working-dir` and `--auto-update` binary options for local or global installations (#272)

## [1.23.0] - 2026-04-26
Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ composer dev-tools:fix
# Run the standalone binary from another project directory
vendor/bin/dev-tools --working-dir=/path/to/project tests

# Store generated reports and caches outside the default .dev-tools workspace
vendor/bin/dev-tools --workspace-dir=.artifacts reports

# Update the installed DevTools package
vendor/bin/dev-tools self-update
```
Expand Down Expand Up @@ -124,6 +127,7 @@ composer wiki
# Generate documentation frontpage and related reports
composer reports
composer reports --target=.dev-tools --coverage=.dev-tools/coverage
FAST_FORWARD_WORKSPACE_DIR=.artifacts composer reports

# Synchronize packaged agent skills into .agents/skills
composer skills
Expand Down Expand Up @@ -296,6 +300,13 @@ skills they depend on.
| `composer dev-tools:sync` | Updates scripts, CODEOWNERS, funding metadata, workflow stubs, `.editorconfig`, `.gitignore`, `.gitattributes`, wiki setup, packaged skills, and packaged agents. |
| `vendor/bin/dev-tools self-update` / `composer dev-tools:self-update` | Updates the local DevTools package, or the Composer global installation when the active binary is globally installed. |

`--working-dir`/`-d` changes the project root used by the standalone binary.
`--workspace-dir`/`-w` changes where generated DevTools artifacts and caches are
written when command-specific paths are omitted. Composer executions can use
`FAST_FORWARD_WORKSPACE_DIR=.artifacts composer reports` for the same workspace
policy, while explicit options such as `--target`, `--coverage`, `--metrics`,
and `--cache-dir` continue to take precedence.

## 🔌 Integration

DevTools integrates with consumer repositories in two ways. The Composer plugin
Expand Down
6 changes: 4 additions & 2 deletions docs/commands/docs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ Options

``--target, -t`` (optional)
Path to the output directory for the generated HTML documentation.
Default: ``.dev-tools``.
Default: selected workspace directory, ``.dev-tools`` unless
``--workspace-dir`` or ``FAST_FORWARD_WORKSPACE_DIR`` is configured.

``--source, -s`` (optional)
Path to the source directory for the guide documentation.
Expand All @@ -40,7 +41,8 @@ Options

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

``--cache``
Force phpDocumentor caching on for this run.
Expand Down
7 changes: 5 additions & 2 deletions docs/commands/metrics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,15 @@ Options
Comma-separated directories that should be excluded from analysis.

Default:
``vendor,tmp,cache,spec,build,.dev-tools,backup,resources``.
``vendor,tmp,cache,spec,build,.dev-tools,backup,resources`` plus a custom
relative workspace directory when ``--workspace-dir`` or
``FAST_FORWARD_WORKSPACE_DIR`` selects one.

``--target=<directory>``
Output directory for the generated metrics reports.

Default: ``.dev-tools/metrics``.
Default: selected workspace ``metrics`` directory, usually
``.dev-tools/metrics``.

The command writes:

Expand Down
3 changes: 2 additions & 1 deletion docs/commands/phpdoc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ 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: ``.dev-tools/cache/php-cs-fixer``.
Path to the cache directory for PHP-CS-Fixer. Default: selected workspace
cache directory, usually ``.dev-tools/cache/php-cs-fixer``.

``--cache``
Force PHP-CS-Fixer caching on for this run.
Expand Down
9 changes: 6 additions & 3 deletions docs/commands/reports.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,18 @@ Options

``--target`` (optional)
The target directory for the generated documentation.
Default: ``.dev-tools``.
Default: selected workspace directory, ``.dev-tools`` unless
``--workspace-dir`` or ``FAST_FORWARD_WORKSPACE_DIR`` is configured.

``--coverage, -c`` (optional)
The target directory for the generated test coverage report.
Default: ``.dev-tools/coverage``.
Default: selected workspace ``coverage`` directory, usually
``.dev-tools/coverage``.

``--metrics`` (optional)
The target directory for the generated metrics report.
Default: ``.dev-tools/metrics``.
Default: selected workspace ``metrics`` directory, usually
``.dev-tools/metrics``.

``--cache-dir`` (optional)
Base cache directory for nested ``docs`` and ``tests`` caches.
Expand Down
8 changes: 8 additions & 0 deletions docs/commands/self-update.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,21 @@ options before the command name:
.. code-block:: bash

vendor/bin/dev-tools --working-dir=/path/to/project tests
vendor/bin/dev-tools --workspace-dir=.artifacts reports
vendor/bin/dev-tools --auto-update tests

``--working-dir`` (or ``-d``) switches the process directory before resolving
paths, managed files, or command defaults. This lets a globally installed
binary operate on another project without first changing shell directories.
Composer executions can use Composer's own ``--working-dir``/``-d`` option.

``--workspace-dir`` (or ``-w``) changes where generated DevTools artifacts and
caches are written when command-specific paths are omitted. It does not change
the project root selected by ``--working-dir``. Composer plugin executions can use
``FAST_FORWARD_WORKSPACE_DIR=.artifacts`` to apply the same workspace policy.
Explicit command options such as ``--target``, ``--coverage``, ``--metrics``,
and ``--cache-dir`` continue to take precedence over the workspace default.

``--auto-update`` runs the self-update flow before the requested command. The
same behavior MAY be enabled with ``FAST_FORWARD_AUTO_UPDATE=1``. When the
active ``dev-tools`` binary is already installed globally, auto-update also
Expand Down
3 changes: 2 additions & 1 deletion docs/commands/tests.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ Options
Path to the bootstrap file. Default: ``./vendor/autoload.php``.

``--cache-dir`` (optional)
Path to the PHPUnit cache directory. Default: ``.dev-tools/cache/phpunit``.
Path to the PHPUnit cache directory. Default: selected workspace cache
directory, usually ``.dev-tools/cache/phpunit``.

``--cache``
Force PHPUnit result caching on for this run.
Expand Down
3 changes: 2 additions & 1 deletion docs/commands/wiki.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ Options

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

``--cache``
Force phpDocumentor caching on for this run.
Expand Down
11 changes: 10 additions & 1 deletion docs/configuration/tooling-defaults.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ create them on day one.
Generated and Cache Directories
-------------------------------

- ``.dev-tools/`` contains generated documentation and report output.
- ``.dev-tools/`` contains generated documentation and report output by
default.
- ``.dev-tools/coverage/`` contains HTML coverage, Testdox, Clover, and raw
coverage data.
- ``.dev-tools/metrics/`` contains PhpMetrics HTML output plus the generated
Expand All @@ -56,6 +57,14 @@ Generated and Cache Directories
``.dev-tools/cache/php-cs-fixer/.php-cs-fixer.cache`` store repository-local
tool caches.

The standalone binary accepts ``--workspace-dir`` to replace the generated
artifact root used by those defaults. Composer executions can set
``FAST_FORWARD_WORKSPACE_DIR`` for the same behavior. ``--working-dir`` still
selects the project root, while ``--workspace-dir`` selects where generated
artifacts and caches are written. Explicit command options such as
``--target``, ``--coverage``, ``--metrics``, and ``--cache-dir`` override the
workspace default.

Local Versus Packaged Files
---------------------------

Expand Down
18 changes: 12 additions & 6 deletions docs/running/reports.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,25 @@ What the Command Runs

``reports`` executes the following steps:

1. ``docs --target .dev-tools``
2. ``tests --coverage .dev-tools/coverage --coverage-summary``
3. ``metrics --target .dev-tools/metrics --junit .dev-tools/coverage/junit.xml``
1. ``docs`` with the selected workspace target
2. ``tests --coverage`` with the selected workspace coverage target
3. ``metrics --target`` with the selected workspace metrics target and JUnit
input from the selected workspace coverage directory

With the default workspace, those steps resolve to ``docs --target .dev-tools``,
``tests --coverage .dev-tools/coverage --coverage-summary``, and
``metrics --target .dev-tools/metrics --junit .dev-tools/coverage/junit.xml``.

Outputs
-------

After a successful run you should expect:

- the documentation site rooted at ``.dev-tools/``;
- the documentation site rooted at the selected workspace, usually
``.dev-tools/``;
- guide pages generated from the local ``docs/`` source;
- coverage reports inside ``.dev-tools/coverage/``;
- PhpMetrics output inside ``.dev-tools/metrics/``;
- coverage reports inside the selected workspace ``coverage`` directory;
- PhpMetrics output inside the selected workspace ``metrics`` directory;
- ``.dev-tools/coverage/testdox.html`` and ``.dev-tools/coverage/clover.xml`` for
human and CI consumption;
- ``.dev-tools/metrics/report.json`` and ``.dev-tools/metrics/report-summary.json`` for
Expand Down
11 changes: 8 additions & 3 deletions docs/running/specialized-commands.rst
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ Analyzes code metrics with PhpMetrics.

composer metrics
composer metrics --target=.dev-tools/metrics
FAST_FORWARD_WORKSPACE_DIR=.artifacts composer metrics
composer --working-dir=packages/example metrics

Important details:
Expand All @@ -128,6 +129,8 @@ Important details:
- ``--target`` stores the HTML report plus ``report.json`` and
``report-summary.json`` in the same directory for CI artifacts or manual
review;
- when ``--target`` is omitted, metrics output is written under the selected
DevTools workspace, usually ``.dev-tools/metrics``;
- ``--json`` and ``--pretty-json`` keep the top-level DevTools response
structured while forwarding JSON or quieter modes to the wrapped tools where
available;
Expand Down Expand Up @@ -262,9 +265,11 @@ Runs the documentation and test-report pipeline used by GitHub Pages.

Important details:

- it calls ``docs --target .dev-tools``;
- it calls ``tests --coverage .dev-tools/coverage --coverage-summary``;
- it calls ``metrics --target .dev-tools/metrics --junit .dev-tools/coverage/junit.xml``;
- it calls ``docs``, ``tests --coverage``, and ``metrics`` with defaults rooted
in the selected DevTools workspace;
- with the default workspace, that is equivalent to ``docs --target .dev-tools``,
``tests --coverage .dev-tools/coverage --coverage-summary``, and
``metrics --target .dev-tools/metrics --junit .dev-tools/coverage/junit.xml``;
- ``docs`` remains detached, while ``tests`` and ``metrics`` run in sequence so
PhpMetrics can reuse the JUnit report generated by PHPUnit;
- cache stays enabled by default for the nested ``docs`` and ``tests`` steps;
Expand Down
16 changes: 10 additions & 6 deletions docs/usage/documentation-workflows.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,23 @@ What Each Command Is For
- ``docs`` builds the HTML documentation site. It fails early if the source
guide directory does not exist.
- ``wiki`` builds Markdown API pages intended for ``.github/wiki``.
- ``reports`` runs ``docs --target .dev-tools`` and
``tests --coverage .dev-tools/coverage`` and then
- ``reports`` runs ``docs``, ``tests --coverage``, and ``metrics`` using the
selected DevTools workspace defaults. With the default workspace that means
``docs --target .dev-tools``, ``tests --coverage .dev-tools/coverage``, and
``metrics --target .dev-tools/metrics --junit .dev-tools/coverage/junit.xml``.
When ``--workspace-dir`` or ``FAST_FORWARD_WORKSPACE_DIR`` selects another
workspace, those nested defaults move together unless an explicit command
option overrides them.

Outputs to Expect
-----------------

- an HTML site rooted at the target directory chosen for ``docs``;
- guide pages generated from ``docs/``;
- coverage data under ``.dev-tools/coverage`` when ``reports`` or
``tests --coverage`` is used;
- metrics data under ``.dev-tools/metrics`` when ``reports`` or ``metrics`` is
used;
- coverage data under the selected workspace ``coverage`` directory when
``reports`` or ``tests --coverage`` is used;
- metrics data under the selected workspace ``metrics`` directory when
``reports`` or ``metrics`` is used;
- Markdown API pages under ``.github/wiki`` when ``wiki`` is used.

Troubleshooting
Expand Down
3 changes: 2 additions & 1 deletion docs/usage/testing-and-coverage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ When you run ``tests``, DevTools:
- keeps PHPUnit result caching enabled by default;
- treats ``--cache`` as an explicit force-on flag and ``--no-cache`` as an
explicit force-off flag for the current run;
- uses ``.dev-tools/cache/phpunit`` only when caching stays enabled;
- uses the selected workspace ``cache/phpunit`` directory only when caching
stays enabled;
- can generate HTML coverage, Testdox, Clover, and raw PHP coverage output
when ``--coverage`` is provided.

Expand Down
33 changes: 32 additions & 1 deletion src/Console/Command/MetricsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ final class MetricsCommand extends Command
*/
private const int PHP_DEFAULT_SOCKET_TIMEOUT = 1;

/**
* @var list<string> the directories PhpMetrics SHOULD skip by default
*/
private const array DEFAULT_EXCLUDED_DIRECTORIES = [
'vendor',
'tmp',
'cache',
'spec',
'build',
ManagedWorkspace::WORKSPACE_ROOT,
'backup',
'resources',
];

/**
* @param ProcessBuilderInterface $processBuilder the builder used to assemble the PhpMetrics process
* @param ProcessQueueInterface $processQueue the queue used to execute the PhpMetrics process
Expand Down Expand Up @@ -89,7 +103,7 @@ protected function configure(): void
name: 'exclude',
mode: InputOption::VALUE_OPTIONAL,
description: 'Comma-separated directories that SHOULD be excluded from analysis.',
default: 'vendor,tmp,cache,spec,build,.dev-tools,backup,resources',
default: implode(',', $this->getDefaultExcludedDirectories()),
)
->addOption(
name: 'target',
Expand Down Expand Up @@ -164,4 +178,21 @@ protected function execute(InputInterface $input, OutputInterface $output): int
'output' => $processOutput,
]);
}

/**
* Returns the default PhpMetrics directory exclusion list.
*
* @return list<string>
*/
private function getDefaultExcludedDirectories(): array
{
$directories = self::DEFAULT_EXCLUDED_DIRECTORIES;
$workspaceRoot = ManagedWorkspace::getProjectRelativeWorkspaceRoot();

if (null !== $workspaceRoot && ! \in_array($workspaceRoot, $directories, true)) {
$directories[] = $workspaceRoot;
}

return $directories;
}
}
27 changes: 27 additions & 0 deletions src/Console/DevTools.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use FastForward\DevTools\Console\Command\SelfUpdateCommand;
use Override;
use FastForward\DevTools\Environment\EnvironmentInterface;
use FastForward\DevTools\Path\ManagedWorkspace;
use FastForward\DevTools\SelfUpdate\SelfUpdateRunnerInterface;
use FastForward\DevTools\SelfUpdate\SelfUpdateScopeResolverInterface;
use FastForward\DevTools\SelfUpdate\VersionCheckNotifierInterface;
Expand All @@ -38,6 +39,8 @@
use Symfony\Component\Console\Output\OutputInterface;
use Throwable;

use function Safe\putenv;

/**
* Wraps the fast-forward console tooling suite conceptually as an isolated application instance.
* Extending the base application, it MUST provide default command injections safely.
Expand Down Expand Up @@ -118,6 +121,13 @@ protected function getDefaultInputDefinition(): InputDefinition
description: 'Update fast-forward/dev-tools before running the requested command.',
));

$definition->addOption(new InputOption(
name: 'workspace-dir',
shortcut: 'w',
mode: InputOption::VALUE_REQUIRED,
description: 'Store generated DevTools artifacts in the given directory.',
));

return $definition;
}

Expand All @@ -134,6 +144,7 @@ public function doRun(InputInterface $input, OutputInterface $output): int
{
try {
$this->workingDirectorySwitcher->switchTo($this->getWorkingDirectoryOption($input));
$this->configureWorkspaceDirectory($input);
} catch (Throwable $throwable) {
$output->writeln(\sprintf('<error>%s</error>', $throwable->getMessage()));

Expand Down Expand Up @@ -183,6 +194,22 @@ private function getWorkingDirectoryOption(InputInterface $input): ?string
return \is_string($workingDirectory) ? $workingDirectory : null;
}

/**
* Applies the configured workspace directory before resolving command defaults.
*
* @param InputInterface $input the application input
*/
private function configureWorkspaceDirectory(InputInterface $input): void
{
$workspaceDirectory = $input->getParameterOption('--workspace-dir', null, true);

if (! \is_string($workspaceDirectory) || '' === $workspaceDirectory) {
return;
}

putenv(ManagedWorkspace::ENV_WORKSPACE_DIR . '=' . $workspaceDirectory);
}

/**
* Runs an explicit automatic update without letting failures block the requested command.
*
Expand Down
Loading
Loading