Skip to content

Define release-safe refs for consumer workflow wrappers and checked-out actions #238

@coisa

Description

@coisa

Problem

Consumer repositories currently synchronize thin workflow wrappers from resources/github-actions/*.yml, and those wrappers call reusable workflows from this repository using php-fast-forward/dev-tools/.github/workflows/<workflow>.yml@main.

Inside the reusable workflows, when local composite actions are needed, the workflow sparse-checks out .github/actions from php-fast-forward/dev-tools into .dev-tools-actions. In consumer runs that checkout currently resolves against main as well.

That means a consumer repository can run automation from the current development state of dev-tools, not necessarily from the latest published fast-forward/dev-tools release installed in that consumer. If main contains workflow or action changes that have not been released yet, consumers can see behavior that does not match the package version they depend on.

Why This Matters

This creates a subtle version skew across the ecosystem:

  • the consumer's Composer dependency may be pinned to a released fast-forward/dev-tools version;
  • the consumer's copied workflow wrapper may still point to reusable workflows on @main;
  • the reusable workflow may checkout local action implementations from main;
  • the action implementation may expect PHP classes, scripts, files, or command behavior that only exist on main, not in the consumer's installed release.

The result can be hard-to-debug CI anomalies where the workflow logic and the package code are from different points in time.

Current Surfaces

Examples of the current pattern:

  • resources/github-actions/tests.yml calls php-fast-forward/dev-tools/.github/workflows/tests.yml@main.
  • resources/github-actions/changelog.yml calls php-fast-forward/dev-tools/.github/workflows/changelog.yml@main.
  • resources/github-actions/reports.yml, wiki.yml, wiki-maintenance.yml, review.yml, auto-assign.yml, and label-sync.yml follow the same wrapper model.
  • reusable workflows then checkout .github/actions into .dev-tools-actions, commonly resolving php-fast-forward/dev-tools at main for consumer repositories.
  • docs currently describe the sparse checkout model, but do not define a release/version contract for which ref should be used.

Proposed Direction

Define and implement a versioning policy for consumer-facing reusable workflows and the local action source they checkout.

This issue should evaluate at least these approaches:

  1. Pin action checkout refs to the latest published release

    • Reusable workflows could checkout .github/actions at the same released tag as the reusable workflow ref.
    • This reduces unreleased action drift, but we need a reliable way to know the intended ref from inside the workflow.
  2. Pin consumer wrappers to released tags instead of @main

    • resources/github-actions/*.yml could be rendered with a concrete @vX.Y.Z ref during release or sync.
    • Dependabot could then manage workflow updates in consumers similarly to dependency updates.
    • Release automation would need to guarantee wrappers are updated consistently when a new DevTools release is prepared.
  3. Keep wrappers on @main, but pin only .github/actions checkout

    • This reduces action-source drift while preserving central reusable workflow updates.
    • It still leaves reusable workflow YAML on main, so it may not fully solve version skew.
  4. Expose a workflow input for dev-tools-ref

    • Consumer wrappers could pass dev-tools-ref explicitly.
    • Defaults could remain main for development, but generated consumer wrappers could use a release tag.
    • This may be the most flexible route, but it requires touching every reusable workflow that checks out .github/actions.
  5. Release-managed wrapper regeneration

    • During release preparation, update resources/github-actions/*.yml to point at the release tag that is about to be published.
    • Ensure the packaged/synchronized workflow wrappers and docs explain how consumers receive updates.
    • Evaluate whether Dependabot should be configured to raise PRs when these uses: php-fast-forward/dev-tools/...@vX.Y.Z references lag behind.

Implementation Strategy

Start with a design pass before changing every workflow:

  • inventory every consumer wrapper under resources/github-actions/ and every reusable workflow under .github/workflows/ that sparse-checks out .github/actions;
  • decide whether the authoritative ref should be main, latest release tag, Composer package version, or an explicit wrapper input;
  • define how release automation updates the chosen ref;
  • define how consumer repositories receive and update that ref through dev-tools:sync and/or Dependabot;
  • update documentation so the release/version contract is explicit;
  • only then apply the workflow changes consistently.

Requirements

  • Consumer repositories MUST NOT unexpectedly execute unreleased .github/actions implementations when their wrappers are intended to represent a released DevTools version.
  • The selected policy MUST be consistent across all packaged workflow wrappers, not only one workflow.
  • Reusable workflows that checkout .github/actions MUST use a deterministic ref that matches the selected policy.
  • Release automation MUST keep generated wrappers, reusable workflow refs, and documentation aligned.
  • The solution SHOULD preserve a convenient development path for this repository's own PRs, where workflows need to test in-branch changes before release.
  • The solution SHOULD explain how Dependabot or another automation will update workflow refs in consumers if the final design uses versioned tags.
  • The solution MUST avoid requiring consumers to manually edit every workflow after each DevTools release.

Open Questions

  • Should consumer wrappers point at @main, immutable release tags such as @v1.21.0, or a moving major/minor tag such as @v1?
  • If wrappers use release tags, should dev-tools:sync rewrite them to the installed Composer package version or to the latest known upstream release?
  • Can Dependabot reliably update reusable workflow references that point to php-fast-forward/dev-tools/.github/workflows/*.yml@vX.Y.Z?
  • Should .github/actions checkout use the same ref as the reusable workflow, or should it have an independent input/default?
  • How do we handle this repository's own workflows so PRs can still validate unreleased action changes before those actions are tagged?
  • Should release preparation fail if packaged workflow wrappers still point to @main or to a stale release ref?

Non-goals

  • Redesigning the workflow architecture unrelated to version/ref consistency.
  • Removing reusable workflows or going back to copying full workflow implementations into every consumer.
  • Solving arbitrary consumer workflow customization drift in the same change.

Acceptance Criteria

Functional Criteria

  • The repository has a documented versioning policy for consumer workflow wrappers and .github/actions checkout refs.
  • All packaged consumer wrappers under resources/github-actions/ follow the chosen policy consistently.
  • All reusable workflows that checkout .github/actions use the selected deterministic ref strategy.
  • Release preparation or validation detects stale or unintended workflow refs before publication.
  • Consumer update behavior is documented, including whether updates happen through dev-tools:sync, Dependabot, release automation, or a combination.
  • This repository can still validate unreleased workflow/action changes safely in its own PRs.

Regression Criteria

  • Add workflow/static validation coverage or command-level tests that catch accidental @main usage where the selected policy forbids it.
  • Add documentation coverage for the chosen policy in the GitHub Actions or consumer sync docs.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    Status

    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions