Skip to content

Extending the reusable test-suite workflow in heavily-customized downstreams (e.g. setuptools) #211

Open

Description

@jaraco

Background

#199 factored the shared test/collateral setup into a reusable test-suite.yml (reusable workflows having been chosen over composite actions per the discussion in #162 / #163). For most consumers this is a clear win: main.yml shrinks to thin uses: calls, and the shared steps + env live in one place.

For heavily-customized downstreams it's a harder fit. setuptools is the motivating case. Its test job interleaves a lot of project-specific work with the shared steps:

  • pre-building the sdist/wheel and exporting PRE_BUILT_SETUPTOOLS_*
  • a cached download of setupcfg examples
  • SETUPTOOLS_USE_DISTUTILS and a pypy continue-on-error
  • publishing coverage

Plus two jobs that can't use the reusable workflow at all: test_cygwin (every step runs under a Cygwin bash shell) and integration (separate, tag-gated).

The friction

  1. You can't inject steps into a reusable workflow. A calling job may only set uses/with/secrets/needs/if/strategy/permissions — never steps. So setuptools can't "call the shared workflow and add its pre-build steps"; the custom steps have nowhere to live in the caller.

  2. So the only way to keep the pattern is to fork test-suite.yml and add the project steps there, gated by an input (setuptools uses a full-test flag). But that customizes the skeleton's own shared file — the one the skeleton will keep iterating on — so every future skeleton update to test-suite.yml now conflicts. It inverts the usual "customize main.yml, inherit test-suite.yml" contract.

  3. Env can't be shared with decoupled jobs. A called reusable workflow doesn't inherit the caller's top-level env:, and test_cygwin/integration can't call it, so the shared env block (FORCE_COLOR, PIP_*, TOX_OVERRIDE) ends up duplicated across test-suite.yml and each decoupled job.

setuptools' current resolution (in the pending skeleton merge) is Option-D-style: a forked test-suite.yml with a full-test input gating the setuptools-specific steps, and test_cygwin/integration decoupled with duplicated env. It works, but it accepts (2) and (3).

Question

Could the skeleton offer extension points so a downstream can customize without forking test-suite.yml? A couple of directions:

  • Convention hooks — test-suite.yml runs a downstream-provided script at a well-known path if it exists (e.g. a pre-tox ./.github/pre-test and/or a post-tox hook). Degenerate/no-op by default; setuptools would move its pre-build / download-cache logic into such a script, keeping test-suite.yml upstream-pristine.
  • Composite actions for the genuinely shared concerns (setup-python + tox; publish-coverage) that both test-suite.yml and decoupled jobs like test_cygwin could call — which would also address the env/coverage duplication in (3). (Acknowledging the composite-action tradeoffs already raised in tests and collateral share some behavior implicitly #162 — collapsed/ugly log output in particular.)

Curious whether hooks, composites, or "downstreams just fork test-suite.yml and own it" is the intended story for cases like setuptools.

Activity

  1. jaraco commented on Aug 2, 2026

    @jaraco
    OwnerAuthor

    Recording an analysis + recommendation here to shelve for later; setuptools has landed the Option-D workaround (forked test-suite.yml with a full-test input; test_cygwin/integration decoupled with duplicated env).

    Residual duplication in Option D as shipped

    Concern Copies
    env vars (FORCE_COLOR/PIP_*/TOX_OVERRIDE) 3 — test-suite.yml, test_cygwin, integration
    coverage-publish (codecov step) 2 — test-suite.yml, test_cygwin
    custom setup (pre-build, download cache) forks the skeleton's test-suite.yml

    Three levers, and what each can/can't do

    1. Pre/post-test hooks in test-suite.yml — run a downstream script at a well-known path if present (if hashFiles('.github/pre-test.sh')). setuptools moves its shell setup there (pre-build, downloads.preload, echo SETUPTOOLS_USE_DISTUTILS >> $GITHUB_ENV). Keeps test-suite.yml un-forked → clean future merges. Limit: hooks are shell only, so action-based steps — setuptools' actions/cache restore, and job-level continue-on-error — can't move into a script. Hooks shrink the fork but don't fully remove it.

    2. A publish-coverage composite action used by both test-suite.yml and decoupled jobs like test_cygwin. This is a single action-wrapping step, exactly the composite use-case endorsed in tests and collateral share some behavior implicitly #162 — so it dodges the collapsed/ugly-log objection to multi-step composites, and it dedupes coverage across the reusable path and Cygwin. I'd recommend this one regardless.

    3. Env is the stubborn one. A called reusable workflow can't inherit the caller's env:, a composite can't cleanly set job-level env, and decoupled jobs can't call the reusable workflow — so the only true single source across all of them is repo-level vars.* (config in GitHub settings, less visible/portable). Otherwise the duplication for test_cygwin/integration is irreducible in-repo.

    Recommendation (mostly skeleton-side)

    • Skeleton adds a publish-coverage composite (lever 2) and a pre-test hook in test-suite.yml (lever 1).
    • Downstreams move shell setup into the hook script, use the coverage composite in both the reusable path and decoupled jobs, and keep only what genuinely can't be hooked (actions/cache + continue-on-error) as a much smaller test-suite.yml delta.
    • Accept env duplication for the decoupled jobs, or adopt vars.* if it must go.

    The two underlying platform gaps are already tracked upstream (no new reports filed):

    Shelving the implementation here for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions