open-telemetry/dev-tools
Shared development tooling for OpenTelemetry PHP: coding-standard, static-analysis, and CI configurations that keep contributions consistent across the ecosystem. Add it as a dev dependency to align packages with project conventions.
open-telemetry/dev-tools is not a runtime package — do not composer require it into a Laravel app expecting tracing, middleware, or TracerProvider wiring. Those live in open-telemetry/sdk, open-telemetry/exporter-otlp, and open-telemetry/opentelemetry-auto-laravel. This package is the shared development baseline the OpenTelemetry PHP repositories use to keep code style, static analysis, tests, and release tooling consistent across api, sdk, context, exporters, and instrumentation packages.
As of 0.2 it is also demonstrably more than a bag of dotfiles: the release adds "filtering by repository prefix" and "list released versions," which means there is a console entrypoint (Symfony Console based — hence the Symfony 8 support work) that queries and reports on the OTel PHP repo/package set. That tooling is the most interesting thing in the package and is the thing worth evaluating first.
Two realistic audiences:
First steps:
composer require --dev open-telemetry/dev-tools
ls vendor/bin # 0.2 ships a real binary; confirm the name here
vendor/bin/<binary> list # Symfony Console app: enumerate commands
vendor/bin/<binary> <cmd> --help # check for the new prefix-filter option
Then inspect, in this order:
bin/ → the console entrypoint and which command classes it wiressrc/ / src/Command/ → the release/version-listing commands, especially the repository-prefix filter argumentcomposer.json → bin, require (you will now see symfony/console and friends), require-dev, scripts, autoload.php-cs-fixer.dist.php, psalm.xml/phpstan.neon, phpunit.xml.dist, Makefile, .github/workflows/First use case: run the version-listing command with a repository-prefix filter against the package set you care about, and see what it reports versus what you believe is tagged and released. If your monorepo splits into several repos (myorg/laravel-foo, myorg/laravel-bar, …), a prefix filter like myorg/laravel- is exactly the scoping knob you'd otherwise hand-roll in bash. Second, open the shipped .php-cs-fixer.dist.php and psalm.xml and run them once against your src/ to see the delta. Those two runs tell you more about the package than the README does.
Dev-only, pinned exactly. Always --dev, and pin an exact version ("open-telemetry/dev-tools": "0.2.0"). This is pre-1.0 internal-facing tooling with no stability promise — ^0.2 only buys you patches, and even those can move tool versions underneath you.
Config inheritance rather than copy-paste. The intended pattern is to have your own config require the distributed one:
// .php-cs-fixer.php
$config = require __DIR__.'/vendor/open-telemetry/dev-tools/.php-cs-fixer.dist.php';
$config->setFinder(PhpCsFixer\Finder::create()->in(__DIR__.'/src'));
return $config;
Same idea for psalm.xml (<xi:include href="vendor/.../psalm.xml"/>) and phpunit.xml.dist (extend the base suite, override bootstrap).
Composer script normalization. Wire your scripts to the shared entrypoints so CI and local dev never diverge:
"scripts": {
"fix": "php-cs-fixer fix",
"analyse": "psalm --no-cache",
"test": "phpunit",
"check": ["@fix", "@analyse", "@test"]
}
Release bookkeeping as a script, not a ritual. The 0.2 commands are the pattern worth stealing: put the audit in scripts so it runs the same way locally and in CI, with the repo prefix passed as an argument rather than hardcoded.
"scripts": {
"release:audit": "<binary> <version-listing-command> --repository-prefix=myorg/"
}
Run it as a pre-tag gate: it surfaces sub-packages that are tagged but never released, or released but drifted, which PHPUnit will never tell you. Combine with the composer.json/manifest validator (if present) so metadata problems and release-state problems fail in one place.
Monorepo / multi-package pattern. If you split a Laravel package into core, laravel, testing sub-packages, mirror OTel's approach: path repositories in the root composer.json, one shared dev-tools dev-dependency at the root, and per-package composer.json files that stay dependency-light. This is the pattern that makes a six-package repo testable as a unit — and it is the shape the prefix filter assumes.
CI integration. Let the package own the tool versions and let your workflow own only the matrix (PHP 8.2/8.3/8.4, Laravel 10/11/12). Install once, call composer check. Cache ~/.composer/cache and use --prefer-dist. Put the release audit in a separate, non-matrixed job — it is a whole-repo question, not a per-PHP-version one, and running it six times only multiplies API calls and cache churn.
Pre-release validation. If the package ships a composer.json/manifest validator command, run it over every sub-package before tagging — it catches missing license, wrong autoload paths, and dependency drift that PHPUnit will never surface.
myorg/ and myorg/laravel- select very different sets, and a too-loose prefix silently includes unrelated repos. Verify the match semantics (prefix vs. substring vs. regex) before trusting a release report. If it queries the GitHub API for released versions, expect to need a token and to hit rate limits in unauthenticated CI — check the command's --help and source before wiring it into a workflow that fans out.symfony/console depends on your PHP version and on what Laravel has already pinned — Laravel 11/12 ship Symfony 7 components. On older matrix entries you'll get the 7.x line; if anything in your tree requires symfony/console ^8, resolution can fail or silently pick a combination you didn't test. Run composer why symfony/console after adding this and check the lock diff.pint, larastan, or your app's phpunit. If composer update starts fighting, isolate it with bamarni/composer-bin-plugin (tools/ bin namespace) so the dev-tools dependency tree never touches your application's. This also keeps its vendor/bin binary out of your app's bin namespace, which matters now that there is a binary.composer dump-autoload; only the binary appears in vendor/bin. Verify with ls vendor/bin before wiring scripts, otherwise composer check fails in CI with "command not found" rather than a useful error. Note the binary name is whatever composer.json's bin says — don't guess.--dev bump can silently break composer install on your oldest CI matrix entry — pin the PHP version in the job that installs dev dependencies.composer why open-telemetry/dev-tools and composer show -t to see what pulled it in; composer show --all open-telemetry/dev-tools to inspect versions and constraints..php-cs-fixer.php / psalm.xml that require or xi:include the distributed config, per-package <testsuite> overrides in phpunit.xml, and wrapper composer scripts around the new release commands. Avoid editing anything under vendor/ — it disappears on the next composer update.require (not just require-dev) before publishing a Laravel package; a dev-tools entry in require drags Symfony console and a release CLI into every consumer's install for zero runtime benefit.How can I help you explore Laravel packages today?