Skip to content

[P1] Prevent tag-based workflow dry runs from entering the NuGet publish job #19

Closed

Description

@AGiorgetti

Priority and scope

P1: A tag-selected manual rehearsal can publish packages even when the maintainer explicitly selected dry run and left publish disabled. Treat this as release-safety work before the next rehearsal.

Reviewed default develop at 612e5c03bba3e811741385cd7440ffb5af43b8df. main at b9697f2f91aa737360479a434f7d3cc01ccaa8fd has the identical source tree, so this is not develop-only.

Evidence and cause

The publish condition starts with github.ref_type == 'tag' || .... The checks for inputs.dry_run == false and inputs.publish == true apply only to the second branch. The dry-run handoff can report a no-push rehearsal immediately before that publish job. The final step pushes all three packages.

Minimal reproduction (proposed, not executed)

Evaluate the workflow's job conditions with event_name=workflow_dispatch, ref_type=tag, ref=refs/tags/, inputs.dry_run=true, inputs.publish=false, and successful prerequisite jobs. Do not test against the real NuGet endpoint; use a condition-unit test or a mocked publish command.

Actual behavior predicted from source

The publish condition is true solely because ref_type is tag. The job can request production-environment approval and, if that gate permits it and credentials are present, invoke NuGet push. Actual production protection settings were not inspected, so automatic publication without approval is not asserted.

Expected behavior

Every manual dry run must exclude the publish job regardless of branch/tag selection. The publish=false input must not be bypassed by selecting a tag.

Fix direction

Separate tag-push events from manual dispatches. Require a push event for automatic tag publishing, and evaluate dry_run/publish explicitly for every manual-dispatch path. Keep production approval as defense in depth.

Regression acceptance

  • Test the full event × ref-type × publish × dry_run matrix
  • Tag dispatch with dry_run=true never schedules a publish or calls push
  • Branch dry runs remain nonpublishing
  • Authorized valid tag pushes and approved manual production runs still publish
  • Validate conditions themselves, rather than just searching YAML for the word dry_run

Duplicate review

This is a narrow follow-up to closed #17 and merged #18: their broad dry-run requirement was implemented, but the tag-dispatch condition bypasses it. All 18 existing issue/PR records and 72 issue-conversation comments were inspected; none currently tracks this specific unresolved case.

Verification limits

This is a static source finding. The reproduction was not compiled or run, and no repository code, release workflow, or benchmark was executed in this review. The existing exact-head CI run passed its build/test and Roslyn-host jobs; release pack, artifact-verification, and publish jobs were skipped. That existing run does not validate this proposed regression.

Prepared with OpenAI Codex.


Validation update (2026-10-02)

Confirmed by source-extracted condition evaluation. The earlier static-only verification statement is superseded for the checks below. The source remains 612e5c03bba3e811741385cd7440ffb5af43b8df; no fix was applied.

Executed checks

An independent Python evaluator read the original job conditions directly from .github/workflows/ci.yml and evaluated their documented boolean/string expression subset, including the needs success gate. It completed 72 event/ref/input cases and 12 failed/cancelled/skipped-prerequisite controls. This was not a GitHub Actions workflow execution.

For workflow_dispatch on refs/tags/1.0.0, assuming successful prerequisites and a valid tag matching GitVersion:

publish dry_run Pack reachable Artifact verification reachable Publish reachable
false false false false false
false true true true true
true false false false false
true true true true true

Both dry-run tag dispatches therefore reach the publish job, including publish=false. Branch dry runs remained nonpublishing. All 12 prerequisite failure/cancellation/skip controls blocked publication.

Scope and limits

The raw publish expression is true in all four tag-dispatch rows, but the two dry_run=false rows do not reach publishing because pack is skipped. A true publish expression alone is insufficient; the successful dependency chain is part of this reproduction.

The matrix assumes later package and artifact validation succeeds. Production-environment protections and credential availability were not inspected. No workflow was dispatched and no package was published, so this confirms that the condition can reach the production approval gate, not that approval can be bypassed.

The evaluator follows GitHub's documented expression behavior and job dependency rules. Synthetic pull-request/tag combinations in the matrix are negative controls, not normal pull-request contexts.

Overall cloud-validation scope

The dated evidence above supersedes the earlier static-only verification statement for the listed cases; unexecuted regression-acceptance variants remain proposed. The unchanged full solution built in Release with zero warnings/errors. The existing suites recorded 653 passes and 2 failures across 655 tests, with no skips. Both failures, TrimmedConsumerPublishesAndRunsWithoutLiteMapperWarnings and NativeAotConsumerPublishesAndRunsWithoutLiteMapperWarnings, were cloud infrastructure blocked: ILLink's out-of-process ComputeManagedAssemblies task host failed with MSB4216 and Unix-domain pipe SocketException (13), permission denied. Trimming/AOT behavior was not established, and these tests are not intrinsically Windows-only. The repository's separate win-x64 final-package release lane still requires a Windows execution environment and Windows/MSVC toolchain.

The 20 focused generator tests comprised 14 intentional contract assertion failures reproducing defects and 6 passing controls/measurement cases; they are not an all-green acceptance suite. No production fixes or releases were made.

Activity

  1. AGiorgetti commented on Oct 3, 2026

    @AGiorgetti
    ContributorAuthor

    Execution plan

    Continuing only #19 in an isolated checkout from develop at 612e5c03bba3e811741385cd7440ffb5af43b8df, branch feat/codex-issue-19-publish-gate. No existing fix PR or blocking dependencies were found. This comment records ownership for this task; the user's explicit issue instruction supplies readiness.

    1. Add MSTest regressions reading the actual workflow expressions and dependency graph; demonstrate failure before changing YAML.
    2. Exercise event/ref/publish/dry_run combinations, unsuccessful prerequisites, and authorized tag-push/manual branch paths with local mocked publishing.
    3. Restrict automatic tag publishing to push events while preserving manual branch authorization, production environment protection, and package/artifact validations.
    4. Run focused and broader validation, then open a draft PR against develop and verify its remote head and ordinary PR CI.

    No release workflow dispatch, tags, NuGet publication, merge, security setting changes, or software installation. Installed AgentStack cannot perform protocol operations: agentstack doctor expects .agent-stack/active-tracker.json, while the repository uses .agent-stack/modules/protocol/active-tracker.json. Using the repository-authorized GitHub CLI fallback without changing the tooling.

    Prepared with OpenAI Codex.

  2. AGiorgetti commented on Oct 3, 2026

    @AGiorgetti
    ContributorAuthor

    Regression baseline confirmed

    Added source-based MSTest coverage before modifying production YAML. The initial run executed 154 cases: 20 failed, 134 passed, zero skipped.

    • Both tag-selected manual rehearsals (dry_run=true, publish=false/true) reached pack, artifact verification, and publish. Executing the extracted publish step with a local mocked dotnet function recorded three push calls per case. No real push occurred.
    • The raw publish condition also incorrectly accepted all tag-dispatch input combinations and synthetic PR/tag or unsupported event/tag controls. A true raw condition alone is not evidence of reachable publication: non-dry-run tag dispatches skip pack.
    • Authorized stable/prerelease tag pushes and manual main/release/hotfix publishing passed their controls. All 48 failure/cancellation/skip prerequisite cases blocked publication.

    Next: require github.event_name == 'push' for the automatic tag branch of the publish condition. Keep manual authorization, the production environment, dependency gates, and all package validation unchanged. Dependency restore succeeded on the approved unrestricted retry after sandbox NU1301 SSL errors.

    Evidence: artifacts/validation/issue-19/red/issue-19-red.trx. These are local condition/dependency tests and mocked command execution, not a GitHub release run.

    Prepared with OpenAI Codex.

  3. AGiorgetti commented on Oct 3, 2026

    @AGiorgetti
    ContributorAuthor

    Publishing gate fixed and focused validation passed

    The publish condition now requires a push event for its automatic tag branch. Manual production publishing still requires publish=true and dry_run=false on main/release//hotfix/.

    • All 154 new workflow condition/dependency/mock cases pass, zero skips.
    • All 19 existing release-quality cases pass, zero skips.
    • Release solution build: zero warnings/errors.
    • YAML parse and diff whitespace checks pass.
    • Independent read-only review found no acceptance gap or normative blocker.

    Full solution tests are running. This machine has .NET 8/9/10 runtimes but no MSVC C++ toolchain, so local Native AOT validation may be inconclusive; ordinary exact-head PR CI will check Windows/Linux. The production environment, dependency gates, SemVer/package/content/checksum/provenance validation, and actual publish command are preserved. No release has been performed.

    Prepared with OpenAI Codex.

  4. AGiorgetti commented on Oct 3, 2026

    @AGiorgetti
    ContributorAuthor

    Draft PR opened

    Draft PR #33 targets develop. The pushed remote head exactly matches validated local commit 34d0549132b50bf0c0e09dd6e143ea1d26f7ea66. The test-first regression commit is c228266aa82e89204039a1fab57acf75a5167be9; both commits carry Codex co-author attribution.

    • Focused release suite: 173 passed, zero skipped.
    • Full local run: 806 passed, two stale sample-asset failures (NETSDK1064), one missing-MSVC Native AOT prerequisite skip. Regenerating assets and rebuilding recovered both failures; affected sample/usage tests plus release regressions then passed 175/175, zero skipped. The full-run and recovery evidence establish passing results for all 808 executed cases without claiming a single all-green full invocation.
    • Release solution build: zero warnings/errors. YAML and CRLF-aware whitespace checks pass; working tree is clean.

    Checking ordinary pull_request CI on that exact head now. Local Native AOT remains inconclusive; live production environment behavior is outside the local evaluator's scope. No release workflow dispatch, real NuGet push, tags, merge, or repository security-setting change occurred.

    Prepared with OpenAI Codex.

  5. AGiorgetti commented on Oct 3, 2026

    @AGiorgetti
    ContributorAuthor

    Ready for human review

    Draft PR #33 against develop is ready. Ordinary PR CI passed on exact head 34d0549132b50bf0c0e09dd6e143ea1d26f7ea66, matching the remote branch and PR head.

    • Windows and Linux: 809 tests passed per platform, zero failures/skips, including all 154 new publishing regressions and required trimming/Native AOT checks.
    • All six Roslyn host jobs passed.
    • Pack & Validate, Verify Release Artifacts, and Publish NuGet Packages were skipped.
    • Test-first baseline: 20 failed/134 passed before the fix. Local focused release tests pass 173/173; the two stale-cache sample failures were recovered, and local Native AOT's missing-MSVC skip is superseded by successful required CI validation on both platforms.

    One production condition line changed. Publishing command execution was mocked locally; no live production approval or NuGet publication was tested. No release, workflow dispatch, tag push, merge, security-setting change, or unrelated issue change occurred. Both commits have Codex co-author attribution. PR remains draft and #19 remains open. Stopping here as requested.

    Prepared with OpenAI Codex.

  6. added 2 commits that reference this issue on Oct 5, 2026
    92fae64
    1b1709c
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

    priority:p1AgentStack priority P1type:bugAgentStack work item type: bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions