fix: full-sync NOP results without check run + idempotent ruleset create - #1047
Open
decyjphr wants to merge 2 commits into
Open
fix: full-sync NOP results without check run + idempotent ruleset create#1047decyjphr wants to merge 2 commits into
decyjphr wants to merge 2 commits into
Conversation
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
A ruleset POST is not idempotent. When Octokit retries a create that already succeeded, or a repo is processed by two overlapping syncs (full sync racing with repository.created), the second create fails with 422 'Name must be unique'. Reconcile by looking the existing ruleset up by name and updating it in place. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Improves robustness of dry-run full-sync execution and ruleset creation by preventing crashes when webhook-only payload fields are missing and by making ruleset creation effectively idempotent under retries/concurrency.
Changes:
- Guarded NOP/dry-run result handling to avoid dereferencing
payload.check_run/payload.repositoryand to log a value-free summary instead of attempting check-run reporting. - Added reconciliation logic for
POST /rulesetsduplicate-name422responses by re-fetching the existing ruleset and updating it in place. - Added unit tests covering both the full-sync dry-run guard and the ruleset duplicate-name reconciliation behavior.
Show a summary per file
| File | Description |
|---|---|
| test/unit/lib/settings.test.js | Adds coverage ensuring full-sync dry runs without check_run/repository log a value-free summary and do not call the Checks API. |
| test/unit/lib/plugins/rulesets.test.js | Adds coverage for reconcile-by-update on duplicate-name 422s for both repo/org rulesets, and verifies other 422s still surface. |
| lib/settings.js | Adds an early-return guard for NOP full-sync runs missing webhook payload fields, logging summary at info and full results at debug. |
| lib/plugins/rulesets.js | Adds duplicate-name detection and reconciliation path to make ruleset creation resilient to retried/concurrent POSTs. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Lite
| if (!match) { | ||
| return this.handleError(e) | ||
| } | ||
| return this.update(match, attrs) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Two related robustness bugs surfaced during full-sync and repo-creation flows:
Full-sync NOP runs crashed. A NOP run triggered outside the webhook flow (e.g. the full-sync entrypoint) builds a minimal payload that has no
check_runorrepository.handleResultsunconditionally dereferencedpayload.check_run.idandpayload.repository.owner.login, so a scheduled or CLI dry-run died after doing all its work instead of reporting a plan. (Incorporates PR fix(settings): handle nop mode results when check run is missing #1018.)Ruleset creation failed with
422 "Name must be unique".POST /rulesetsis not idempotent. When Octokit's retry/auth-app layer re-sends a create that already succeeded (observed withretryCount: 1), or a repo is processed by two overlapping syncs (a full sync racing with therepository.createdwebhook), the second create hits a duplicate-name 422 even though the ruleset now exists, failing the run.Approach
lib/settings.js(NOP full-sync guard): When the payload lackscheck_runorrepository, write the deduplicated dry-run results to the log and return before any check-run/PR-comment reporting. The full diff can contain sensitive config values (e.g. Actions variables), so it goes todebug(passed as an object so it is only serialized when debug is emitted) whileinfogets a value-free summary. The webhook flow is untouched.lib/plugins/rulesets.js(idempotent create): On a422 "Name must be unique"fromadd(), reconcile instead of failing: re-fetch existing rulesets viafind(), match by name viacomparator, andupdate()the existing ruleset in place. Any other error (including a non-uniqueness 422) still surfaces normally. Applies to both repo and org scope.Notes for reviewers
update()preferring the existing ruleset's numeric id, so a config that carries noid(the normal case) is updated against the real ruleset.Tests
handleResultscoverage: full-sync dry runs without a check run / without a repository log a value-free summary and never call the checks API.