Backport Builder is a release-engineering project. Treat source repositories as inputs, generated trees as outputs, and custom Rector rules as tested build logic.
Use this guide when you maintain downgrade rules, generated package metadata, target-runtime checks, or release automation for nextpdf/backport-builder.
Layer Owned by Responsibility Do not put here Source repositories Product repos Authoritative PHP source and tests. Generated downgrade edits. Build scripts nextpdf/backport-builderMerge source, run transformations, write metadata, and validate output. Runtime application logic. Rector config nextpdf/backport-builderTarget-specific downgrade policy. Cross-target assumptions without tests. Custom Rector rules nextpdf/backport-builderProject-specific syntax transforms. Broad untested rewrites. Generated packages Build output Installable artifacts for older runtimes. Manual source-of-truth patches.
Stage Behavior Developer action Source checkout The release workflow checks out source repositories at the target tag. Keep source refs aligned across packages. Contract validation ValidateBuildContract::run() checks build assumptions.Treat a failed contract as release-blocking. Merge MergeSources::run() assembles the target package tree.Verify target scope before running Rector. Transform Rector configurations and custom rules downgrade syntax. Add fixture tests for every rule change. Composer adjustment AdjustComposer writes generated package metadata and replace maps.Validate package names, versions, licenses, and constraints. Runtime validation Generated output is syntax-checked and tested on target PHP versions. Treat target-runtime failure as release-blocking. Release Archives are attached to a release. Do not patch generated output as the source of truth.
Work item Source of truth Generated output policy PHP feature usage Main source repo. Backport rules adapt the feature. Dependency constraints Source composer.json metadata plus the adjustment script. Generated composer.json must be reproducible. Syntax downgrade Rector config and custom rules. Generated source should not be manually edited. Runtime support Target branch and CI matrix. Build must pass on target PHP. Release notes Docs and release automation. Generated artifacts should link back to source release.
Each custom rule should have a narrow purpose, metadata, and fixture coverage.
Rule method Purpose Quality requirement getRuleDefinition()Documents the transform for Rector tooling. Include a before/after sample that matches the actual downgrade. getNodeTypes()Limits the AST nodes inspected by the rule. Keep the node list as small as possible. refactor()Applies the transform or returns unchanged. Leave unrelated nodes unchanged and deterministic. Fixture test Verifies before/after output. Cover the smallest valid input and at least one skip case.
final class ExampleDowngradeRector extends AbstractRector
public function getNodeTypes () : array
return [ SomeNode :: class ];
public function refactor ( Node $node ) : ? Node
if ( ! $node instanceof SomeNode ) {
return $this-> rewriteNode ( $node );
Use dry runs during development and release candidate validation. Write real output only when the source refs and target branch are known.
php scripts/build.php --version=2.0.0 --target=php81 --dry-run
php scripts/build.php --version=2.0.0 --target=php74 --no-pro
Run generated package validation on the target runtime, not only on the modern build host.
Extension point Use it for Constraint Rector config files Target-specific downgrade policy. Keep PHP 8.1 and PHP 7.4 lanes separate. Custom Rector rules Project-specific syntax transforms. Must have metadata and fixture tests. Composer adjustment script Generated package identity. Must preserve SemVer-aligned versioning. Merge script Select and shape source package input. Must log source roots and output roots. Build workflow Release orchestration. Must validate generated output on target runtime.
Reproduce the unsupported syntax in a minimal fixture.
Add or update a custom Rector rule.
Add before/after fixtures for the rule.
Run the dry build.
Validate generated output on the target PHP runtime.
Apply the same logical change to each permanent target branch when required.
Keep release artifacts reproducible from source tags and build scripts.
Failure Where it should be handled Recommended response Missing source repo Contract validation or merge stage. Stop the build and fix checkout inputs. Rector parse failure Transform stage. Reduce to a fixture and update the rule or config. Generated composer.json mismatch Composer adjustment stage. Fix generation script, not generated metadata. Target syntax failure Runtime validation. Block the release until the transform is corrected. Pro source unavailable Build configuration. Build public artifact only when that is the intended target.
Concern Default When to override Generated output Read-only artifact. Never make it the source of truth. Branch model Separate permanent target branches. Keep changes synchronized through independent pull requests. Build host Modern PHP. Target runtime validation still decides release readiness. Custom rules Small and fixture-backed. Avoid broad transforms without explicit before/after examples. PHP 7.4 lane Core-only unless explicitly supported. Do not include Pro output without target-runtime validation.
Rector rule metadata tests instantiate every custom rule.
Fixture tests cover before and after code for each transform.
Dry build runs before release jobs.
Target runtime syntax checks and package tests run on generated output.
Composer metadata tests assert package name, version, constraints, replace map, and license.
Build logs include source paths, target path, target runtime, dry-run state, and Pro inclusion state.