Skip to content

Release timeout falsely reports workflow approval after CI has already started #145

Closed

Description

@unbraind

Observed failure and immutable source

At main 247b95e6214f687d0d838d1685cc0e99db664cd6, release.yml initializes awaiting_approval=0 once before the merge loop, sets it to 1 when a run is action_required/waiting, and never resets it when a later poll reports no approval-pending runs.

Daily Release 39015290805 timed out at 08:37:04 UTC on October 17 and told the maintainer to approve the CI run. But the same log repeatedly reports both required tests in progress, including at 08:37:03. Node 22 started at 08:13:14 and passed at 08:38:02; Node 26 started at 08:12:55 and passed at 08:39:04. This was a slow-check timeout, not an approval still required at timeout.

At the 09:15 UTC read, release PR #144 remains open at 328e284cd30afb2811998fc6d0f02e78994d537c, its checks are green, and the latest GitHub release is still v2026.10.16. Publication/tagging steps were skipped. This report does not authorize a merge, retry, or release.

Bounded reproduction

Run the workflow's approval-state assignments in isolation, without any gh/git/network calls:

  1. Initialize awaiting_approval=0
  2. First poll: pending_runs is nonempty, so the existing conditional sets awaiting_approval=1
  3. Later poll: pending_runs is empty because CI is now in_progress; the same conditional leaves awaiting_approval at 1
  4. Execute the deadline diagnostic conditional: it selects 'awaiting workflow approval'

Observed exit 0 and approval-required diagnostic despite current approval-required=false. Source inspection finds only three uses: initialization line 354, setting line 479, deadline branch line 484.

Expected: terminal diagnostics reflect the latest successfully observed approval/check state and distinguish slow-running checks from a genuinely approval-blocked workflow. Actual: a historical approval observation permanently selects the approval message, directing the maintainer to an action that is no longer applicable.

Goal and impact

The protected-release merge loop introduced in PR #33 deliberately keeps publication behind verified merge and diagnoses a bounded wait. Preserve that safety behavior. The defect is stale state in the recovery guidance; increasing timeouts or bypassing checks is not required to correct it. Today it obscures why a fully green release PR is still unpublished.

Regression acceptance

  • action_required -> in_progress -> deadline reports checks still settling, without claiming approval is currently required
  • action_required -> action_required -> deadline still reports the actual pending run
  • action_required -> successful checks/merge does not emit a stale approval blocker
  • An unavailable run-state read is distinguished from a verified empty result
  • No reduction to required checks, review gates, permissions or publication protections

Scope: hosted log/check evidence and a minimal isolated state-transition reproduction, not a full release replay or newly run package suite. All-status repository issues/PRs and all 131 canonical PM records were checked for an existing owner before filing.

Activity

  1. unbraind commented on Oct 18, 2026

    @unbraind
    OwnerAuthor

    Fixed in PR #148 at f94e4e5e7f06b5a3d443f082a1b4f4215c967534 (pushed). The actual release merge-wait shell now clears historical approval after a successful empty run-state read and reports unavailable reads separately. node --test test/release-approval.test.ts passes 4/4: pending-to-running timeout, still-pending timeout with run URL, unavailable read, and later verified merge. Reverting only release.yml fails 2/4; restoring it passes. Full isolated npm/Bun gates and CI are in progress; no live merge or publication was performed.

  2. unbraind commented on Oct 18, 2026

    @unbraind
    OwnerAuthor

    Final delivery for PR #148 is pushed at 96a4b4bedea2943797a02510e7f4e7aad395b8f6. Actual release-loop regression: 4/4 pass; reverting only the fix fails 2/4. Both isolated CI release commands pass 824/824 with zero failures/skips and exact 100% in all four coverage dimensions across 14 modules. Final-head Node 22/26, native Bun acceptance, CodeQL and Semgrep pass: https://github.com/unbraind/pm-github/actions/runs/39098874412 . Implementation and tests match the release-gated source; the temporary validation workflow was removed. No PR was merged.

  3. unbraind commented on Oct 18, 2026

    @unbraind
    OwnerAuthor

    Revalidated after integrating current main in pushed head 04bbf3603c30e6dd81efa2622e3aa0d086f845eb. node --test test/release-approval.test.ts passes 4/4. Both exact isolated-identity npm run release:check and bun run release:check pass 836/836 with exact 100/100/100/100 coverage across all 14 authored modules: https://github.com/unbraind/pm-github/actions/runs/39105101037. The validated head was 762285d94e90e645927b90e8032292c191772b49; final production code, tests, scripts, docs and dependency pins are byte-identical. Existing behavioral revert proof is preserved, and PR #148 retains its closing link. Final-head CI is tracked in the PR body; this comment does not close the issue.

  4. unbraind commented on Oct 18, 2026

    @unbraind
    OwnerAuthor

    PR #148 is pushed at 7d4306774005b5542ab617926593252c6b319f80. node --test test/release-approval.test.ts passes 4/4. Original approval-state transition fix and recorded production-only revert proof are retained after merging current main.

    Both exact isolated npm run release:check and bun run release:check pass 893/893 with zero failures/skips/cancellations/todos and exact 100/100/100/100 source coverage: https://github.com/unbraind/pm-github/actions/runs/39119457879 . Fresh-clone strict health passes. Final-head Node 22/26 CI, including native Bun acceptance, passes (https://github.com/unbraind/pm-github/actions/runs/39120403305); CodeQL and Semgrep pass; no merge or release was performed.

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions