feat(project): manage a project's custom fields #143
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/YT-89-project-custom-fields"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
yt projectcould read a project but not configure one: nothing managed which custom fields were attached, so standing a project up stayed a click-path through Administration > Projects > Fields even when the rest of the setup was scripted. The failure mode is silent. Attaching a NEW field namedAI Agentinstead of the existing instance-level one produces a field that looks correct in the UI, carries its own empty bundle, makesyt issue set-field AUD-1 "AI Agent" Failedreturn HTTP 400 while the same command succeeds onDEV, and makes the runner's-Resolved AI Agent: Queuedquery match nothing.yt project fields <SHORT_NAME>lists the attached fields with their bundle name and id, which is what makes two same-named fields distinguishable at a glance. The bare form is kept here rather than replaced byfields list(both parse) because it is the form a setup script reaches for.fields add --field <NAME>attaches an existing instance-level field: the name is resolved against the paged prototype collection by exact match, and a name matching more than one prototype is refused with the candidate ids instead of guessed at. So is a--bundlename matching more than one bundle, which is the same mistake one level down. With--bundleomitted the bundle is taken from the prototype's existing attachments and only when every one of them agrees, so an attach copies what the other projects already share instead of inventing a fresh empty bundle.--create-type <FIELD_TYPE>creates the instance-level prototype first when no field of that name exists, so a project is not left half-configurable.fields remove --field <NAME>detaches, prompting unless--yesis given, matching theyt issue deleteconvention.Resolution is split from the write:
api::plan_attach_project_custom_fieldreturns anAttachFieldPlanthatapi::attach_project_custom_fieldexecutes, so--dry-runprints the byte-exact body the live path would post. The ids the body carries are explained in a separateresolvedblock rather than mixed into the payload, so the preview never shows a key the real request would not send. Both writes re-read the project afterwards and report a request the server accepted and then ignored, the same contract the team membership writes carry.Every one of the four new collection reads goes through
fetch_all_pages, including the prototype'sinstances, which is read from its own subresource rather than nested in the prototype entity because a nested collection cannot page (YT-83). The value-type maps (bundle_path_segment,project_custom_field_type) are closed lists probed against the live instance;ownedFieldandbuildhad no attachment to sample, so an existing instance's$typeis preferred over the map whenever one exists.Covered by fifteen new tests in
youtrack-client(fourteen against wiremock, one pure map assertion), two clap parse tests, and four integration tests that drive the real binary against a mock server with the POST and DELETE mounted atexpect(0), so a--dry-runthat started sending a mutation fails the build.#YT-89