feat(forms): extend the persisted batch primitive to Forms (forms.batchUpdate is the only mutation endpoint, exposed one request at a time)
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 8.4k
- Forks
- 697
- Avg merge
- 15h 39m
- Merged PRs (30d)
- 89
Description
The gap
The Forms API has exactly one mutation endpoint: forms.batchUpdate, taking an ordered list of CreateItem / UpdateItem / MoveItem / DeleteItem / UpdateFormInfo / UpdateSettings requests.
gog forms exposes that endpoint one request at a time: add-question, delete-question, move-question, update, publish. Building a form is therefore one API call per question, and gog batch cannot help because it is Docs-only. gog batch begin accepts --doc and nothing else, and no gog forms command carries --batch.
The cost
Documented Forms quota is 150 write requests per minute per user per project (https://developers.google.com/workspace/forms/api/limits), so this is less likely to 429 than Docs, Sheets or Slides at 60. The argument here is ordering and atomicity rather than quota.
A generated form is the normal case for this command: a survey or an intake form built from a source file, thirty to sixty questions. Today that is thirty to sixty sequential calls, each of which can fail on its own, leaving a half-built form with no clean way back. A caller who wants a reproducible form has to write its own idempotence, because re-running the script duplicates every question rather than replacing it.
Index-based positioning makes the per-call shape worse than it looks. add-question inserts at an index, and every subsequent insert shifts the indices the caller computed. A script that builds thirty questions has to track index drift across thirty separate calls, where a single forms.batchUpdate applies the whole ordered list against one starting state.
What a caller has to do today
Compute indices defensively, re-read the form between calls, and accept that a mid-run failure leaves a partial form. Or drop to a Google API client library and post one batchUpdate, which is what the API was designed for.
Proposed surface
Same shape as the shipped Docs batch:
gog batch begin --form=<id> [--name=<label>]
gog forms add-question --batch=<id> ...
gog forms delete-question --batch=<id> ...
gog forms move-question --batch=<id> ...
gog forms update --batch=<id> ...
gog batch end <id>
--dry-run, --continue-on-error and the revision lock behave as they do for Docs. forms.batchUpdate carries includeFormInResponse and a writeControl with requiredRevisionId, so the revision lock maps directly.
get, raw, responses and watch are reads or a different endpoint and stay out.
A batched path also opens a forms equivalent of building a whole form from a source file in one submission, which is the workload most callers actually want and cannot express today.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the shipped Docs batch flow behind gog batch begin, gog batch end, and the existing --batch command handling, then trace the Forms entry points for add-question, delete-question, move-question, and update. Compare their request handling with the forms.batchUpdate endpoint and define how dry runs, continuation, and revision locks behave. Done means Forms mutations can be queued and submitted atomically through the proposed batch commands while reads and watch remain unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- api, cli
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100