You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Port the two-phase CI/CD pattern just implemented in ProjectTemplate (ptr727/ProjectTemplate#97 → #98, merged to develop) into PlexCleaner. This issue captures exactly what was done there so the work can continue here. PlexCleaner's workflow layout is essentially identical to ProjectTemplate's pre-change layout, so the port is mostly mechanical — minus PyPI (PlexCleaner has no PyPI library; its targets are the Docker image and the console executable 7-runtime build).
Goal
Decouple merging from publishing. PRs get fast, path-gated smoke builds; the full multi-arch build/publish moves to a weekly schedule + manual dispatch, with an opt-in switch for publish-on-merge.
Target architecture (mirror of ProjectTemplate #98)
Thread ref / branch / smoke through every reusable task. Branch-derived config (main ⇒ Release/latest, else Debug/develop/prerelease) must key off inputs.branch, never github.ref_name — the weekly publisher builds both branches from one run. get-version-task.yml gains a ref input.
smoke mode: Docker builds linux/amd64 only (skip QEMU); executable builds a representative runtime subset (e.g. linux-x64 + win-x64) instead of the full 7; nothing pushes.
build-release-task.yml: add smoke, ref, branch, and per-target enable_* gates. smoke hard-disables every push (&& !inputs.smoke).
test-pull-request.yml: add a dorny/paths-filterchanges job (needs permissions: pull-requests: read), gate per-target smoke jobs on it, keep unit tests always-on, and extend the check-workflow-status aggregator to require the changes job succeeded (so a filter error can't merge a target-changing PR with its smoke skipped). Build-workflow files are intentionally excluded from filters.
publish-release.yml: become the single publisher — push + weekly schedule + workflow_dispatch. A setup job computes the branch list (schedule/dispatch ⇒ both branches, push ⇒ the pushed branch) and a publish gate github.event_name != 'push' || vars.PUBLISH_ON_MERGE == 'true'. Build both branches via a matrix. Absorb publish-periodic-docker-release.yml (delete it). Use a global concurrency group (group: ${{ github.workflow }}, not ref-scoped) + cancel-in-progress: false.
Consolidation: fold unit tests into the PR workflow and delete test-release-task.yml. Default PUBLISH_ON_MERGE unset ⇒ two-phase.
Refinements discovered during the ProjectTemplate Copilot review — bake these in from the start
These were review findings on #98; apply them directly so PlexCleaner doesn't repeat them:
Make branch a required input on every task (no ${{ github.ref_name }} default — it's a footgun that would mislabel the develop leg of the matrix).
Check out the PR head by SHA in the smoke job: ref: ${{ github.event.pull_request.head.sha || github.ref_name }} (works for fork PRs; head_ref does not).
Branch-suffix all upload-artifact names (executable-build-${branch}, per-runtime publish-${branch}-${runtime}, etc.) so both matrix legs coexist in one run without collisions. (PlexCleaner uploads the executable 7z, so this matters; the GitHub release downloads by artifact-id which is unaffected.)
Branch-scope the Docker registry cache (buildcache-${branch}, read both branches, write own) and gate cache-to on inputs.push (non-publishing builds never write cache or need write creds).
Gate the github-release job on && !inputs.smoke so smoke can never create a release.
Pin the release target_commitish to NBGV GitCommitId (immutable, right branch) instead of github.sha (wrong on the develop leg) or a branch name (moving ref). Surface GitCommitId as a get-version output.
Docker Hub login: ProjectTemplate consciously keeps always-login (private repo, higher pull rate limits) and documents the trade-off (fork PRs can't run the Docker smoke). Decide per PlexCleaner's visibility — gating login on inputs.push is the alternative.
Linting stays editor/workspace + commit gate — no CI lint job. Don't claim actionlint runs in CI; lint workflows locally before pushing.
CodeGen cadence: if PlexCleaner has scheduled codegen, move it to daily (cheap under two-phase).
PlexCleaner-specific notes
Targets are Docker + executable only (no NuGet/PyPI) — drop those enable_*/jobs/filters.
PlexCleaner currently has a redundant merge-time Docker build (built non-pushed in the release path, pushed in the periodic workflow). The unified publisher removes that duplication.
Consider whether develop mutable-tag republishing on routine merges should stop (it does under two-phase by default).
Per-target modularity + the subsetting checklist should be documented in PlexCleaner's AGENTS.md, same as ProjectTemplate.
Port the two-phase CI/CD pattern just implemented in ProjectTemplate (ptr727/ProjectTemplate#97 → #98, merged to
develop) into PlexCleaner. This issue captures exactly what was done there so the work can continue here. PlexCleaner's workflow layout is essentially identical to ProjectTemplate's pre-change layout, so the port is mostly mechanical — minus PyPI (PlexCleaner has no PyPI library; its targets are the Docker image and the console executable 7-runtime build).Goal
Decouple merging from publishing. PRs get fast, path-gated smoke builds; the full multi-arch build/publish moves to a weekly schedule + manual dispatch, with an opt-in switch for publish-on-merge.
Target architecture (mirror of ProjectTemplate #98)
ref/branch/smokethrough every reusable task. Branch-derived config (main⇒ Release/latest, else Debug/develop/prerelease) must key offinputs.branch, nevergithub.ref_name— the weekly publisher builds both branches from one run.get-version-task.ymlgains arefinput.smokemode: Docker buildslinux/amd64only (skip QEMU); executable builds a representative runtime subset (e.g.linux-x64+win-x64) instead of the full 7; nothing pushes.build-release-task.yml: addsmoke,ref,branch, and per-targetenable_*gates.smokehard-disables every push (&& !inputs.smoke).test-pull-request.yml: add adorny/paths-filterchangesjob (needspermissions: pull-requests: read), gate per-target smoke jobs on it, keep unit tests always-on, and extend thecheck-workflow-statusaggregator to require thechangesjob succeeded (so a filter error can't merge a target-changing PR with its smoke skipped). Build-workflow files are intentionally excluded from filters.publish-release.yml: become the single publisher —push+ weeklyschedule+workflow_dispatch. A setup job computes the branch list (schedule/dispatch ⇒ both branches, push ⇒ the pushed branch) and a publish gategithub.event_name != 'push' || vars.PUBLISH_ON_MERGE == 'true'. Build both branches via a matrix. Absorbpublish-periodic-docker-release.yml(delete it). Use a global concurrency group (group: ${{ github.workflow }}, not ref-scoped) +cancel-in-progress: false.test-release-task.yml. DefaultPUBLISH_ON_MERGEunset ⇒ two-phase.Refinements discovered during the ProjectTemplate Copilot review — bake these in from the start
These were review findings on #98; apply them directly so PlexCleaner doesn't repeat them:
brancha required input on every task (no${{ github.ref_name }}default — it's a footgun that would mislabel the develop leg of the matrix).ref: ${{ github.event.pull_request.head.sha || github.ref_name }}(works for fork PRs;head_refdoes not).executable-build-${branch}, per-runtimepublish-${branch}-${runtime}, etc.) so both matrix legs coexist in one run without collisions. (PlexCleaner uploads the executable 7z, so this matters; the GitHub release downloads by artifact-id which is unaffected.)buildcache-${branch}, read both branches, write own) and gatecache-tooninputs.push(non-publishing builds never write cache or need write creds).github-releasejob on&& !inputs.smokeso smoke can never create a release.gh release view "$SemVer2") — weekly no-op weeks shouldn't churn/fail the release. (Same fix filed for NxWitness: Publisher: skip duplicate GitHub release on no-op weeks and pin release tag to the built commit SHA NxWitness#407.)target_commitishto NBGVGitCommitId(immutable, right branch) instead ofgithub.sha(wrong on the develop leg) or a branch name (moving ref). SurfaceGitCommitIdas a get-version output.inputs.pushis the alternative.actionlintruns in CI; lint workflows locally before pushing.PlexCleaner-specific notes
enable_*/jobs/filters.developmutable-tag republishing on routine merges should stop (it does under two-phase by default).Reference
publish-release.yml+test-pull-request.yml).🤖 Filed by Claude Code; ready to continue the work directly in PlexCleaner.