Skip to content

Support workflow_call consumers without a local DevTools dependency #303

@coisa

Description

@coisa

Problem

The reusable workflows currently shipped from php-fast-forward/dev-tools assume that the consumer repository already installs fast-forward/dev-tools locally.

Today, .github/actions/php/setup-composer/action.yml only sets up PHP, warms the Composer cache, and runs composer install. After that, the reusable workflows execute composer dev-tools ... directly. That works for repositories that declare fast-forward/dev-tools as a Composer dependency, but it blocks workflow_call consumers that want to reuse the packaged automation without taking a direct package dependency.

This limitation is visible in workflows such as:

  • .github/workflows/tests.yml
  • .github/workflows/changelog.yml
  • .github/workflows/reports.yml
  • .github/workflows/wiki-preview.yml

These workflows already check out the DevTools workflow action source, but they still fail when the consumer repository does not provide a local composer dev-tools entrypoint.

That makes it harder to sync and reuse the packaged automation in repositories such as fast-forward/agents, fast-forward/github-actions, and similar workflow-driven repositories that may not need the full local DevTools package as an application dependency.

Proposal

Support a workflow runtime fallback that prefers the consumer local fast-forward/dev-tools installation when it exists and otherwise installs or resolves DevTools globally for workflow execution.

As part of this setup work, prefer delegating the generic Composer install/cache responsibilities to ramsey/composer-install where it fits, instead of continuing to grow a bespoke Composer install action for concerns that are not DevTools-specific.

This should be treated as an interim compatibility improvement before the broader reusable-workflow extraction tracked in #240.

Goals

  • Allow workflow_call consumers to run packaged DevTools workflows without adding fast-forward/dev-tools to their local Composer dependencies.
  • Preserve the current behavior for repositories that already depend on fast-forward/dev-tools locally.
  • Keep the fallback deterministic so workflow behavior does not depend on an unrelated implicit global package version.
  • Reuse a maintained off-the-shelf Composer install/cache action for the generic setup path when that does not compromise Fast Forward-specific bootstrap needs.

Expected Behavior

When a reusable workflow needs to execute DevTools commands:

  • if the consumer repository already provides fast-forward/dev-tools, the workflow continues to use that local installation;
  • if the consumer repository does not provide fast-forward/dev-tools, the workflow resolves a global DevTools runtime and still completes successfully;
  • synced wrappers under resources/github-actions/ continue to work for both kinds of consumers;
  • workflow output, failure handling, and generated artifacts remain equivalent between the local and fallback paths.

Implementation Strategy

  • Introduce a shared workflow bootstrap around .github/actions/php/setup-composer or an adjacent helper so local-vs-global DevTools resolution happens in one place.
  • Prefer ramsey/composer-install for the generic Composer dependency installation and cache management portion of that bootstrap, while keeping Fast Forward-specific concerns such as safe.directory, auth wiring, and DevTools runtime resolution in our own wrapper layer when needed.
  • Update every reusable workflow that currently shells into composer dev-tools ... after setup to use that shared runtime bootstrap instead of assuming a local Composer script exists.
  • Keep the fallback limited to workflow execution; this issue should not change how repositories use DevTools locally through Composer, the plugin, or synced scripts.
  • Ensure the fallback runtime is resolved deterministically from the workflow execution context rather than silently pulling an arbitrary latest release.

Requirements

  • Reusable workflows that execute DevTools commands MUST support consumers that do not install fast-forward/dev-tools locally.
  • The bootstrap MUST prefer a consumer-local DevTools installation when it exists and only fall back to a global runtime when it is missing.
  • The fallback MUST resolve a deterministic DevTools runtime aligned with the workflow source or ref strategy being executed.
  • The shared runtime bootstrap MUST be reused across affected workflows instead of duplicating local-vs-global resolution logic in each workflow file.
  • Generic Composer dependency installation and cache management SHOULD reuse ramsey/composer-install unless a concrete Fast Forward-specific requirement prevents it.
  • Workflow documentation and troubleshooting guidance MUST be updated when this makes the local package dependency optional for workflow-only consumers.

Non-goals

  • Migrating all reusable workflows and composite actions into php-fast-forward/.github as part of this issue; that broader extraction remains tracked by Extract shared GitHub Actions automation into php-fast-forward/.github #240.
  • Removing or deprecating the local fast-forward/dev-tools dependency path for repositories that already rely on it.
  • Replacing every Fast Forward composite action with third-party actions beyond the generic Composer install/cache layer.
  • Redesigning the overall workflow ref or release policy beyond what is necessary to make the fallback deterministic.

Benefits

This would let Fast Forward repositories adopt synced workflow automation without having to declare fast-forward/dev-tools as a direct Composer dependency when they only need the reusable workflows. It also gives us a cleaner bridge while the larger workflow/action extraction work is still pending.

Leaning on ramsey/composer-install for the generic Composer setup path would also reduce the amount of cache and install behavior we need to maintain ourselves, letting the Fast Forward wrapper stay focused on DevTools-specific runtime concerns.

Acceptance Criteria

Functional Criteria

  • A workflow_call consumer without fast-forward/dev-tools in its local Composer dependencies can run the packaged workflows that require DevTools commands.
  • Consumers that already install fast-forward/dev-tools locally continue to use the local installation without behavioral regressions.
  • .github/workflows/tests.yml, .github/workflows/changelog.yml, .github/workflows/reports.yml, .github/workflows/wiki-preview.yml, and any other reusable workflow that executes DevTools commands use the shared fallback bootstrap instead of assuming composer dev-tools exists locally.
  • The fallback runtime is deterministic and aligned with the workflow execution context instead of implicitly installing an unrelated latest global release.
  • The setup path reuses ramsey/composer-install for generic Composer install/cache handling unless a documented Fast Forward-specific constraint blocks that adoption.
  • Documentation explains when workflow consumers can omit a local fast-forward/dev-tools dependency.

Regression Criteria

  • Add or update automated coverage for a consumer-style workflow scenario where fast-forward/dev-tools is not installed locally.
  • Existing workflow consumers with a local DevTools dependency remain covered by regression checks.
  • Reports, changelog validation, PHPUnit and dependency checks, and wiki preview generation remain functionally equivalent after the runtime bootstrap change.

Architectural / Isolation Criteria

  • MUST: The core logic MUST be isolated into dedicated classes or services instead of living inside command or controller entrypoints.
  • MUST: Responsibilities MUST be separated across input resolution, domain logic, processing or transformation, and output rendering when the change is non-trivial.
  • MUST: The command or controller layer MUST act only as an orchestrator.
  • MUST: The implementation MUST avoid tight coupling between core behavior and CLI or framework-specific I/O.
  • MUST: The design MUST allow future extraction or reuse with minimal changes.
  • MUST: The solution MUST remain extensible without requiring major refactoring for adjacent use cases.

Metadata

Metadata

Assignees

No one assigned

    Projects

    Status

    Merged

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions