Skip to content

Fix cards column color 404 from missing bucket in URL#455

Closed
packagethief wants to merge 1 commit intomainfrom
fix/cards-column-color-bucket-path
Closed

Fix cards column color 404 from missing bucket in URL#455
packagethief wants to merge 1 commit intomainfrom
fix/cards-column-color-bucket-path

Conversation

@packagethief
Copy link
Copy Markdown
Member

Summary

  • basecamp cards column color was sending PUT /{account}/card_tables/columns/{id}/color.json (no bucket segment) and 404ing on every invocation. Reported in Basecamp card 9825845889.
  • Root cause is in basecamp-sdk/go v0.7.3: the generated client at pkg/generated/client.gen.go:7757 builds the path without /buckets/{bucket_id}. The SDK's pkg/basecamp/url-routes.json (lines 165, 183, 200) shows the same bucket-less pattern for GetCardColumn, SetCardColumnColor, EnableCardColumnOnHold, DisableCardColumnOnHold. Basecamp tolerates the bucket-less path for the read/update endpoints but rejects it for /color.json and /on_hold.json.
  • This PR works around the SDK bug for color only — on-hold and no-on-hold have the same problem and need separate fixes.

Reproduction (verified live)

  • Broken: PUT /3642500/card_tables/columns/7103332776/color.json404 Not Found
  • Correct: PUT /3642500/buckets/36395297/card_tables/columns/7103332776/color.json200 OK

Fix

internal/commands/cards.go:

  • newCardsColumnColorCmd(project *string) — accept the project pointer plumbed from the cards command group (cards.go:1274), matching the existing pattern used by column show, column move, etc.
  • Resolve the bucket from URL > --in/--project flag > config > interactive (the same 8-line pattern repeated in 23 sites across 8 command files).
  • Send the PUT via app.Account().Put(ctx, "/buckets/<id>/card_tables/columns/<id>/color.json", body) — the existing raw API escape hatch already used by todos.go:1157 for similar SDK gaps. This bypasses the broken generated client path.
  • Re-fetch the column via SDK Get (which works on the bucket-less path) so the response is still a typed *CardColumn.

internal/commands/cards_test.go:

  • Update the existing TestCardsColumnColorShowsHelp call site for the new signature.

Verified live

  • basecamp cards column color 7103332776 --color blue --account 3642500 --in 36395297 -vvPUT .../buckets/36395297/.../color.json → 200, color updated.
  • URL form basecamp cards column color https://3.basecamp.com/.../columns/7103332776 --color blue → resolves project from URL, hits correct path, returns 200.

Test plan

  • make fmt-check vet test check-bare-groups check-skill-drift check-surface all pass locally.
  • Repro on real account: command was 404ing; with fix, returns 200.
  • URL-arg form resolves bucket from the URL.
  • CI green.

Follow-ups (separate, not blocking this PR)

  1. File an issue on basecamp-sdk for the missing bucketId path parameter on SetCardColumnColor, EnableCardColumnOnHold, DisableCardColumnOnHold (and review whether GetCardColumn/UpdateCardColumn should also include it now that the API requires it for some sibling endpoints).
  2. Apply the same workaround in newCardsColumnOnHoldCmd and newCardsColumnNoOnHoldCmd — they 404 today for the same reason.
  3. Once the SDK is fixed and bumped, this PR's raw-PUT workaround can be reverted to a clean app.Account().CardColumns().SetColor(...) call.

🤖 Generated with Claude Code

`basecamp cards column color` was sending PUT requests without the
`/buckets/{id}` path segment, causing every invocation to 404.

The SDK's generated client (basecamp-sdk/go v0.7.3) builds the path
`/{accountId}/card_tables/columns/{columnId}/color.json` — missing the
bucket. Basecamp tolerates this for `Get`/`Update` but rejects it for
`/color.json`, so the command was unusable.

Workaround in the CLI until the SDK is fixed: resolve the bucket from
the URL, `--in`/`--project` flag, or config (the same pattern as
`cards column show` and others), then send the PUT via the raw API
helper `app.Account().Put` to the correct bucket-scoped path. Re-fetch
through the SDK `Get` so the typed `*CardColumn` return shape is
preserved.

Same SDK bug affects `cards column on-hold` and `cards column
no-on-hold` (`/on_hold.json`); those are not addressed here.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 28, 2026 18:19
@github-actions github-actions Bot added commands CLI command implementations tests Tests (unit and e2e) bug Something isn't working labels Apr 28, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes basecamp cards column color 404s by bypassing a Basecamp Go SDK route bug and issuing a bucket-scoped PUT .../color.json request.

Changes:

  • Plumbs the project/--in pointer into newCardsColumnColorCmd and resolves the bucket before setting the color.
  • Uses app.Account().Put() against /buckets/<id>/card_tables/columns/<id>/color.json, then re-fetches the column via the SDK Get.
  • Updates the existing help test to use the new command constructor signature.

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.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
internal/commands/cards.go Updates the column color command to resolve bucket and use a raw bucket-scoped PUT workaround.
internal/commands/cards_test.go Updates the help-test call site for the new newCardsColumnColorCmd(project *string) signature.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1760 to +1767
// Resolve project - use URL > flag > config, with interactive fallback.
// The color endpoint requires a bucket-scoped path (PUT /buckets/<id>/card_tables/columns/<id>/color.json).
projectID := *project
if projectID == "" && urlProjectID != "" {
projectID = urlProjectID
}
if projectID == "" {
projectID = app.Flags.Project
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The project-resolution precedence doesn’t match what’s stated here (and in the PR description). The code initializes projectID from the --in/--project pointer and only falls back to urlProjectID if that’s empty, so flags override the URL. Either update the precedence logic to prefer urlProjectID when present, or adjust the comment/PR description to reflect the actual behavior to avoid confusion and unexpected bucket selection when both are provided.

Copilot uses AI. Check for mistakes.
Comment on lines +1784 to +1787
path := fmt.Sprintf("/buckets/%s/card_tables/columns/%d/color.json", resolvedProjectID, columnID)
if _, err := app.Account().Put(cmd.Context(), path, map[string]string{"color": color}); err != nil {
return convertSDKError(err)
}
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

This new raw PUT to a bucket-scoped /color.json endpoint is the core of the fix, but there’s no unit test asserting that the command actually issues a PUT to /buckets/<project>/card_tables/columns/<id>/color.json (and that URL-form args populate the bucket). Since cards_test.go already uses custom RoundTrippers for request-path assertions, consider adding a transport-backed test that captures the PUT path/body and validates the bucket segment is present.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 2 files

@packagethief
Copy link
Copy Markdown
Member Author

Root-cause SDK fix opened: basecamp/basecamp-sdk#291

That PR adds bucketId to the Smithy spec for SetCardColumnColor, EnableCardColumnOnHold, and DisableCardColumnOnHold, regenerates all six language SDKs, and updates the Go / TypeScript / Ruby tests. Once it ships and make bump-sdk brings it in here, the raw-Put workaround in this PR can be reverted to a clean app.Account().CardColumns().SetColor(ctx, bucketID, columnID, color) call.

Recommend keeping this PR as a stopgap until the SDK release lands, since customers (per card 9825845889) are blocked today.

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

Labels

bug Something isn't working commands CLI command implementations tests Tests (unit and e2e)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants