Skip to content

Create a New Composer Package

This guide covers the full flow from idea to a published internal package that can be required from other projects.


Prerequisites

  • GitHub access to the subscribed-aps organisation
  • composer installed locally (≥ 2.0)
  • git configured with an SSH key for GitHub

1. Create the GitHub repo

Create a new private repo under the subscribed-aps organisation using the naming convention:

subscribed-aps/wp-pkg-<name>
# Examples:
subscribed-aps/wp-pkg-otp
subscribed-aps/wp-pkg-billing
subscribed-aps/wp-pkg-notifications

Choose: PHP .gitignore template, MIT License, no readme (we'll create it ourselves).


2. Bootstrap locally

mkdir wp-pkg-<name> && cd wp-pkg-<name>
git init
git remote add origin git@github.com:subscribed-aps/wp-pkg-<name>.git

3. composer.json

Minimum composer.json for an internal package:

{
    "name": "subscribed-aps/wp-pkg-<name>",
    "description": "Internal <description> shared across Subscribed projects",
    "type": "library",
    "license": "MIT",
    "require": {
        "php": "^7.4"
    },
    "require-dev": {
        "phpunit/phpunit": "^9.0",
        "phpstan/phpstan": "^1.10"
    },
    "autoload": {
        "psr-4": {
            "Subscribed\\<Name>\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Subscribed\\<Name>\\Tests\\": "tests/"
        }
    },
    "config": {
        "sort-packages": true,
        "allow-plugins": {
            "phpstan/extension-installer": true
        }
    },
    "minimum-stability": "stable",
    "prefer-stable": true
}

Naming convention

Use subscribed-aps/wp-pkg-<name> as the Composer package name and Subscribed\<PascalCase>\ as the root namespace.


4. Directory structure

wp-pkg-<name>/
├── src/
│   └── <Name>Manager.php
├── tests/
│   └── <Name>ManagerTest.php
├── docs/
│   └── index.md           # Synced to Engineering Handbook
├── .github/
│   └── workflows/
│       ├── tests.yml
│       └── notify-handbook.yml
├── CHANGELOG.md
├── composer.json
└── README.md

5. CI/CD checklist

Create .github/workflows/tests.yml:

name: Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with:
          php-version: "7.4"
          coverage: xdebug
      - run: composer install --prefer-dist --no-progress
      - run: vendor/bin/phpunit --coverage-text
      - run: vendor/bin/phpstan analyse src --level=8

See the Handbook Notifications guide for how to set up the notify-handbook.yml workflow.


6. Publish the first version

git add .
git commit -m "feat: initial package setup"
git push -u origin main

git tag v1.0.0
git push origin v1.0.0

7. Require the package from another project

Add the repo to the project's composer.json:

{
    "repositories": [
        {
            "type": "vcs",
            "url": "git@github.com:subscribed-aps/wp-pkg-<name>.git"
        }
    ]
}

Then:

composer require subscribed-aps/wp-pkg-<name>:^1.0

PR Checklist

Before merging to main on a package repo:

  • composer install runs without errors
  • All tests pass (vendor/bin/phpunit)
  • PHPStan level 8 passes (vendor/bin/phpstan analyse src)
  • CHANGELOG.md is updated
  • Breaking changes are described in the PR description
  • Version is tagged correctly (semver: v1.2.3)
  • docs/index.md is updated if the API has changed