Skip to content

Host Get-Version and Publish-Plan as Hub Reusable Tasks - #759

Merged
ptr727 merged 3 commits into
developfrom
feature/pure-function-tasks
Aug 16, 2026
Merged

Host Get-Version and Publish-Plan as Hub Reusable Tasks#759
ptr727 merged 3 commits into
developfrom
feature/pure-function-tasks

Conversation

@ptr727

@ptr727 ptr727 commented Aug 16, 2026

Copy link
Copy Markdown
Owner

Stage 3 of the hub-hosted reusable-workflow rollout (docs/reusable-workflows.md
"Rollout"). Hosts get-version-task.yml and publish-plan-task.yml in the hub's
.github/workflows/, moved out of catalog/snippets/workflows/.

What moved

  • get-version-task.yml: the catalog canonical, with action pins updated to the
    hub's current actions/checkout@...v7.0.1 and actions/setup-dotnet@...v6.0.0
    (the catalog copy had fallen behind what the hub's own publish-release.yml
    already runs). Read against the 8 downstream copies (ESPHome-NonRoot, NxWitness,
    PhotoCleaner, PlexCleaner, VSCode-Server-DotNetCore, KiCadLibrary, aiopurpleair,
    homeassistant-purpleair): 5 are byte-identical to the canonical, KiCadLibrary only
    documents the same design, and aiopurpleair and homeassistant-purpleair each add a
    Prerelease output derived from SemVer2 with identical logic (SemVer2 contains
    a - segment). That derivation is a real, duplicated improvement, so it is hosted
    as a sixth output on the task rather than left as per-repo logic. Homeassistant's
    Tag output is not carried forward, since it is a bare copy of SemVer2 with no
    derivation of its own, and a caller can read SemVer2 directly.
  • publish-plan-task.yml: the catalog canonical, unchanged in behavior. All 3
    downstream copies (ESPHome-NonRoot, NxWitness, Utilities) are a strict subset of
    it, missing the -E in set -Eeuo pipefail and the ::warning:: branch for an
    unrecognized actor pushing to main (WORKFLOW.md D8.4), so nothing from the
    copies is folded in.

Neither task nests the other, and neither is called from a hub ./ path in this
PR: build-release-task.yml (stage 4, a sibling agent's PR) inlines the
get-version and validate-release jobs rather than nesting a sibling hub task, per
the design's no-./-nesting rule. A downstream publish-release.yml stub that
reads version outputs directly, without carrying the whole release orchestrator,
calls get-version-task.yml by pin instead. Both shapes are documented in the new
"Adopting the Pure Functions" section of docs/reusable-workflows.md, with
placeholder pins (@<hub-main-commit-sha> # <release-tag>) since no release has
carried these tasks yet.

Manifest and audit

Per the brief, no interface contract is added to spec/files.json for either
task: they are hub-only files with no caller-stub filename convention of their
own (a caller reaches them as a job inside its own publish-release.yml or
build-release-task.yml, not a standalone top-level workflow), so there is no
downstream stub shape to check today. spec/audit.py's check_interface
selftest set is unchanged for the same reason.

Confirmed the manifest-gap mechanics will do what is expected once this merges:
spec/audit.py's hub_only_paths is the hub's own git ls-files output minus
spec/files.json's baseline paths, so .github/workflows/get-version-task.yml
and .github/workflows/publish-plan-task.yml join that set the moment they land
here undeclared in the manifest. spec/fidelity_honesty.py's manifest_gap_pass
then walks every cataloged repo's ground-truth tree and reports one whose tree
still contains either path as a gap naming that repo, which is exactly how a
downstream copy left over after this PR would surface once the fleet-wide report
runs. spec/divergences.json gains two retire gap dispositions, one per path,
naming the current carriers so the burn-down report reads as tracked rather than
UNTRIAGED. python3 spec/validate.py accepts them (spec/divergences.schema.json
has no repos field on a gap entry, so carriers are named in the reason text
instead, matching the ledger's existing prose style).

scripts/prose_lint.py's HUB_HOSTED literal (which exempts a hub-hosted path
from the dead-path check once a downstream repo retires its own copy) gained both
new paths, since scripts/tests/test_prose_lint.py's
test_the_hub_hosted_set_matches_the_ledger asserts that set equals every
retire gap path in the ledger.

Not run live

Per the brief, the live fleet report
(python3 spec/fidelity_honesty.py --report) was not run in this PR, since it
reads every cataloged repo over the network and is not guaranteed to finish
quickly. The two new ledger entries were checked structurally instead: spec/ validate.py accepts the schema, and spec/audit.py --selftest's
hub-only set excludes every declared path case (184 hub-hosted paths now, up
from 182) confirms the two new paths are read into hub_only_paths as expected.
reports/workflow-reuse.md is not regenerated here either, per the Rollout
section's rule that regeneration happens in the PR that ticks a stage's last
adoption, not the hub PR.

Tracker

  • docs/reusable-workflows.md "Rollout" Stage 3: ticked the hub pull request
    item with this PR, expanded the single adoption line into one checkbox per
    carrier (9 repos, with ESPHome-NonRoot and NxWitness carrying both files), and
    added a catalog-snippet follow-up item concluding that no snippet is warranted
    today since a caller of either task is a job inside a larger stub.
  • TODO.md "Hub-Hosted Reusable Workflows" pure-functions bullet: added Settled
    lines recording the fleet reading above.

Gates run

spec/validate.py, unittest discover -s scripts/tests (686 tests), spec/ audit.py --selftest, spec/workflow_reuse.py --selftest, scripts/repo_gate.py,
scripts/build_dist.py --check, scripts/prose_lint.py with the named checks,
ruff check/ruff format --check, mypy, and the Docker actionlint,
markdownlint-cli2, and editorconfig-checker invocations (the last flags only
.git, .mypy_cache, .ruff_cache). All pass.

🤖 Generated with Claude Code

Copilot AI lite review requested due to automatic review settings August 16, 2026 03:36
ptr727 added a commit that referenced this pull request Aug 16, 2026
docs/reusable-workflows.md Rollout tracker only, per the PR being its own evidence.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Stages reusable “pure function” GitHub Actions tasks in the hub by moving get-version-task.yml and publish-plan-task.yml into .github/workflows/ for downstream reuse via pinned uses:, and updates the fleet’s retirement ledger and documentation to track/drive adoption.

Changes:

  • Add hub-hosted reusable workflow .github/workflows/get-version-task.yml (including a derived Prerelease output) and update the existing publish-plan-task.yml header comment.
  • Retire downstream copies via new retire gap entries in spec/divergences.json and align scripts/prose_lint.py’s HUB_HOSTED set with those retirements.
  • Update rollout/adoption docs and remove the catalog snippet copy of get-version-task.yml.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
TODO.md Records settled findings about downstream divergence analysis for the two tasks.
spec/divergences.json Adds retire gap entries for the two newly hub-hosted workflows.
scripts/prose_lint.py Extends HUB_HOSTED exemptions to include the newly hub-hosted workflow paths.
docs/reusable-workflows.md Adds “Adopting the Pure Functions” section and expands Stage 3 adoption tracking.
catalog/snippets/workflows/README.md Updates snippet catalog prose/table to describe hub-hosted tasks (needs a path fix per review comment).
catalog/snippets/workflows/get-version-task.yml Removes the catalog copy now hosted in .github/workflows/.
.github/workflows/publish-plan-task.yml Updates header comment to reflect hub-hosted reuse.
.github/workflows/get-version-task.yml New hub-hosted reusable task with updated action pins and Prerelease derivation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread catalog/snippets/workflows/README.md Outdated
Copilot AI review requested due to automatic review settings August 16, 2026 03:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (2)

catalog/snippets/workflows/README.md:10

  • This table lists get-version-task.yml / publish-plan-task.yml as bare filenames, but those files were moved out of catalog/snippets/workflows/ and now live under .github/workflows/. Listing them as bare names is likely to be read as “present in this snippets directory” and makes the table misleading. Consider using the full repo-relative paths for these two hub-hosted tasks.
| `get-version-task.yml` | Hub-hosted and reached by pin from a leaf or publisher rather than carried, with no caller-stub snippet since it is called as a job inside a larger stub, per [`docs/reusable-workflows.md`][reusable-workflows] | D3 |
| `publish-plan-task.yml` | Hub-hosted and reached by pin from every publish-release job rather than carried, with no caller-stub snippet since it is called as a job inside a larger stub, per [`docs/reusable-workflows.md`][reusable-workflows] | D4 |

.github/workflows/get-version-task.yml:97

  • Prerelease detection checks SemVer2 for any - without stripping SemVer2 build metadata (+...). This can misclassify stable versions that include build metadata containing - (SemVer2 allows hyphens in build metadata), and it diverges from the existing validate-release logic which strips +... before testing for -. Strip build metadata first and test the core+prerelease segment only.
          set -Eeuo pipefail
          if [[ "$SEMVER2" == *-* ]]; then
            PRERELEASE=true
          else
            PRERELEASE=false
          fi

Copilot AI review requested due to automatic review settings August 16, 2026 03:45
@ptr727

ptr727 commented Aug 16, 2026

Copy link
Copy Markdown
Owner Author

Replies to the two suppressed findings from the round on bce9930:

catalog/snippets/workflows/README.md:10
This table lists get-version-task.yml / publish-plan-task.yml as bare filenames, but those files were moved out of catalog/snippets/workflows/ and now live under .github/workflows/. Listing them as bare names is likely to be read as "present in this snippets directory" and makes the table misleading. Consider using the full repo-relative paths for these two hub-hosted tasks.

Accepted. Fixed in a4822cb: both rows now name the full .github/workflows/ path instead of a bare filename.

.github/workflows/get-version-task.yml:97
Prerelease detection checks SemVer2 for any - without stripping SemVer2 build metadata (+...). This can misclassify stable versions that include build metadata containing - (SemVer2 allows hyphens in build metadata), and it diverges from the existing validate-release logic which strips +... before testing for -. Strip build metadata first and test the core+prerelease segment only.

Accepted. Fixed in a4822cb: the step now strips +buildmetadata first (CORE_AND_PRE="${SEMVER2%%+*}"), matching validate-release's existing logic, before testing for a prerelease -.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Suppressed comments (1)

catalog/snippets/workflows/README.md:3

  • The sentence "Each file below" is misleading now that the table includes hub-hosted workflows under .github/workflows/ (not files located in catalog/snippets/workflows/). Reword to describe the table entries/workflows rather than implying everything listed is a snippet file in this directory.
The reusable build/publish workflow tasks a code-shipping repo runs. They are **inert reference here**: this repo is source-only and keeps just the orchestrator set (`test-pull-request`, `publish-release`, `validate-task`, `merge-bot-pull-request`) in `.github/workflows/`, plus the hub-hosted reusable tasks a downstream repo reaches rather than carries (`merge-bot-task`, `get-version-task`, `publish-plan-task`, per [`docs/reusable-workflows.md`][reusable-workflows]). Each file below is the canonical implementation of one or more `WORKFLOW.md` guarantees. The audit asserts a downstream repo's own Actions satisfy those guarantees, not that they match these bytes.

Copilot AI review requested due to automatic review settings August 16, 2026 03:50
@ptr727

ptr727 commented Aug 16, 2026

Copy link
Copy Markdown
Owner Author

Reply to the suppressed finding from the round on a4822cb:

catalog/snippets/workflows/README.md:3
The sentence "Each file below" is misleading now that the table includes hub-hosted workflows under .github/workflows/ (not files located in catalog/snippets/workflows/). Reword to describe the table entries/workflows rather than implying everything listed is a snippet file in this directory.

Accepted. Fixed in 34c5eb2: the sentence now reads "Each row below names the canonical implementation of one or more WORKFLOW.md guarantees, whether the file lives in this directory or is hub-hosted and reached by pin."

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

ptr727 added 2 commits August 16, 2026 06:07
Move get-version-task.yml and publish-plan-task.yml from catalog/snippets/workflows/
into the hub's .github/workflows/, per docs/reusable-workflows.md stage 3.

get-version-task.yml keeps the five canonical outputs and adds Prerelease, a
derivation two live callers (aiopurpleair, homeassistant-purpleair) duplicated
identically, hosted here rather than as per-repo logic. publish-plan-task.yml
carries the canonical unchanged, since every downstream copy is a strict subset
missing the -E pipefail flag and the unrecognized-actor warning branch.

Neither task nests the other or a future build-release-task.yml, per the
no-./-nesting rule; a caller that needs only the version reaches get-version-task.yml
directly, documented in the new docs/reusable-workflows.md 'Adopting the Pure
Functions' section with placeholder pins.

spec/divergences.json gains retire gap dispositions for both paths naming their
carriers, and scripts/prose_lint.py's HUB_HOSTED set is kept in sync per its own
test. catalog/snippets/workflows/README.md rows now describe both as hub-hosted.
Strip SemVer2 build metadata before testing for a prerelease '-' in
get-version-task.yml, matching validate-release's existing CORE_AND_PRE logic,
so a stable version whose build metadata happens to contain a hyphen is no
longer misclassified as a prerelease.

catalog/snippets/workflows/README.md now names the two hub-hosted rows by
their full .github/workflows/ path, since a bare filename in this directory's
table reads as present in the snippets tree.
@ptr727
ptr727 force-pushed the feature/pure-function-tasks branch from 34c5eb2 to 0507837 Compare August 16, 2026 13:09
Copilot AI review requested due to automatic review settings August 16, 2026 13:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

ptr727 added a commit that referenced this pull request Aug 16, 2026
Fail fast in docker-prepare-default when the image input is empty, note the
hub's own outcome-preserving use of build-release-task.yml as a source-only
release path in WORKFLOW.md, and track the hub's own missing plan job as an
Open item pending #759.
ptr727 added a commit that referenced this pull request Aug 16, 2026
Fail fast in docker-prepare-default when the image input is empty, note the
hub's own outcome-preserving use of build-release-task.yml as a source-only
release path in WORKFLOW.md, and track the hub's own missing plan job as an
Open item pending #759.
…ion-tasks

# Conflicts:
#	docs/reusable-workflows.md
Copilot AI review requested due to automatic review settings August 16, 2026 14:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

@ptr727
ptr727 merged commit 7a81264 into develop Aug 16, 2026
6 checks passed
@ptr727
ptr727 deleted the feature/pure-function-tasks branch August 16, 2026 14:34
ptr727 added a commit that referenced this pull request Aug 16, 2026
Fail fast in docker-prepare-default when the image input is empty, note the
hub's own outcome-preserving use of build-release-task.yml as a source-only
release path in WORKFLOW.md, and track the hub's own missing plan job as an
Open item pending #759.
ptr727 added a commit that referenced this pull request Aug 16, 2026
Now that publish-plan-task.yml is hosted on develop (#759), the hub's own
publish-release.yml gains the plan job the interface contract in
spec/files.json always required, resolving the tracked gap this stage
had documented instead of carrying it forward.
ptr727 added a commit that referenced this pull request Aug 16, 2026
Copilot review on c1dadd1: the merge with #759 (get-version-task.yml,
publish-plan-task.yml) rows added a claim that the table names the
canonical implementation whether a file lives here or is hub-hosted,
but the four stage-5 type-specific tasks are hub-hosted with no row,
since their own caller-stub snippet returns only after each task's
release per the paragraph beneath it. Names the four explicitly rather
than leaving the coverage claim to read as complete.
ptr727 added a commit that referenced this pull request Aug 16, 2026
… Default (#768)

Promote `develop` to `main`, carrying the remaining stages of the
hub-hosted reusable-workflow rollout and the changes that landed beside
them:

- #759 Host Get-Version and Publish-Plan as Hub Reusable Tasks
- #760 Host the Validate Task and Reshape the Test Pull Request Stub
(settles #729 by design: the hub's validate task runs `uvx
<tool>@latest`, since Dependabot tracks the action pins and not a uvx
version)
- #761 Host the Type-Specific Tasks and Retire the Date Badge
- #762 Host the Release Chain and the Docker Core in the Hub
- #748 and #752, the staged rollout tracker and the PhotoCleaner
merge-bot pilot record
- #758 Flip the Fleet Line-Ending Default from CRLF to LF
- #753, #755, #756, #764, host-setup and test-collection changes

The release that follows this promotion is the first tag carrying every
hub task, so it is the pin the stage 2 to 5 adoptions and their catalog
snippets use. It is also the first run of the hub's own
`publish-release.yml` through `build-release-task.yml` with every target
disabled, which is the live proof that `github-release` runs when its
build needs are skipped.

Closes #729.
Refs #521 (hub half shipped, the merge-bot adoption sweep is what
remains).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants