See Repository Setup for mandatory initial setup required for the Wiki workflow to function. See Branch Protection and Bot Commits for branch protection, bot commit, and submodule pointer conflict guidance.
GitHub Actions Workflows
FastForward DevTools provides a set of reusable GitHub Actions workflows that automate testing, documentation generation, and wiki synchronization. These workflows are synchronized into consumer repositories via the dev-tools:sync
command.
Workflow Layers
The automation model now has three layers:
- Local composite and JavaScript actions
in
.github/actions/inside this repository. These contain the reusable implementation details for PHP setup, project-board transitions, GitHub Pages handling, changelog publishing, wiki branch management, and related helpers. - Reusable workflows
in
.github/workflows/inside this repository. These are the canonical automation entrypoints consumed by Fast Forward repositories and wrappers. - Consumer wrappers
copied from
resources/github-actions/*.ymlinto the consumer repository's.github/workflows/directory bydev-tools:sync. These wrappers keep triggers and repository-specific defaults local while delegating implementation to the reusable workflows inphp-fast-forward/dev-tools.
Wrapper Workflows
Consumer repositories usually keep thin wrapper workflows in
.github/workflows/
that call the reusable workflows published by
php-fast-forward/dev-tools
.
Example of an inherited workflow:
name: "Fast Forward Reports"
uses: php-fast-forward/dev-tools/.github/workflows/reports.yml@main
secrets: inherit
This approach ensures that all libraries in the ecosystem benefit from infrastructure updates without requiring manual changes to every repository.
The packaged wrappers currently include:
tests.ymlreports.ymlchangelog.ymlwiki.ymlfor pull-request wiki previewswiki-maintenance.ymlfor merged-publication and cleanup workauto-assign.ymllabel-sync.yml
For the protected-branch-safe preview and publish model, see Branch Protection and Bot Commits.
Fast Forward Reports
The reports.yml
workflow is responsible for generating technical documentation and quality reports.
Triggers: Push to ``main``. Pull Request (opened, synchronized, reopened, closed). * Manual trigger (workflow_dispatch).
Behavior:
**Main Branch**: Runs all checks and deploys the final reports to the root of the ``gh-pages`` branch.
Runs a post-deploy health check against the published reports index and coverage URLs with retry/backoff to account for Pages propagation.
Resolves the workflow PHP version from ``composer.lock`` or ``composer.json`` before installing dependencies.
Removes .dev-tools/cache
from the publish directory before deployment so repository-local tool caches never leak into GitHub Pages output.
**Pull Requests**:
Generates a Preview
of the documentation, coverage, and metrics.
Deploys the preview to ``gh-pages`` under ``previews/pr-{number}/``.
Verifies the preview index and coverage URLs after deployment before posting preview links.
Posts a **Sticky Comment** on the PR with links to the live preview, coverage report, and metrics site.
Groups nested command output into collapsible GitHub Actions log sections so docs, tests, and metrics are easier to inspect independently.
**Cleanup**: When a PR is closed, the workflow automatically removes the preview directory from the ``gh-pages`` branch to keep the repository clean.
Concurrency
: New pushes to the same PR cancel older in-progress preview runs without affecting other PRs.
* Scheduled Cleanup
: A scheduled/manual cleanup removes stale previews/pr-{number}/
directories for already closed pull requests.
Fast Forward Wiki
Wiki automation is split into two reusable workflows and two consumer wrappers:
wiki.ymlcalls the reusablewiki-preview.ymlworkflow and is responsible only for pull-request preview updates.wiki-maintenance.ymlcalls the reusablewiki-maintenance.ymlworkflow and is responsible for merged publication, closed-preview deletion, and scheduled cleanup.
Behavior:
**Submodule Management**: Both wiki workflows work against the
``.github/wiki`` submodule that points to the actual GitHub Wiki
repository.
Pull Request Preview
: wiki.yml
updates a dedicated preview branch
in the wiki repository named pr-{number}
.
**Preview Generation**: The preview workflow resolves the PHP version,
installs dependencies, runs ``composer dev-tools wiki -- --target=.github/wiki``,
commits the generated Markdown into the wiki submodule, and then updates
the parent repository's submodule pointer when needed.
Merged Publication
: wiki-maintenance.yml
promotes the matching
pr-{number}
preview branch to master
after a pull request is merged
into main
and validates the resulting remote SHA.
* Cleanup
: wiki-maintenance.yml
deletes preview branches for closed
pull requests and also performs scheduled cleanup for stale
pr-{number}
branches.
Fast Forward Tests
The tests.yml
workflow provides standard Continuous Integration.
- Runs PHPUnit tests across the supported PHP matrix.
- Resolves the minimum supported PHP minor version from
composer.lockorcomposer.jsonand builds the test matrix from that floor upward. - Runs dependency health as a separate required job.
- Defaults the dependency-health threshold to
--max-outdated=-1so outdated packages stay visible in CI without failing the workflow on count alone. - Surfaces logged command failures as native GitHub Actions error annotations, including file and line metadata when the command provides them.
- Uses PR-scoped concurrency so newer pushes cancel older in-progress runs for the same pull request.
Fast Forward Changelog
The changelog.yml
workflow validates pull-request changelog updates and
automates the release-preparation flow for repositories that use the local
changelog commands. Consumer repositories typically expose it through the thin
wrapper in resources/github-actions/changelog.yml
.
Triggers: Pull Request (opened, synchronized, reopened). Pull Request Target (closed) for merged release-preparation pull requests. * Manual trigger (workflow_dispatch).
Behavior:
**Pull Requests**:
Resolves the workflow PHP version from composer.lock
or
composer.json
before installing dependencies.
Uses ``fetch-depth: 0`` so the base branch reference can be compared
safely.
Fetches the base branch changelog reference.
Runs ``composer dev-tools changelog:check -- --against=<base-ref>`` against the base ref.
Fails when a normal non-release branch does not add a meaningful Unreleased
change.
Skips the validation job for pull requests whose head branch matches the configured ``release-branch-prefix``, because release-preparation branches intentionally leave ``Unreleased`` empty after promotion.
Manual Release Preparation
:
Checks out the repository default branch with full history.
Resolves the next version from Unreleased
unless a version input is provided.
Promotes ``Unreleased`` into the selected version with the current UTC release date.
Writes a release-notes preview file to .dev-tools/release-notes.md
with
composer dev-tools changelog:show -- <version>
.
Opens or updates a release-preparation pull request instead of committing directly to ``main``.
Requires repository Actions permissions that allow the workflow token to create pull requests.
**Merged Release Pull Requests**:
Detects merged branches that match the configured release branch prefix.
Renders the released changelog section with ``composer dev-tools changelog:show -- <version>``.
Creates or updates the Git tag and GitHub release with the rendered changelog section as the release body.
* Does not
run for ordinary feature or fix pull requests merged into main
.
Inputs:
``changelog-file``: managed changelog path, default ``CHANGELOG.md``.
version
: optional explicit version for manual release preparation.
* release-branch-prefix
: release branch prefix, default release/v
.
Repository prerequisites: Go to **Settings** > **Actions** > **General**. Under Workflow permissions , enable Read and write permissions . Enable **Allow GitHub Actions to create and approve pull requests**. If either control is disabled or grayed out, the repository is likely constrained by organization-level policy or missing admin permission. In that case, an organization or repository admin must unlock the setting before manual release preparation can open a release pull request.
Branch protection is not what blocks the release-preparation workflow from opening a pull request. Branch protection affects the merge of the release/v...
pull request later in the flow. The gray or disabled workflow-permission controls come from repository permissions or organization policy.
Maintenance Workflows
- Project Board Automation
:
Supports both direct repository use and ``workflow_call`` wrappers in
consumer repositories.
Uses
github.repository_ownerto determine the owning organization or user. For ``php-fast-forward`` repositories, defaults to the first organization Project V2 when no explicit project number is provided. Consumer repositories SHOULD either passprojectin the wrapper workflow or definePROJECTas a repository variable. The reusable workflows consistently resolve the board as ``inputs.project || vars.PROJECT || ''``. In practice that means: wrapper input wins, then the repository variable, and finally the php-fast-forward organization default when the reusable workflow supports it. Adds new issues to the project and moves them intoBacklog. Adds linked pull requests to the same project, mirrors milestone plus inferable project metadata, and keeps draft PRs in ``In progress`` until they are explicitly ready for review. Promotes approved pull requests intoReady to Merge. Moves merged pull requests and linked issues into ``Merged``. Moves all currentlyMergedwork intoRelease Preparedwhenchangelog.ymlopens or updates a release-preparation pull request. Promotes all ``Release Prepared`` work into ``Released`` when the release-preparation pull request is merged and the GitHub release is published. Uses the built-in workflow token for project updates. - Label Sync : Synchronizes repository labels with ecosystem standards.