fix(github): make branch protection usable and wire workflow_id to its endpoint - #7308
Conversation
…s endpoint
`github_update_branch_protection` could not be called. `restrictions` was a
required tool param with no subBlock anywhere in the block, so every run threw
"Restrictions is required for GitHub Update Branch Protection" before the
request. The other three body fields were `required: true` behind `mode:
'advanced'` subBlocks that are hidden by default, and their subBlock types did
not match their param types.
GitHub documents all four as required but nullable - "Set to null to disable" -
so "required" there means present in the body, which `null` satisfies. Sim's
`required: true` means the user must supply a non-empty value, which is strictly
stronger. The params are now optional and the body builder supplies the explicit
`null` GitHub demands for each field left unset, normalizing the editor's JSON
strings and the dropdown's 'true'/'false' along the way. A `restrictions`
subBlock is added.
`workflow_id` rendered for `github_list_workflow_runs` but the tool declared no
such param and always hit the repo-wide `/actions/runs`. It now selects
`GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs`, which GitHub
documents as accepting the same query filters.
No subBlock id is renamed or removed and no visibility is flipped.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@cubic review |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
All reported issues were addressed across 8 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
Greptile SummaryThe PR makes GitHub branch-protection updates callable with nullable settings and connects workflow-run filtering to GitHub’s per-workflow endpoint.
Confidence Score: 5/5The PR appears safe to merge. No blocking failure remains; the prior invalid-string coercion issue is resolved because only normalized
|
| Filename | Overview |
|---|---|
| apps/sim/tools/github/update_branch_protection.ts | Normalizes nullable branch-protection objects and booleans; the previously reported truthiness bug is fixed by accepting only unambiguous values. |
| apps/sim/tools/github/list_workflow_runs.ts | Selects the encoded per-workflow runs endpoint when a workflow identifier is supplied. |
| apps/sim/blocks/blocks/github.ts | Adds the missing restrictions field and aligns branch-protection JSON input metadata. |
| apps/sim/tools/github/types.ts | Updates parameter types for optional nullable protection fields and workflow identifiers. |
| apps/sim/tools/github/branch_protection_and_workflow_runs.test.ts | Covers nullable request construction, strict boolean normalization, endpoint selection, encoding, block wiring, and stale-value containment. |
Reviews (2): Last reviewed commit: "Merge remote-tracking branch 'origin/sta..." | Re-trigger Greptile
There was a problem hiding this comment.
1 issue found across 8 files
Confidence score: 4/5
- In
apps/sim/tools/github/branch_protection_and_workflow_runs.test.ts, the two “stale advanced value” tests expect the alias mapper to return{}forgithub_update_branch_protectionandgithub_create_issue, while the mapper only emits configuredGITHUB_PARAM_ALIASESentries. This may leave the intended stale-value behavior unclear or make the tests brittle—align the assertions with the current alias configuration and tool behavior.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/sim/tools/github/branch_protection_and_workflow_runs.test.ts">
<violation number="1" location="apps/sim/tools/github/branch_protection_and_workflow_runs.test.ts:229">
P2: These two 'stale advanced value' tests assert the alias-mapper output is {} for github_update_branch_protection and github_create_issue. That mapper only emits GITHUB_PARAM_ALIASES entries, and none of restrictions/workflow_id/enforce_admins/required_status_checks are aliases, so the assertion is always true and the tests cannot fail. They do not exercise the leak path (`shouldSerializeSubBlock`/generic-handler's `{...inputs, ...params(inputs)}` merge) the comments describe, so they provide no regression protection against stale advanced values leaking between operations. Assert on the full merged inputs that generic-handler feeds to the tool (or a test that toggles the operation after filling an advanced field) instead of the alias mapper.</violation>
</file>
Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.
Fix all with cubic | Re-trigger cubic
# Conflicts: # apps/sim/tools/generated/tool-metadata.ts
|
@cubic review |
@waleedlatif1 I have started the AI code review. It will take a few minutes to complete. |
# Conflicts: # apps/sim/tools/generated/tool-metadata.ts
Summary
Two verified GitHub defects: an operation that could never run, and a UI field wired to nothing.
github_update_branch_protectionwas unusablePUT /repos/{owner}/{repo}/branches/{branch}/protectiondocuments four body fields as required but nullable —required_status_checks,enforce_admins,required_pull_request_reviews,restrictions, each "Set to null to disable."GitHub's "required" means present in the body, satisfiable by
null. Sim'srequired: truemeans the user must supply a non-empty value —validateRequiredParametersAfterMergerejectsnull,undefinedand''outright, so Sim could not express GitHub's disable case at all. Combined withrestrictionshaving no subBlock anywhere in the block, every call threwRestrictions is required for GitHub Update Branch Protectionbefore reaching the network.required: falserequest.bodynow emits an explicitnullfor each unset field instead of dropping the key, preserving GitHub's "present but null = disable" contract'true'/'false'to booleans, fixing the type mismatches without touchingtools.config.toolrestrictionssubBlock, so the operation finally has full param coverageworkflow_idrendered but did nothingThe block showed a
workflow_idfield forgithub_list_workflow_runs, but the tool declared no such param and always hit the repo-wide/actions/runs.GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runsexists, takes the identical query set, and returns the identical response schema — so this wires the field rather than deleting a working affordance. The segment isencodeURIComponent-escaped.Design notes
Normalization lives in the tool's
request.body, not inGITHUB_PARAM_ALIASES. Nothing here needs renaming, and the tool body covers the agent tool-calling path identically while carrying zero cross-operation clobber risk — the alias mapper is scoped by operation precisely because advanced fields serialize without their condition being evaluated.The three pre-existing subBlocks stay
mode: 'advanced'. Withrequired: falsethat is now correct — they are genuinely optional — and flipping them would have changed visibility.updateBranchProtectionV2Toolsharesparamsandrequestby reference and inherits both fixes; a test asserts it.Backwards compatibility
restrictions). Subblock-ID stability check passes.required: only ever loosened (true→false), never tightened — no saved workflow can newly fail validation.visibilityandmode: unchanged on every existing param.The only behavior change is that an operation which always threw now runs, and a field that was discarded now takes effect.
Testing
apps/sim/tools/github/branch_protection_and_workflow_runs.test.ts— 41 tests; 151 pass acrossblocks/blocks/githubandtools/github.Verified red-first per guard, reverting each individually:
required: falseon the four paramsrestrictionssubBlockjsoninput typesworkflow_idparamencodeURIComponentTwo of those tests initially passed with their guard deleted and were rewritten. The presence-guard test used
toEqual, which treats an undefined-valued key as absent — so{title: 'v1.0', description: undefined}compared equal to{title: 'v1.0'}. It now asserts onObject.keys, which is the distinction that actually matters when the provider spreads the transform over a model's tool-call arguments. The scoping test used real param names instead of alias source names and was rewritten to usemilestone_title/gist_public/fork_name.Includes coverage that a stale advanced value from another operation cannot leak into anything wired here.
bun run lint,type-check,check:audits(39 audits),tool-metadata:check,docs:check,integration-catalog:check,deployment-config:checkandcheck-block-registry.ts origin/stagingall pass. Regenerated artifacts committed.Deferred:
github_check_starConfirmed dead and deliberately left alone. GitHub answers
204for starred and404for not-starred; the shared executor throws on!response.okbeforetransformResponseruns, sostarred: falseis unreachable and the ordinary negative answer surfaces as a failure.Three options exist — convert to an internal operation (isolated, but leaves the shared retry/DNS-pinning/size-limit machinery for one trivial GET), add an opt-in like
expectedErrorStatusesonToolConfig.request(generalizes, but sits on the hot path for every tool), or have callers read thestatusthe thrown error already carries.Worth noting for that decision: 13 GitHub tools use the
status === 204pattern, but 12 are mutations where any non-204 genuinely is an error — their false branch is harmless dead code, not a defect.check_staris the only GitHub tool where the non-2xx status carries meaning; the comparable live cases elsewhere areelasticsearch/get_document.tsanddelete_document.ts. That makes it a three-tool problem rather than a ten-tool one, which argues against paying for the shared-executor change.Type of Change
Checklist