Skip to content

Add Topics.Update to rename a thread subject - #220

Open
jeissonneira wants to merge 2 commits into
basecamp:mainfrom
jeissonneira:topics-update-rename
Open

jeissonneira wants to merge 2 commits into
basecamp:mainfrom
jeissonneira:topics-update-rename

Conversation

@jeissonneira

@jeissonneira jeissonneira commented Sep 17, 2026 •

Copy link
Copy Markdown

The gap

HEY lets you rename a thread’s subject in the web UI. The SDK’s Topics service can read and trash topics, but it has no write for that rename — so a CLI command cannot go through the typed SDK the way Workflows().Update does.

The change

Topics().Update(ctx, topicID, name) PATCHes /topics/{id}.json with {"name":"…"} — the same JSON body the web app sends (field is name, not subject).

Success is HTTP 302 to the HTML topic URL. The redirect is captured and not followed, matching PatchForm / doBodyRequest mutations (CheckResponse stays 2xx-only; this path does not go through it).

Not in OpenAPI, so this is a hand-written wrapper next to Trash / Move, via doBodyRequest with Content-Type: application/json.

This is a real JSON endpoint HEY’s own UI calls, not an HTML-form scrape of an undocumented action.

Tests

TestTopicsService_Update* covers PATCH path, JSON name (not subject), 302 without follow, and error surfacing.

GOWORK=off go test ./pkg/hey/ green.

Follow-up

hey-cli can then add hey thread rename <id> --name "…" on top of this, mirroring hey workflow update / rename.


Summary by cubic

Adds Topics().Update so callers can rename a thread subject the same way HEY's web UI does, now modeled in Smithy and regenerated across Go, Kotlin, Rust, Swift, and TypeScript.

  • PATCHes /topics/{topicId} with {"name":"…"} — the field is name, not subject.
  • Treats HTTP 302/303 to the topic URL as success and does not follow the redirect; the operation is idempotent and retries 429/503 up to twice.
  • Conformance tests and runners verify the PATCH path, JSON body, redirect capture, and error surfacing.

Written for commit fa7eb36. Summary will update on new commits.

Review in cubic

PATCH /topics/{id}.json with {"name":…}; treat 302 as success without following.
Copilot AI balanced review requested due to automatic review settings September 17, 2026 05:51

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The operation must use the model-first pipeline and include cross-SDK and conformance coverage.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds topic renaming through a JSON PATCH endpoint in the Go SDK.

Changes:

  • Adds TopicsService.Update.
  • Adds request, redirect, and error tests.

[!TIP]
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

File summaries
File Description
go/pkg/hey/topics.go Implements topic renaming.
go/pkg/hey/topics_test.go Tests the new request behavior.
Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 2
  • Review effort level: Balanced (auto)

Note

Copilot is running an experiment and ran this review at Balanced.


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread go/pkg/hey/topics.go
// HTML topic URL; the redirect is captured and not followed (same as PatchForm mutations).
// This is not in the OpenAPI model, so it goes through doBodyRequest rather than a
// generated client method.
func (s *TopicsService) Update(ctx context.Context, topicID int64, name string) error {
Comment thread go/pkg/hey/topics_test.go
}
}

func TestTopicsService_UpdateRenamesViaJSONPatch(t *testing.T) {
Rename a thread via PATCH /topics/{topicId} with flat {"name":…}.
HEY answers 302; treat it as success and do not follow (heyEmptyOn +
captureRedirects in Rust/Swift/Kotlin generators; Go still sends through
doBodyRequest). Conformance path fixture and runners wired.
@jeissonneira

Copy link
Copy Markdown
Author

Addressed the Copilot review on the model-first path:

  • Smithy: UpdateTopic (PATCH /topics/{topicId}) with flat UpdateTopicRequestContent{name}, registered on the service, removed from excluded-routes.json.
  • @heyEmptyOn(statusCodes: [302, 303]): 302/303 is success; clients must not follow (Location is HTML / often 403).
  • Regenerated Go / Rust / TypeScript / Kotlin / Swift from the model.
  • Go wrapper: still uses doBodyRequest so the 302 is captured (generated http.Client follows redirects). Body type is the generated UpdateTopicRequestContent.
  • Rust / Swift / Kotlin generators: emit capture_redirects / captureRedirects when emptyOn includes 302/303 so the generated update methods match the wire.
  • Conformance: path fixture for body + 302; runners wired (Go also uses ErrUseLastResponse on the generated client so a lone 302 mock does not get followed).

Go unit tests + full Go conformance: 196/196 green locally.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants