Skip to content

ci: prune dead/duplicate workflows, owner-guard publishing, document secrets, first release-nuget dry run - #344

Merged
IanFrelinger merged 5 commits into
masterfrom
ci/workflow-pruning
Aug 17, 2026
Merged

ci: prune dead/duplicate workflows, owner-guard publishing, document secrets, first release-nuget dry run#344
IanFrelinger merged 5 commits into
masterfrom
ci/workflow-pruning

Conversation

@IanFrelinger

Copy link
Copy Markdown
Owner

Production-readiness audit, L10 + L12 + M31 (fixable half). Ledger: https://claude.ai/code/artifact/15fa4198-97b8-4da6-bea0-0c24d364a7f3

Summary

PR 18 - L10 (fork/secret hygiene) + L12 (dead / duplicate / always-red workflows) + the fixable half of M31 (the release path had never been exercised).

  • Inventory of all 62 workflow files from gh run list --workflow <f> --limit 15 --json conclusion,createdAt,event,headBranch + each file's on: block (table below).
  • Pruned: 7 deleted, 7 marked # DORMANT: <reason>, <date> (one of them loses its weekly schedule). Nothing on the protected list was deleted; only cert-gate is required by branch protection (gh api .../branches/master/protection), so merges are unaffected.
  • L10:if: github.repository_owner == 'IanFrelinger' on container-image-publish.yml, release.yml (validate, which every other job needs), release-nuget.yml, release-staging-on-label.yml; new docs/CiSecrets.md lists every secrets.* / vars.* a workflow reads and what a fork gets without it.
  • M31:release-nuget.yml dispatched on this branch in artifact-only mode (no NUGET_PUBLISH_MODE variable exists upstream) - outcome below.
  • docs/CiGateInventory.md gets a short Pruning subsection instead of a rewrite because PR docs: make the repo's self-description true - ProjectTiers, README, CI inventory, layer rules #338 (docs/repo-map-refresh) already rewrites that file; the deleted rows / domain-coverage references were removed from the current version so onboarding-docs-guard's referenced-path check stays green.

release-nuget.yml dry run (M31)

Dispatched from this branch (commit 28e73ad, guards already in place):

gh workflow run release-nuget.yml --ref ci/workflow-pruning -f version=0.1.0-ci.1

Outcome: success on the first attempt, no harness fix needed, no re-dispatch.
Run: https://github.com/IanFrelinger/Nexo/actions/runs/31991505114 (2026-08-17 03:33 -> 03:35 UTC, 2m35s).

Job / stepResult
nuget / pack-and-publishsuccess
Verify pack script matches Nexo.Hosting MSBuild graphsuccess
Resolve version (0.1.0-ci.1)success
Pack hosting graph + bundle + client SDKsuccess - 22 .nupkg + 5 .snupkg (Nexo.Abstractions ... Nexo.Transport.Grpc, Nexo.Client, Nexo.Sdk, Nexo.Authoring, Nexo.CLI)
Release manifest (SHA-256 per nupkg)success - nuget-publish-manifest.json (22 packages)
Pre-publish feed verification (consumer sample)success - scripts/verify-stable-sdk-host-sample-packages.sh restored from the local feed
Upload NuGet packages + manifestsuccess - artifact nuget-packages-0.1.0-ci.1 (125.8 MB)
staging push / SBOM / Grype / OIDC login / nuget.org push / post-push verify (x5)skipped (no NUGET_PUBLISH_MODE, no NUGET_STAGING_FEED_URL, no NUGET_RELEASE_SBOM)
Publish skipped (configure repo)success - ::notice::NUGET_PUBLISH_MODE is not 'oidc' or 'apikey' (artifact-only)
Verify NuGet consumer (nuget.org)skipped (only runs when a publish mode is set)

Observation, not a bug: Nexo.CLI.0.1.0-ci.1.nupkg is 122.8 MB (PackAsTool embeds every ProjectReference output). nuget.org's limit is 250 MB so it would upload, but it is the artifact's entire weight; worth a look before the first real publish.

The remaining unexercised half of M31 is release.yml (tag push -> GHCR images + draft release), which was deliberately not dispatched, and the NUGET_PUBLISH_MODE=oidc|apikey branches (need the owner to set the variable + secret).

Inventory (62 files at 7196305, 2026-08-16)

Legend: G/R/c/s = success/failure/cancelled/skipped newest-first over the last 15 runs. Class: active-green, active-flaky, dead (no run in 60 days and no push/pull_request/schedule trigger that can fire), duplicate, always-red, manual (dispatch-only but referenced by a script/runbook), never-run.

FileTriggersRuns (newest first)LastClassAction
application-gate.ymlPR (paths), dispatch13G (2 running)2026-08-17active-greenkeep
cert-gate.ymlPR, push master, dispatch13G (2 running)2026-08-17active-green (required)keep
compat-gate.ymlpush master (scripts/compat-gate*.sh), dispatch1G2026-05-22active, path-rarekeep
compose-gate.ymlpush (paths), dispatch15G2026-08-17active-greenkeep
composition-mesh-gate.ymldispatch (tiered)14G 1R2026-06-13manual (readiness family: Makefile targets, scripts/composition-mesh-gate-tier-*.sh)keep
container-image-gate.ymlpush (paths), dispatch15G2026-08-17active-greenkeep
container-image-publish.ymlpush master (paths), dispatch15G2026-08-17active-greenkeep + owner guard
core-domain-coverage.ymlPR + push (kernel paths)14G (1 running)2026-08-17duplicate of kernel-coverage-gate's Domain legdeleted
cross-platform-tests.ymldispatch (push commented out 2026-08-11)15R2026-08-11always-red, mutedDORMANT
dependency-boundary.ymlPR + push (paths), dispatch15G2026-08-17active-greenkeep
devcontainer-gate.ymlpush (paths), dispatch15G2026-08-17active-greenkeep
devlog-ghost-release.ymlrelease: published, dispatch1s2026-07-26event-driven, var/secret-gatedkeep
distribution-matrix-gate.ymlPR + push (paths), weekly, dispatch14G (1 running)2026-08-17active-greenkeep
docs-link-check.ymlPR + push (docs), dispatch15G2026-08-17active-greenkeep
dr-gate.ymlpush master (scripts/dr-gate*.sh), dispatch1G2026-05-22active, path-rarekeep
environment-setup-gate-v1.ymlpush master (paths), dispatch15G2026-08-17active-greenkeep
friend-mesh-prefab-gate.ymlpush (paths), dispatch8G then 1R 1G 3R 2G2026-08-17active-green (past flake)keep
full-platform-readiness-gate.ymlpush (paths), weekly, dispatchG c c c c R c c c c c c R G G2026-08-17active (recently fixed)keep
grpc-transport-gate.ymlpush (paths), dispatch15G2026-08-17active-greenkeep
installer-bruteforce-gate.ymldispatch15G2026-05-23manual, dispatched by scripts/rc-gate-tier-d.shkeep
kernel-coverage-gate.ymlPR + push (kernel paths)14G (1 running)2026-08-17active-greenkeep
kernel-gate.ymlPR (paths), push master, dispatch13G (2 running)2026-08-17active-greenkeep
layer-boundary.ymlPR (**)G R G G G G G R R R R R R G G2026-08-17active-flakykeep
mapbox-tile-helpers-ci.ymldispatch15R2026-08-12always-red (job-level if: secrets.* is not a valid context)deleted
mcp-a2a-gate.ymlpush (paths), dispatch7G2026-08-17active-greenkeep
mesh-lab-gate.ymldispatch (push commented out 2026-08-11)15R2026-08-11always-red, mutedDORMANT
mesh-lab-remote-gate.ymldispatch (5 secrets + tailnet runner)0-never-rundeleted
mesh-lab-stress-gate.ymlweekly Mon 06:00, dispatch8R then 4G2026-08-10always-red on scheduleDORMANT, schedule removed
mesh-lab-tls-gate.ymlweekly Tue 07:00, dispatchG then 6R then 5G2026-08-11active-flakykeep
nuget-consumer-verify.ymldispatch (version)8G 1c2026-05-11manual release tooling (docs/NuGetConsumerVerify.md)keep
onboarding-docs-guard.ymlpush (docs/scripts), dispatch15G2026-08-17active-greenkeep
onboarding-quickstart-gate.ymlpush (paths), weekly, dispatch8G then 7R2026-08-17active-green (recovered)keep
ops-gate.ymldispatch (tiered)1G 1R2026-08-17manual (readiness family)keep
optimize-agent-cluster-gate.ymlpush (paths), dispatch6G then c's + 1G2026-08-17active-greenkeep
pack-hosting-graph-alignment.ymlpush master (paths), dispatch14G 1R2026-08-17active-greenkeep
perf-certification.ymldispatch0-never-run (readiness family, docs/production-readiness/PerfHardeningPlan-v1.md)keep
perf-gate.ymlpush master (paths), dispatch15G2026-08-17active-greenkeep
prod-dry-run-pr.ymldispatch12G 2R 1c2026-08-17manual (protected)keep
production-readiness-gate-v1.ymlpush (paths), dispatch15G2026-08-17active-greenkeep
provenance-graph-gate.ymlPR (paths), dispatch15G2026-08-16active-greenkeep
rc-gate.ymlpush master (paths), monthly, dispatch9G 1R2026-08-17active-greenkeep
release-nuget.ymldispatch (version)0 -> 1 (this PR)2026-08-17never-run -> exercisedkeep + owner guard
release-staging-on-label.ymlPR labeled15s2026-08-14event-driven (skips unless label matches)keep + owner guard
release.ymltag v*.*.*, dispatch0-never-run (NOT dispatched: creates draft release / images)keep + owner guard
reusable-container-publish.ymlworkflow_call0 (runs under caller)-reusablekeep
reusable-release-nuget.ymlworkflow_call0 -> exercised via release-nuget-reusablekeep
reusable-verify-nuget-consumer.ymlworkflow_call0 (only runs when NUGET_PUBLISH_MODE set)-reusablekeep
runtime-release-gate.ymlpush master (paths), dispatch10G 5c2026-08-17active-greenkeep
runtime-release-promotion.ymldispatch (schedule removed earlier)5R 3G 6R2026-05-11dead + mostly red; optional in rc-gate-tier-d.shDORMANT
runtime-studio-forge-smoke.ymldispatch14G 1R2026-06-14dead (63 days, no refs)deleted
runtime-studio-playground.ymldispatch4R2026-05-11duplicate of cross-platform-tests scope=playground, always-reddeleted
security-gate.ymlPR (paths), dispatch15G2026-08-17active-greenkeep
setup-smoke-suite.ymldispatch7G 7R 1 running2026-05-23manual, documented entry point (docs/CiFirstHardwareSecond.md)keep
shell-lint.ymlPR (scripts/**), dispatch10G2026-08-17active-greenkeep
ship-gate.ymldispatch (tiered)2G2026-08-17manual (protected)keep
test-air-gapped-no-network.ymldispatch11R2026-05-23always-red (never green since 2026-03-08; MSB1011 from CLI step)DORMANT
test-caching-multi-env.ymldispatch (push commented out 2026-08-11)14R 1c2026-08-11always-red, muteddeleted
test-persistence-multi-os.ymlpush master (persistence paths), dispatch15R2026-07-04duplicate of cross-platform-tests scope=persistence; red on publish-action 403, tests passdeleted
test-trust-multi-env.ymldispatch12G 2R 1c2026-05-23dead (85 days)DORMANT
testing-strategy-gate.ymlPR (paths)15G2026-08-17active-greenkeep
waterproofing-gate.ymldispatch0-never-run (readiness family: Makefile waterproofing-gate-full, scripts/waterproofing-gate.sh)keep
workflow-regression-gate.ymldispatch15G2026-06-14dead (63 days)DORMANT

Not done / deferred (with evidence)

  • CLI image fold. The four builders (container-image-gate: local build + --help + multi-arch --output type=cacheonly; distribution-matrix-gate: build + --help + pipeline validate --help; full-platform-readiness-gate: image inside a setup->discovery->dry-run matrix; reusable-container-publish: buildx push to GHCR) differ in platform, output and smoke. Three of the four are protected workflows and full-platform-readiness-gate only went green on 2026-08-16. A parameterised reusable job is a separate PR.
  • cross-platform-tests.yml / test-persistence-multi-os 403.EnricoMi/publish-unit-test-result-action needs checks: write; cross-platform-tests.yml still lacks a permissions: block, so its Linux job would fail on publish even if the product assertion (Cross-platform: RuntimeStudioBlackBoxSmokeTests.Daemon_extender_claims_objective_from_store_increments_attempts fails on all platforms (net8 + net9) #252) were fixed. Not touched here (out of scope: pruning, not repair) - noted for whoever un-mutes it.
  • test-air-gapped-no-network.yml fails inside nexo test multi-env (MSB1011), a CLI defect; left DORMANT rather than deleted because three hardening docs and a test comment cite it.
  • CONTRIBUTING.md line 45 claims cross-platform-tests.yml triggers on src/Nexo.Infrastructure/** and prod-dry-run-pr.yml runs on PRs; both are dispatch-only. Left alone (not a workflow-inventory file; PR docs: make the repo's self-description true - ProjectTiers, README, CI inventory, layer rules #338 owns the "self-description" pass) - flagging.

Merge-order note

PR #338 (docs/repo-map-refresh) rewrites docs/CiGateInventory.md, docs/GitHubBranchProtection.md, docs/architecture/TestingModel.md, docs/architecture/TestingStrategyPivot-v1.md and docs/production-readiness/CoverageGates-v1.md; this PR touches the same lines (removing domain-coverage / deleted-workflow rows). Whichever lands second needs a small rebase: keep #338's text, drop core-domain-coverage.yml / domain-coverage, and the seven deleted files from its trigger tables (they appear there as short names, so the referenced-path guard will not catch them).

Verification

  • Every remaining workflow re-read after edit; edits are comment lines, one job-level if: per guarded workflow, and the removed schedule: block. actionlint is not on PATH.
  • git grep for each deleted file name and job name across .github, Makefile, scripts, docs, src, application: only prose mentions remain, all updated to say "deleted" or pointing at the surviving equivalent.
  • Local replica of onboarding-docs-guard's "Referenced repo paths must exist" step: 0 missing path(s). No Markdown link targets a deleted workflow (lychee-safe).
  • gh api repos/IanFrelinger/Nexo/branches/master/protection --jq .required_status_checks.contexts = ["cert-gate"] - no deleted workflow was a required check.
  • release-nuget dry run: see above.

🤖 Generated with Claude Code
Note: conflicts with #338 on the CI docs are expected; #338's rewrite wins and this PR's pruning subsection is re-applied on top.

PlzTouchGrassand others added 3 commits August 16, 2026 23:32
…ormant ones
Roughly a third of the 62 workflow files were dead weight. Each file was
classified from `gh run list --workflow <f> --limit 15` plus its `on:` block
(active-green / active-flaky / dead / duplicate / always-red); the full table
is in the PR and the summary lives in docs/CiGateInventory.md ("Pruning").
Only `cert-gate` is required by branch protection, so nothing here changes
what blocks a merge.
Deleted (recoverable at 7196305):
- core-domain-coverage.yml: identical Domain=100% step to the first leg of
scripts/ci/kernel-coverage-gate.sh, same PR/push paths -> duplicate.
- runtime-studio-playground.yml / test-persistence-multi-os.yml: byte-for-byte
the `scope=playground` / `scope=persistence` legs of cross-platform-tests.yml
(same 3-OS matrix, same filters); 4/4 and 15/15 red. The persistence
failures were the publish-unit-test-result-action 403ing on check-runs,
not the tests.
- test-caching-multi-env.yml: 14 red + 1 cancelled of 15, muted since
2026-08-11, dispatch-only. compose-gate still validates the
Dockerfile.test-caching* images.
- mapbox-tile-helpers-ci.yml: 15/15 red, dispatch-only; the job-level
`if: secrets.MAPBOX_ACCESS_TOKEN != ''` is not a valid context there.
- runtime-studio-forge-smoke.yml: dispatch-only, last run 2026-06-14, no refs.
- mesh-lab-remote-gate.yml: never dispatched, five secrets + tailnet runner;
scripts/mesh-lab-verify-remote.sh is the supported path.
Marked `# DORMANT: <reason>, <date>` and left dispatchable:
cross-platform-tests, mesh-lab-gate (both muted 2026-08-11),
mesh-lab-stress-gate (weekly schedule REMOVED after eight consecutive red
runs 2026-06-22..2026-08-10), runtime-release-promotion (rc-gate-tier-d
lists it as optional), test-air-gapped-no-network (never green; MSB1011 from
the CLI step), test-trust-multi-env and workflow-regression-gate (dead by
the 60-day rule but cited by hardening plans / only e2e of `nexo workflow`).
Kept although rarely run: compat-gate, dr-gate (path-triggered),
composition-mesh-gate, waterproofing-gate, perf-certification,
installer-bruteforce-gate (dispatched by rc-gate-tier-d), nuget-consumer-verify,
setup-smoke-suite (docs/CiFirstHardwareSecond.md), mesh-lab-tls-gate.
Not folded: the four CLI-image builds differ in platform/output/smoke and
three are protected workflows; a shared reusable job is its own PR.
Docs: every backtick path and Markdown link to a deleted file was updated
(onboarding-docs-guard's referenced-path check and lychee would both go red
otherwise), and `domain-coverage` branch-protection recommendations now say
`kernel-coverage`. docs/CiGateInventory.md gets a short "Pruning" subsection
rather than a rewrite because PR #338 (docs/repo-map-refresh) already
rewrites that file.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… secret and variable
A fork of this repository inherits container-image-publish.yml, release.yml,
release-nuget.yml and release-staging-on-label.yml with no owner check, so a
fork's path-filtered push to master (or a v* tag) would try to publish
nexo-cli / nexo-api under the fork's GHCR namespace and walk the NuGet path.
Each of those four now carries `if: github.repository_owner == 'IanFrelinger'`
on the job every other job depends on (release.yml: `validate`), so a fork's
run is skipped rather than half-published. A fork that wants to publish edits
that one line; image names already derive from github.repository_owner.
docs/CiSecrets.md lists every `secrets.*` / `vars.*` a workflow reads (from
`grep -ohE '(secrets|vars)\.[A-Za-z_0-9]+' .github/workflows/*.yml`), which
workflow reads it, the condition under which it is read, and what happens
without it - including the one hard error (NUGET_STAGING_FEED_URL set without
NUGET_STAGING_API_KEY). Nothing is required for PR/push/schedule gates;
NUGET_PUBLISH_MODE unset means artifact-only, which is the state upstream
has always been in (`gh variable list` is empty).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ts.md
release-nuget.yml had zero runs since it was written. Dispatched from this
branch with version=0.1.0-ci.1 (run 31991505114): pack, manifest, consumer
sample restore and artifact upload all green; every nuget.org / staging /
SBOM step skipped because no NUGET_PUBLISH_MODE variable exists. Noting it
where the variable is documented so the next reader knows the harness has
been exercised at least to the push boundary.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@cursor

cursorBot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

PlzTouchGrassand others added 2 commits August 17, 2026 01:00
…ites, re-apply pruning subsection and domain-coverage removals; drop a stray edit artifact from TestingModel.md
@IanFrelinger
IanFrelinger merged commit fac5ace into masterAug 17, 2026
5 checks passed
@IanFrelinger
IanFrelinger deleted the ci/workflow-pruning branch August 17, 2026 05:11
IanFrelinger pushed a commit that referenced this pull request Aug 17, 2026
…ons, keep 10.0.x setup-dotnet, Orchestration csproj from this branch (master side was renormalization only)
Sign up for freeto 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

@IanFrelinger@PlzTouchGrass