ADR-0001: Use Composer for Internal Packages¶
Date: 2024-01-15
Status: Accepted
Decision makers: Dev team
Context¶
We have recurring code across five projects: authentication, billing logic, API clients, and shared utilities. Previously we copied code manually or used git subtrees, which led to diverging versions and difficult maintenance.
We needed a standardised way to share PHP code internally — with versioning, dependency resolution, and reproducible builds.
We considered:
- Git subtrees/submodules — complex, poor DX, no versioning
- Private Packagist — paid, more than we need
- Satis (self-hosted Composer repo) — open source, full control
- GitHub Packages with Composer — tight integration with our existing GitHub setup
Decision¶
We use Composer as the package manager for all internal PHP libraries, with GitHub Packages (or a self-hosted Satis instance) as the private registry.
Each internal library lives in its own GitHub repo with:
- A versioned
composer.json - Semantic versioning via Git tags (
v1.2.3) - A
docs/folder with documentation that syncs to this handbook
All projects require internal packages via composer require subscribed-aps/<package-name>, targeting PHP 7.4 compatibility.
Consequences¶
Positive:
- One place to maintain shared code — no copying
- Semantic versioning gives explicit control over breaking changes
composer.lockensures reproducible builds in CI/CD- Documentation can be automatically pulled into the Engineering Handbook
- Onboarding new developers follows standard PHP workflow
Negative / trade-offs:
- Requires all internal repos to be accessible from CI/CD (token management)
- Breaking changes in a package require coordinated updates across dependent projects
- Overhead in creating a new repo + package structure for each library
Mitigation:
- We maintain a guide for new Composer packages
- Breaking changes are communicated via CHANGELOG.md and Slack
#dev-team - We use
^version pinning by default to allow patch and minor updates