Skip to content

Exit non-zero from sync when a push or pull request fails [patch] - #338

Open
matt-edmondson wants to merge 1 commit into
mainfrom
fix/333-sync-push-failure-exit
Open

matt-edmondson wants to merge 1 commit into
mainfrom
fix/333-sync-push-failure-exit

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #333

What was wrong

SyncService.RunAsync always returned 0 once it reached the push phase. PushToRemoteAsync returned only the repos it had pushed, and PushDirectoryAsync and SyncPullRequestOpener only printed their failures. So ktools sync --auto-push exited 0 after a failed git pull, a rejected push, or a rejected pull request, and the synced commits stayed local without anyone noticing.

The fix

  • PushToRemoteAsync now returns a PushResult(Pushed, Failed) record. Failed lists the repos whose pull or push failed.
  • SyncPullRequestOpener.OpenAsync, and SyncService.OpenPullRequestsAsync through it, now return the number of repos where opening a pull request failed. That covers a gh pr create that exits non-zero and an API create that returns nothing. As before, these are not counted as failures:
    • a repo skipped because it has no GitHub remote or no recorded base branch
    • a branch that already has an open pull request
    • a run with no gh and no token
  • When either step reports a failure, RunAsync lists the repos that failed to push and the number of pull requests that failed, then exits 1. Branches are still restored in the finally before any of this, and one repo's failure still doesn't stop the remaining repos.

Tests

  • RunAsyncExitsNonZeroWhenAnAutoPushFails covers the issue's acceptance case. The workspace holds a real clone of a bare origin with one unpushed commit authored by KtsuTools, so --auto-push finds it pushable. The run uses a process service whose git pull/git push fail, and the test asserts exit 1. With main's SyncService.cs, this test fails on Assert.AreEqual(1, exit), because main returns 0.
  • RunAsyncExitsZeroWhenEveryAutoPushSucceeds uses the same workspace with a successful pull and push. It asserts exit 0 and that the commands were pull, then push.
  • PushToRemoteAsyncReportsARepoWhosePushFailed checks that a rejected push lands in Failed and not in Pushed.
  • The existing opener tests now also check the return value. Two rejected gh creates return 2, a rejected API create returns 1, and a successful create returns 0.
  • The full suite passes: 388/388.

CI note

On main, restore currently fails with NU1903: SixLabors.ImageSharp 3.1.12 has a known high-severity advisory. That failure is unrelated to this change, and it is the same one #337 and #334 report. To run the build and tests above locally, I passed -p:WarningsNotAsErrors=NU1903. This PR does not touch the ImageSharp reference, so CI will stay red on that step until main is fixed.


Generated by Claude Code

SyncService.RunAsync returned 0 once it reached the push phase, whatever
happened there. PushToRemoteAsync only reported the repos it pushed, and the
pull request opener only printed its failures, so `ktools sync --auto-push`
exited 0 after a rejected push left the synced commits local.

PushToRemoteAsync now returns the repos it failed to push alongside the ones
it pushed, SyncPullRequestOpener.OpenAsync returns how many pull requests it
could not open, and RunAsync lists the failures and exits 1 when there are
any. Repos skipped for having no GitHub remote or no base branch still do
not count as failures.

Fixes #333

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW6DQQw6JpYVSCPgTzR

Copy link
Copy Markdown
Contributor Author

The ci / .NET / Test on ubuntu-latest, macos-latest and windows-latest checks fail at restore, before any test runs. The cause is error NU1903: SixLabors.ImageSharp 3.1.12 has a known high-severity vulnerability (GHSA-v76p-62qx-wwq2).

The same three checks are red on main at 3382f1d, and this PR doesn't touch the ImageSharp reference, so the failure isn't caused by this PR.

I don't know of a fix I could bring into this PR. Dependabot's bump to 3.2.0 in #270 is also red, because 3.2.0 needs a Six Labors license in CI (the same problem as ktsu-dev/IconHelper#155). Deciding between a license, a pin with the advisory suppressed, or replacing ImageSharp is a maintainer call.

Locally, with -p:WarningsNotAsErrors=NU1903, the full suite passes: 388/388.


Generated by Claude Code

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.

ktools sync --auto-push exits 0 when the push or pre-push pull fails, leaving the commits local with a success exit code

1 participant