Repository navigation
feat(cli): guard and close request-field gaps in curated commands - #210
Merged
Merged
Conversation
POST /incident/merge accepts remove_source_incidents (default false: the source incidents are closed and kept with a merge timeline entry; true: they are deleted). The hand-written `incident merge` command shadows the generated one and only exposed --source, so the field was unreachable from the CLI. Expose it as an opt-in bool flag; the default request body is unchanged.
A curated command that takes a generated command's name drops the generated twin, and with it every flag the curated one does not re-declare. Check each shadowed operation's top-level request fields against the curated flags, with explicit routes for renamed flags, positional arguments, and deliberately omitted fields.
Flags added: - alert list: --alert-ids, --alert-keys, --asc, --by-updated-at - alert-event list: --asc Remaining request fields are routed to the existing flags that already set them (--severity, --channel, --integration, --since, --until, --page, --active, --muted, --integration-type, --comment-file), or omitted with a stated reason (page cursor, single-valued orderby).
…ands Flags added: - audit search: --is-write, --is-dangerous, --request-id - change list: --orderby, --asc, --include-events, --filters (JSON array of key/oper/vals) - channel list: --channel-ids, --channel-name, --query, --is-my-team, --is-my-starred, --is-my-managed, --is-brief, --orderby, --asc, --page, --limit - field list: --query, --creator-id, --orderby, --asc Every new flag is sent only when set, so default request bodies are unchanged. Differently named existing flags are routed to their wire fields for team list/delete, change list, audit search and channel list.
Flags added: - incident list: --incident-ids, --acker-ids, --closer-ids, --creator-ids, --responder-ids, --team-ids, --asc, --ever-muted, --is-my-channel, --is-my-team, --is-rare, --is-snoozed - incident feed: --asc, --types - incident merge: --title, --comment-file - incident comment: --comment-type-id Fields already carried by an existing flag or positional argument are declared in curatedFieldRoutes; the two fields that cannot be sent are recorded there with the reason.
# Conflicts: # internal/cli/curated_fields_test.go
channel list --name matched names client-side on the returned page only, so with paging it missed channels on other pages, and it duplicated the server-side query filter. Send the escaped text as the server's query regex instead (same case-insensitive substring semantics, now also over the description), drop the separate --query flag, and print the server's total. Also list the valid --orderby values, and state precisely why the audit and alert-event cursor/order fields are not exposed.
- incident create: --field key=value (now sendable with go-flashduty
v0.15.12), --assign-emails, --escalate-rule-id, --escalate-layer.
- --field values are converted by the field's type from /field/list:
checkbox -> bool, multi_select -> string array (comma-separated or a
JSON array), single_select/text -> string. Unknown names are rejected.
- incident update --field sent field_value as {"value": v}; the server
takes the raw value, so every update was rejected. Send the typed
value directly.
- Test helper: reset every slice-valued flag between runs, not only
string slices, so int slices no longer leak across tests.
The layer index only applies to an escalation rule; on its own the flag was silently ignored and the incident was created unassigned.
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.
Summary
A curated (hand-written) command that takes a generated command's name drops the generated twin (
genAddLeaf). Every request field the curated command does not re-declare is then unreachable from the CLI.TestGeneratorTargetsFullSpeconly checks coverage per operation, so these gaps were invisible. For example,incident mergecould not sendremove_source_incidents.This PR adds a field-level guard and closes every existing gap.
Guard:
TestCuratedCommandsCoverRequestFieldsThe test rebuilds the generated tree on a bare root and finds each curated command that shadows a generated twin (19 today). For every top-level request field of that operation, read from the spec and including
allOf/oneOfcomposition, it requires one of the following:curatedFieldRoutes:"--flag"(a renamed flag),"args"(positional), or"omit: <reason>".Routes are validated too. A routed flag must exist, the field must still be in the spec, there must be no redundant same-name routes, and the command must still shadow a twin. A field the API adds later now fails the test instead of silently disappearing.
Gaps closed
101 gaps across 19 commands. Each one was resolved by adding a flag, routing it to an existing flag or argument, or omitting it with a stated reason.
--incident-ids --acker-ids --closer-ids --creator-ids --responder-ids --team-ids --asc --ever-muted --is-my-channel --is-my-team --is-rare --is-snoozed--remove-source-incidents --title --comment-file--comment-type-id--types --asc--alert-ids --alert-keys --asc --by-updated-at--asc--is-write --is-dangerous --request-id--orderby --asc --include-events --filters(JSON array of{key, oper, vals})--channel-ids --channel-name --is-my-team --is-my-starred --is-my-managed --is-brief --orderby --asc --page --limit--query --creator-id --orderby --ascFree-text fields an agent might write use
--*-file(for example--comment-file), never an inline string. When a new flag is not set, the request body is byte-identical to before.Behavior change:
channel list --name--nameused to filter client-side on the returned page only, so with paging it missed channels on other pages. It now sends the escaped text as the server'squery. The match is the same case-insensitive substring, now also over the description. The duplicate--queryflag is gone, and the footer prints the server total.Custom fields and assignment on
incident create(go-flashduty v0.15.12)go-flashduty used to generate
CustomFieldValuesasstruct{}, which dropped every value. That is fixed in flashcatcloud/go-flashduty#90, released as v0.15.12. This PR bumps to that version and adds the following toincident create:--field key=value--assign-emails--escalate-rule-id--escalate-layer--fieldvalues are typed from the field definitions returned by/field/list:Unknown field names are rejected.
Fix:
incident update --fieldincident update --fieldsentfield_valueas{"value": v}, but the server reads the raw value, so every custom-field update was rejected. It now sends the typed value directly. The generatedincident ack/incident resolvecommands also carrycustom_fieldsafter the bump.Test plan
make checkpasses: fmt, lint (0 issues), test, buildmake check-cards--remove-source-incidents. The source is closed and kept without the flag, and deleted (Incident not found) with it.incident create --field project=n9e,duty控制台 --assign-emails …storedprojectas an array, and the responder was resolved from the email.incident update --field test_checkbox=false --field afdasf='["123","567"]' --field abc=456stored a bool, an array, and the string"456".--incident-ids,--responder-ids,--creator-ids 0,feed --types i_merge,channel list --namepage 2, and others).