Skip to content

Adopt two-phase CI/CD with PR smoke builds and opt-in publish - #98

Merged
ptr727 merged 11 commits into
developfrom
feature/97-two-phase-cicd
Jun 3, 2026
Merged

Adopt two-phase CI/CD with PR smoke builds and opt-in publish#98
ptr727 merged 11 commits into
developfrom
feature/97-two-phase-cicd

Conversation

@ptr727

@ptr727 ptr727 commented Jun 3, 2026

Copy link
Copy Markdown
Owner

Closes #97.

What

Decouple merging from publishing across all four delivery targets (Docker, NuGet, PyPI, console executable).

  • Two-phase by default. PRs run unit tests plus a path-gated smoke build of only the changed targets (Docker linux/amd64 only, reduced executable matrix, no push). Merges to main/develop no longer publish.
  • Sole publisher. publish-release.yml (weekly schedule + manual dispatch) builds and publishes both branches in one run via a branch matrix; its push trigger publishes only when the PUBLISH_ON_MERGE repository variable is true (opt-in legacy continuous-release).
  • Parameterized chain. ref/branch/smoke are threaded through every reusable task; branch-derived config keys off inputs.branch, never github.ref_name, so a scheduled run can version/build develop as well as main. get-version-task.yml gained a ref input.
  • Collision/cache safety for the matrix. Build artifacts are branch-suffixed and the Docker registry cache is branch-scoped (buildcache-main/buildcache-develop, reads both, writes own) so the two legs never collide or overwrite each other's cache.
  • Required check hardened. The aggregator fails if the paths-filter job fails, so a target-changing PR can't merge with its smoke build silently skipped.
  • Consolidation. CodeGen weekly → daily; unit tests folded into the PR workflow; test-release-task.yml and publish-periodic-docker-release.yml removed.
  • Per-target modularity. Self-contained leaf tasks + enable_* gates so a derived project can drop a target with minimal edits (checklist in AGENTS.md).

Copilot runbook

Corrects .github/copilot-instructions.md: the requestReviews GraphQL mutation now reliably re-requests a review (previously documented as non-working / manual-UI-only), and the wait-for-maintainer-merge gate is now explicit in AGENTS.md.

Notes

  • .NET NuGet restore caching is intentionally left off (low overhead, no lock files under Central Package Management) — documented inline.
  • Default flips the template's prior "publish on every push" identity to two-phase; docs (README/AGENTS.md) updated accordingly.

🤖 Generated with Claude Code

Decouple merging from publishing (issue #97). By default, PRs run
path-gated smoke builds (Docker amd64-only, reduced executable matrix,
no push) and merges to main/develop no longer publish; the weekly
schedule and manual dispatch are the sole publishers, building and
releasing both branches in one run via a branch matrix. Set the
PUBLISH_ON_MERGE repository variable to true to opt back into legacy
publish-on-every-merge.

Thread ref/branch/smoke through every reusable build task so branch-
derived config keys off inputs.branch (not github.ref_name), letting a
scheduled run version and build develop as well as main. Add per-target
enable gates and a paths-filter changes job for fast, modular PR
feedback; the required status aggregator now fails if path detection
fails so a target-changing PR cannot merge with its smoke build skipped.
Branch-suffix build artifacts and branch-scope the Docker registry cache
so the two matrix legs do not collide or overwrite each other's cache.

Move codegen from weekly to daily, fold unit tests into the PR workflow,
and remove the now-redundant test-release-task and
publish-periodic-docker-release workflows.

Correct the Copilot review runbook: the requestReviews GraphQL mutation
now reliably re-requests a review (previously needed a manual UI click),
and make the wait-for-maintainer-merge gate explicit.
Copilot AI review requested due to automatic review settings June 3, 2026 21:49

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

This PR restructures the template’s CI/CD into a two-phase model: pull requests run fast, path-gated smoke builds, while publishing is batched into a scheduled/manual workflow with an opt-in “publish on merge” switch.

Changes:

  • Replaces the PR validation workflow with unit tests + path-gated smoke builds of only the affected delivery targets.
  • Refactors publishing so publish-release.yml becomes the central publisher (weekly + manual), with push-triggered publishing gated by PUBLISH_ON_MERGE.
  • Threads ref/branch/smoke through reusable build workflows to support a branch matrix (publishing main and develop in one run) and avoid artifact/cache collisions.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
README.md Updates documentation to describe the new two-phase model and codegen schedule.
ProjectTemplate.slnx Removes deleted workflow files from solution items.
AGENTS.md Adds authoritative “Release Model” section and updates review-loop guidance.
.github/workflows/test-release-task.yml Removes the prior “test release” reusable workflow.
.github/workflows/test-pull-request.yml Implements PR path detection + smoke build orchestration + hardened required-check aggregator.
.github/workflows/run-periodic-codegen-pull-request.yml Changes codegen schedule from weekly to daily and updates rationale comments.
.github/workflows/publish-release.yml Introduces publish planning + branch matrix; gates push publishing via PUBLISH_ON_MERGE; adds weekly schedule; changes concurrency cancellation behavior.
.github/workflows/publish-periodic-docker-release.yml Removes the old periodic Docker-only publisher workflow.
.github/workflows/get-version-task.yml Adds ref input to versioning task to support matrix publishing.
.github/workflows/build-release-task.yml Adds ref/branch/smoke + per-target gates; forwards parameters to leaf build tasks; adjusts GitHub release tagging logic.
.github/workflows/build-pypilibrary-task.yml Adds ref/branch; branches artifact names; switches version logic to use inputs.branch.
.github/workflows/build-nugetlibrary-task.yml Adds ref/branch; branches artifact names; uses inputs.branch for config selection.
.github/workflows/build-executable-task.yml Adds ref/branch/smoke; reduces runtime matrix under smoke; branches artifact names; skips aggregation under smoke.
.github/workflows/build-docker-task.yml Adds ref/branch/smoke; makes smoke amd64-only; introduces branch-scoped registry cache.
.github/workflows/build-datebadge-task.yml Adds branch input and gates badge write by inputs.branch.
.github/copilot-instructions.md Updates the Copilot runbook to document GraphQL requestReviews re-request flow.

Comment thread .github/workflows/build-release-task.yml Outdated
Comment thread .github/workflows/build-docker-task.yml Outdated
Comment thread .github/workflows/build-executable-task.yml Outdated
Comment thread .github/workflows/build-nugetlibrary-task.yml Outdated
Comment thread .github/workflows/build-pypilibrary-task.yml Outdated
Comment thread .github/workflows/build-datebadge-task.yml Outdated
Comment thread .github/workflows/get-version-task.yml
Comment thread .github/workflows/test-pull-request.yml
Comment thread .github/workflows/test-pull-request.yml

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 16 out of 16 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

.github/workflows/build-docker-task.yml:69

  • The Docker Hub login step always runs, which will fail on forked PR smoke builds (secrets are unavailable) even though push is false. Gate the login on inputs.push so PR smoke builds can still compile Docker images anonymously, while publish runs authenticate.
      - name: Setup Buildx step
        uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
        with:
          platforms: ${{ inputs.smoke && 'linux/amd64' || 'linux/amd64,linux/arm64' }}

      # Always login to Docker Hub, not just on push, to benefit from
      # higher rate limits with a Docker subscription for pulls and cache
      - name: Login to Docker Hub step
        uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0

Comment thread .github/workflows/build-docker-task.yml Outdated
Comment thread .github/workflows/publish-release.yml

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 16 out of 16 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

.github/workflows/build-docker-task.yml:68

  • docker/login-action runs unconditionally, so PR smoke builds (and any non-publishing builds where secrets aren’t available, e.g. fork PRs / Dependabot runs without Docker Hub secrets) can fail before they even reach the build. Since push=false smoke builds are explicitly meant to work without registry credentials, gate the login step on either inputs.push or the presence of the Docker Hub secrets.
          platforms: ${{ inputs.smoke && 'linux/amd64' || 'linux/amd64,linux/arm64' }}

      # Always login to Docker Hub, not just on push, to benefit from
      # higher rate limits with a Docker subscription for pulls and cache
      - name: Login to Docker Hub step

Comment thread .github/workflows/build-release-task.yml
Comment thread .github/copilot-instructions.md Outdated

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 16 out of 16 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/build-docker-task.yml Outdated

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 16 out of 16 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/test-pull-request.yml

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 16 out of 16 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/build-release-task.yml

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 16 out of 16 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/build-release-task.yml Outdated

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 16 out of 16 changed files in this pull request and generated 2 comments.

Comment thread .github/workflows/test-pull-request.yml Outdated
Comment thread AGENTS.md Outdated

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 16 out of 16 changed files in this pull request and generated no new comments.

@ptr727
ptr727 merged commit 48fa0b3 into develop Jun 3, 2026
18 checks passed
ptr727 added a commit that referenced this pull request Jun 4, 2026
Release merge of `develop` into `main`.

## Headline change (#98, closes #97)

Two-phase CI/CD that decouples merging from publishing across all four
delivery targets (Docker, NuGet, PyPI, console executable):

- **PRs smoke-test only** — path-gated, reduced builds (Docker
`linux/amd64`, trimmed executable matrix), no publish.
- **Sole publisher** — `publish-release.yml` (weekly schedule + manual
dispatch) builds/publishes **both** branches via a matrix; the `push`
trigger publishes only when the **`PUBLISH_ON_MERGE`** repository
variable is `true` (opt-in legacy continuous-release). Default is
two-phase.
- Parameterized chain (`ref`/`branch`/`smoke`, per-target `enable_*`
gates), branch-suffixed artifacts, branch-scoped Docker cache, hardened
required-status aggregator.
- Robustness: skip GitHub release on a duplicate version (no-op weeks),
pin the release tag to NBGV `GitCommitId`, global publish concurrency,
`cache-to`/login gating reviewed.
- CodeGen weekly → daily; `test-release-task.yml` +
`publish-periodic-docker-release.yml` removed.
- Corrected the Copilot review runbook (reliable `requestReviews`
mutation) and made the wait-for-maintainer-merge gate explicit.

Also includes routine codegen updates (#93, #95).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
ptr727 added a commit to ptr727/NxWitness that referenced this pull request Jun 4, 2026
Closes #407.

Two robustness fixes to the `github-release` job in
`publish-release.yml`, ported from ptr727/ProjectTemplate#98.

## 1. Skip duplicate release on no-op weeks

The weekly schedule re-runs even when `main` has no new commits, so NBGV
produces the **same `SemVer2`** and `softprops/action-gh-release` is
asked to (re)create an existing release/tag — churning the release every
week and risking failures re-uploading existing assets. Added a `Check
for existing release` step (`gh release view "$SemVer2"`) that gates the
release-creation step, so a no-op week is a true no-op.

## 2. Pin release tag to the built commit, not a moving ref

`target_commitish: main` is a **moving ref** — a commit landing on
`main` mid-run could tag the release on a newer commit than the one
built. Pinned it to NBGV's `GitCommitId` (the exact commit the version
was computed from; `get-version` runs with `ref: main`). Added
`GitCommitId` as a `get-version-task.yml` output.

Matches the existing file conventions (no new action pins introduced).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
ptr727 added a commit to ptr727/NxWitness that referenced this pull request Jun 4, 2026
Release merge of `develop` into `main`.

## Changes

- **Release-job robustness** (#408, closes #407): skip GitHub release
creation on no-op weekly runs (when the `SemVer2` tag already exists),
while still allowing `workflow_dispatch` to repair a release; and pin
`target_commitish` + the release-job checkout to NBGV `GitCommitId` (the
exact built commit) instead of the moving `main` ref. Ported from
ptr727/ProjectTemplate#98.
- Dependabot: bump `dorny/paths-filter` 3 → 4 (#409).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@ptr727
ptr727 deleted the feature/97-two-phase-cicd branch July 7, 2026 21:05
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