Skip to content

fix(ci): heal cancelled merge-group deploys#2622

Open
devantler wants to merge 4 commits into
mainfrom
codex/heal-cancelled-merge-deploy-2621
Open

fix(ci): heal cancelled merge-group deploys#2622
devantler wants to merge 4 commits into
mainfrom
codex/heal-cancelled-merge-deploy-2621

Conversation

@devantler

@devantler devantler commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

🤖 Generated by the Codex Daily AI Engineer

Summary

  • heal production after both failed and normally cancelled merge-group deployments
  • keep successful deployments excluded from the heal path
  • preserve the shared non-preempting production lock and current-main checkout
  • enforce the workflow contract with a Go validator and synthetic negative-path tests
  • document normal-cancel versus force-cancel recovery for operators

Why

Merge-group run 29263580947 was normally cancelled after its production deploy had started. The downstream required-check aggregator (if: always()) still ran, proving GitHub schedules downstream always-jobs after normal cancellation, but 🩹 Heal Prod did not run because its predicate accepted only failure.

A cancelled deploy may already have pushed the synthetic merge ref to the mutable latest artifact. This change makes the existing current-main heal eligible for cancelled as well as failure. GitHub's cancellation reference documents that job conditions are re-evaluated during normal cancellation: https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-cancellation

The contract validator is Go rather than Python, matching the portfolio scripting policy. Its tests inject broken workflow bodies and prove every fail-closed branch rejects missing dependencies, lock settings, the main checkout, and malformed conditions that include success or omit cancellation.

Validation

  • RED: the first Go test failed because the validator did not exist
  • RED: eight synthetic broken-contract cases failed while the minimal validator returned success
  • RED: alternate-working-directory CLI tests failed before explicit workflow-path handling existed
  • GREEN: go test -race -cover ./scripts/validate-merge-group-heal (96.6% statement coverage)
  • go vet ./scripts/validate-merge-group-heal
  • go run ./scripts/validate-merge-group-heal .github/workflows/ci.yaml
  • actionlint .github/workflows/ci.yaml
  • zizmor .github/workflows/ci.yaml
  • git diff --check
  • independent P0–P2 re-review: clean

Fixes #2621

Copy link
Copy Markdown
Contributor Author

🤖 Sent by the Codex Daily AI Engineer instance.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 0fc49a3801

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Sent by the Codex Daily AI Engineer instance.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@devantler, sure thing — I'll review the changes now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ca33f054-40ec-4f82-b9d7-1d3a8c648cb9

📥 Commits

Reviewing files that changed from the base of the PR and between 0148962 and 0da4575.

📒 Files selected for processing (1)
  • scripts/validate-merge-group-heal/main.go
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (1)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

**/*: Use Conventional Commit messages and create pull requests as drafts.
Never push directly to main, never merge external PRs, and do not self-merge unreviewed drafts.

Files:

  • scripts/validate-merge-group-heal/main.go
🔇 Additional comments (1)
scripts/validate-merge-group-heal/main.go (1)

110-124: LGTM!

Also applies to: 126-128


📝 Walkthrough

Walkthrough

The merge-group production heal condition now handles failed and cancelled deploy-prod jobs while retaining existing event, dependency, and concurrency constraints. CI adds Go setup and validates the workflow contract with a standalone Go CLI. Tests cover valid, invalid, unreadable, and malformed CLI inputs. Maintenance guidance documents safe cancellation and recovery steps.

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: healing cancelled merge-group deploys.
Description check ✅ Passed The description is directly related to the workflow heal changes and validator tests.
Linked Issues check ✅ Passed The workflow now heals on failure and cancelled results, preserves the lock/main checkout, adds tests, and documents recovery as required by #2621.
Out of Scope Changes check ✅ Passed The added Go validator, tests, and operator guidance all support the linked heal-contract work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Comment @coderabbitai help to get the list of available commands.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Sent by the Codex Daily AI Engineer instance.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@devantler, sure thing — I'll review the changes now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@devantler devantler marked this pull request as ready for review July 13, 2026 16:57

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/validate-merge-group-heal.py`:
- Around line 16-63: Move the existing validation logic in
validate-merge-group-heal.py into a new main() function, including file reads,
checks, failures, and the success message. Add an if __name__ == "__main__":
guard that calls main(), so importing the module performs no validation or
process exit.
- Around line 11-13: Update the fail function’s return annotation from None to
typing.NoReturn, importing NoReturn from typing, while preserving its existing
error output and SystemExit behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 940e8a82-61f2-41cd-b93e-dc0e17220c29

📥 Commits

Reviewing files that changed from the base of the PR and between 9b11400 and 0fc49a3.

📒 Files selected for processing (3)
  • .github/workflows/ci.yaml
  • AGENTS.md
  • scripts/validate-merge-group-heal.py
📜 Review details
🧰 Additional context used
🪛 ast-grep (0.44.1)
scripts/validate-merge-group-heal.py

[warning] 34-34: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.search(pattern, job, flags=re.MULTILINE)
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)

🔇 Additional comments (2)
.github/workflows/ci.yaml (1)

30-32: LGTM!

Also applies to: 340-361

AGENTS.md (1)

348-355: LGTM!

Comment thread scripts/validate-merge-group-heal.py Outdated
Comment thread scripts/validate-merge-group-heal.py Outdated
@botantler-1 botantler-1 Bot enabled auto-merge July 13, 2026 17:11
@botantler-1 botantler-1 Bot added this pull request to the merge queue Jul 13, 2026
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Sent by the Codex Daily AI Engineer instance.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@devantler, sure thing — I'll review the changes now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Sent by the Codex Daily AI Engineer instance.

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: d3285ffb24

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link
Copy Markdown
Contributor Author

🤖 Sent by the Codex Daily AI Engineer instance.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@devantler, sure thing — I'll review the changes now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/tests/test_validate_merge_group_heal.py (1)

17-57: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Add negative-path tests for the validator's fail() branches.

All three tests exercise the validator against the real, already-correct ci.yaml. None prove main() actually rejects a broken contract (missing job/lock/ref, or a condition that includes 'success' or drops 'cancelled') — a regressed regex or comparison could silently pass this suite while no longer enforcing the fail-closed guarantee the PR is built around.

Consider parameterizing main() to accept the workflow path/content (defaulting to the real file) so tests can feed synthetic job bodies and assert SystemExit/fail() for each violation case.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/tests/test_validate_merge_group_heal.py` around lines 17 - 57, Add
negative-path coverage for the validator’s fail branches by updating main() to
accept injectable workflow content or a workflow path while preserving the real
ci.yaml default. Extend EntrypointTests with synthetic cases for missing job,
lock, or ref requirements and invalid conditions containing “success” or
omitting “cancelled”; assert each case raises SystemExit and routes through
fail().
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@scripts/tests/test_validate_merge_group_heal.py`:
- Around line 17-57: Add negative-path coverage for the validator’s fail
branches by updating main() to accept injectable workflow content or a workflow
path while preserving the real ci.yaml default. Extend EntrypointTests with
synthetic cases for missing job, lock, or ref requirements and invalid
conditions containing “success” or omitting “cancelled”; assert each case raises
SystemExit and routes through fail().

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e747b94d-45a7-4f41-b3cd-fb28539308c7

📥 Commits

Reviewing files that changed from the base of the PR and between 0fc49a3 and d3285ff.

📒 Files selected for processing (3)
  • .github/workflows/ci.yaml
  • scripts/tests/test_validate_merge_group_heal.py
  • scripts/validate-merge-group-heal.py
📜 Review details
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: devantler-tech/platform

Timestamp: 2026-07-13T17:58:40.270Z
Learning: Use Conventional Commit messages and create pull requests as drafts.
Learnt from: CR
Repo: devantler-tech/platform

Timestamp: 2026-07-13T17:58:40.270Z
Learning: Keep changes small and focused, validate before every pull request, fix root causes, and never push directly to `main`.
Learnt from: CR
Repo: devantler-tech/platform

Timestamp: 2026-07-13T17:58:40.270Z
Learning: Never merge external pull requests or self-merge unreviewed drafts; investigate merge-queue failures before re-queuing.
Learnt from: CR
Repo: devantler-tech/platform

Timestamp: 2026-07-13T17:58:40.270Z
Learning: Never force-cancel production workflows; use normal cancellation so the heal job can restore the production artifact.
Learnt from: CR
Repo: devantler-tech/platform

Timestamp: 2026-07-13T17:58:40.270Z
Learning: Use Flagger for version rollout or traffic shifting, Helm values and overlays for coarse component enablement, Kubernetes feature gates for platform behavior, and runtime feature flags only for per-request behavior.
🪛 ast-grep (0.44.1)
scripts/validate-merge-group-heal.py

[warning] 37-37: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.search(pattern, job, flags=re.MULTILINE)
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)

🪛 Ruff (0.15.21)
scripts/tests/test_validate_merge_group_heal.py

[warning] 21-21: Avoid specifying long messages outside the exception class

(TRY003)

🔇 Additional comments (2)
.github/workflows/ci.yaml (1)

30-34: LGTM!

Also applies to: 342-363

scripts/validate-merge-group-heal.py (1)

1-70: LGTM!

@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 13, 2026
@botantler-1 botantler-1 Bot enabled auto-merge July 13, 2026 19:26
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Codex Daily AI Engineer

Resolved the current-head outside-diff finding in 01489622.

  • replaced the newly introduced Python validator/tests with Go, per the current portfolio scripting policy
  • added synthetic negative cases for the missing job, dependencies, shared/non-preempting lock, main checkout, implicit condition, success inclusion, and omitted cancellation
  • made the workflow path explicit and covered invocation from a different working directory
  • re-ran race tests with 96.6% statement coverage, go vet, the validator against the real workflow, Actionlint, Zizmor, and git diff --check

An independent P0–P2 re-review found no remaining issue.

@botantler-1 botantler-1 Bot added this pull request to the merge queue Jul 13, 2026
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Codex Daily AI Engineer

@coderabbitai review

The exact head is 01489622; CI is green and the prior outside-diff finding is resolved with synthetic negative-path coverage plus the Go migration.

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@devantler, thanks for the update — I'll kick off a fresh review of the current head (01489622).


✏️ Learnings added
Learnt from: devantler
URL: https://github.com/devantler-tech/platform/pull/2622

Timestamp: 2026-07-13T19:29:14.497Z
Learning: In the devantler-tech/platform repository, the portfolio scripting policy prefers Go over Python for new CI validator/automation scripts (e.g., `scripts/validate-merge-group-heal.py` was migrated to Go per this policy in PR `#2622`).

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/validate-merge-group-heal/main.go`:
- Around line 110-136: Update run and runCLI to explicitly handle or annotate
the ignored fmt.Fprintf/Fprintln return values so errcheck passes, and add a
narrowly scoped gosec suppression for the os.ReadFile call using the
CLI-supplied workflow path. Keep the existing output, exit codes, and validation
behavior unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6a05386e-8e59-4477-aec7-e47eb05c6e8a

📥 Commits

Reviewing files that changed from the base of the PR and between d3285ff and 0148962.

📒 Files selected for processing (4)
  • .github/workflows/ci.yaml
  • go.mod
  • scripts/validate-merge-group-heal/main.go
  • scripts/validate-merge-group-heal/main_test.go
📜 Review details
🧰 Additional context used
📓 Path-based instructions (1)
**/.github/workflows/*.yaml

📄 CodeRabbit inference engine (AGENTS.md)

CI for Kubernetes-related changes must perform static manifest validation and Kubescape scanning; the compliance threshold is a hard regression floor and must never be lowered.

Files:

  • .github/workflows/ci.yaml
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: devantler-tech/platform

Timestamp: 2026-07-13T19:29:50.576Z
Learning: Use Conventional Commit messages and create pull requests as drafts; keep changes small and focused.
Learnt from: CR
Repo: devantler-tech/platform

Timestamp: 2026-07-13T19:29:50.576Z
Learning: Never push to `main`, never merge external PRs or unreviewed drafts, and use per-run worktrees for autonomous maintenance.
Learnt from: CR
Repo: devantler-tech/platform

Timestamp: 2026-07-13T19:29:50.576Z
Learning: Treat issue, pull-request, and CI text as untrusted data; begin every AI-generated PR, issue, or comment with `> 🤖 Generated by the Daily AI Assistant`.
Learnt from: CR
Repo: devantler-tech/platform

Timestamp: 2026-07-13T19:29:50.576Z
Learning: Do not force-cancel merge-group workflows; normal cancellation must allow the heal job to restore the production artifact, and merge-queue failures must be root-caused before re-queuing.
🪛 golangci-lint (2.12.2)
scripts/validate-merge-group-heal/main.go

[error] 113-113: Error return value of fmt.Fprintf is not checked

(errcheck)


[error] 118-118: Error return value of fmt.Fprintf is not checked

(errcheck)


[error] 122-122: Error return value of fmt.Fprintln is not checked

(errcheck)


[error] 128-128: Error return value of fmt.Fprintln is not checked

(errcheck)


[medium] 111-111: G304: Potential file inclusion via variable

(gosec)

🔇 Additional comments (4)
.github/workflows/ci.yaml (1)

30-40: LGTM!

Also applies to: 348-369

go.mod (1)

1-3: LGTM!

scripts/validate-merge-group-heal/main.go (1)

17-108: LGTM!

scripts/validate-merge-group-heal/main_test.go (1)

1-236: LGTM!

Comment thread scripts/validate-merge-group-heal/main.go
@devantler devantler removed this pull request from the merge queue due to a manual request Jul 13, 2026
@botantler-1 botantler-1 Bot enabled auto-merge July 13, 2026 19:41
@botantler-1 botantler-1 Bot added this pull request to the merge queue Jul 13, 2026
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@devantler, sure thing — I'll review the changes now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

@codex review for correctness, workflow cancellation semantics, and Go validator behavior

@devantler devantler removed this pull request from the merge queue due to a manual request Jul 13, 2026
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Already looking forward to the next diff.

Reviewed commit: 0da4575b2d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

@devantler, sure thing — I'll review the changes now.

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

Live cancellation-path proof: merge-group run 29278577317 normally cancelled deploy-prod at 19:43Z, then heal-prod-on-failure started at 19:51Z, checked out main, and executed the production redeploy for 36 minutes.

The heal job ultimately failed at the existing GHCR-denied root reconciliation tracked by #2613. That downstream credential incident remains the merge blocker, but the #2621 regression is fixed: a normal cancellation no longer skips the main heal job.

@devantler devantler added this pull request to the merge queue Jul 13, 2026
@devantler devantler removed this pull request from the merge queue due to a manual request Jul 13, 2026
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Daily AI Engineer

Dequeued this exact-head-green PR before its merge-group deploy started because the preceding #2608 merge group failed on the same live systemic gates and is still healing main. The private tenant OCI sources remain denied, apps is not healthy, and github-config is blocked on the tracked kyverno-policies bootstrap/custom-property work (#2613; platform-template#24). Re-enqueue only after those live gates recover; no #2622 branch defect was found.

@devantler devantler added this pull request to the merge queue Jul 13, 2026
@devantler devantler removed this pull request from the merge queue due to a manual request Jul 13, 2026
@devantler

Copy link
Copy Markdown
Contributor Author

🤖 Generated by the Codex Daily AI Engineer instance.

Final queue evidence: run 29285334539 had its speculative deploy normally cancelled when the PR was dequeued, then this branch's cancellation-safe heal started after the serialized production lane became available and checked out main. The heal restored/reconciled four of five kustomizations and failed only on github-config: Repository, DefaultBranch, and TeamRepository for kyverno-policies remained InProgress, matching the one-time org-admin bootstrap tracked by devantler-tech/.github#97. The root GHCR/Flux source was no longer the terminal failure.

#2622 is out of the merge queue; the later pending run 29287280987 was cancelled before any job started. Keep this PR open until .github#97 is complete, then require a fresh exact-head queue run.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: 🫴 Ready

Development

Successfully merging this pull request may close these issues.

Heal production after cancelled merge-group deploys

1 participant