Skip to content

[CMPT-5389] feat(pipelines): add dr pipeline command behind feature gate with shared infrastructure - #517

Merged
ajalon1 merged 12 commits into
datarobot-oss:mainfrom
sunny2get:cmpt-5391/pipelines-base
May 27, 2026
Merged

[CMPT-5389] feat(pipelines): add dr pipeline command behind feature gate with shared infrastructure#517
ajalon1 merged 12 commits into
datarobot-oss:mainfrom
sunny2get:cmpt-5391/pipelines-base

Conversation

@sunny2get

@sunny2get sunny2get commented May 20, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Wires dr pipeline into the CLI root command behind the DATAROBOT_CLI_FEATURE_PIPELINE feature gate — the command is hidden unless DATAROBOT_CLI_FEATURE_PIPELINE=true is exported
  • Introduces internal/pipeline/ shared infrastructure: transport.go (HTTP client helpers, decodeHTTPError, doJSON, doDelete), scope.go (draft/locked scope resolution + --scope/--version flag semantics), and time.go (RFC3339 formatting utilities)
  • Adds internal/drapi/client.go and fixes raw viper imports in internal/drapi/get.go and internal/drapi/client_test.go to use internal/config/viperx (required by depguard)
  • No subcommands yet — this PR exists solely to prove the gate, compile, and test the shared layer before CRUD operations land in the next PR

This is PR 1 of 6 in a stacked series:

PR Branch Adds
1 (this) cmpt-5391/pipelines-base Feature gate + shared infrastructure
2 cmpt-5391/pipelines-crud create/list/get/update/delete/lock/version/graph
3 cmpt-5391/pipelines-runs run subcommand group
4 cmpt-5391/pipelines-inputs input subcommand group
5 cmpt-5391/pipelines-schedules schedule subcommand group
6 cmpt-5391/pipelines-environments environment subcommand group

Test plan

  • go build ./... — compiles cleanly
  • go test ./cmd/pipeline/... ./internal/pipeline/... ./internal/drapi/... — all pass
  • golangci-lint run ./cmd/pipeline/... ./internal/pipeline/... — zero issues
  • DATAROBOT_CLI_FEATURE_PIPELINE=false go run main.go pipeline — command hidden (unknown command error)
  • DATAROBOT_CLI_FEATURE_PIPELINE=true go run main.go pipeline --help — command visible, no subcommands listed

🤖 Generated with Claude Code


Note

Medium Risk
Medium risk because it refactors shared internal/drapi token resolution used by all HTTP helpers (including --skip-auth behavior), which could impact authentication/header injection across commands.

Overview
Introduces a new feature-gated top-level dr pipeline/dr pipelines command (no subcommands yet), wires it into the root command, and documents it in the command reference.

Adds shared pipelines API infrastructure under internal/drapi/pipeline for draft vs locked scope URL construction (ResolveScope/PipelinePath), parsing pipelines-api naive UTC timestamps (Time), and lightweight JSON request/DELETE helpers with improved FastAPI-style error detail extraction.

Refactors internal/drapi auth handling by centralizing the memoized token in auth.go and adding resolveToken() so --skip-auth can source the token from viper config without network verification; updates Get/Post/Patch/Delete to use this resolver.

Reviewed by Cursor Bugbot for commit dc1d016. Configure here.

@ajalon1 ajalon1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

General questions about internal/pipelines. It's a style thing mostly, but you should rename the package internal/drapi/pipelines since almost all of this has to do with API handling.

I'm also wondering about the overall architecture. This feels like there will be a level of strong coupling between the command code and the API code in internal/pipelines. The Workload API folks settled on a filesapi Client interface that hides all of this detail from the command code. I'd suggest looking at that.

Requesting changes for:

  • command name
  • hiding docs from mkdocs TOC
  • removing getToken memoization
  • dealing w. resolveToken refactor

Comment thread cmd/pipelines/cmd.go Outdated
Comment thread internal/pipelines/scope.go Outdated
Comment thread docs/commands/pipeline.md
Comment thread docs/mkdocs.yml Outdated
Comment thread internal/drapi/client.go
Comment thread internal/drapi/pipeline/time.go Outdated
Comment thread internal/drapi/client.go
Comment thread internal/drapi/get.go
}

return config.GetAPIKey(context.Background())
}

@ajalon1 ajalon1 May 20, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Unlike the change to getToken(), I think this one is worth doing, but this is not a complete refactor; drapi.post, .delete, .patch should use it.

You can either make those changes here, or add a TODO and pull everything out into a separate PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'll do the refactor on post/delete/patch and move this function into auth.go since that would seem more natural place for it after the refactors

Comment thread cmd/pipeline/cmd.go
@ajalon1

ajalon1 commented May 20, 2026

Copy link
Copy Markdown
Contributor

I like the direction you're going with token memoization -- I think it will clean up some small bits of our auth story -- but you either need to complete the refactors here or do them separately.

Also, scope.go took me a while to parse, but it actually seems pretty clear and clean. Hopefully easy for your team to manage going forward. :)

@ajalon1

ajalon1 commented May 21, 2026

Copy link
Copy Markdown
Contributor

I just realized that #493 already tackles the getToken memoization issues. Definitely pull out getToken() refactors. :)

@sunny2get

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit dc1d016. Configure here.

Comment thread internal/drapi/auth.go Outdated

@ajalon1 ajalon1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM once PR checks are green

Comment thread internal/drapi/auth.go Outdated
@sunny2get sunny2get changed the title [CMPT-5389] feat(pipelines): add dr pipelines command behind feature gate with shared infrastructure [CMPT-5389] feat(pipelines): add dr pipeline command behind feature gate with shared infrastructure May 27, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🔐 Fork smoke tests started by maintainer

⏳ Security scans passed. Running smoke tests...

Commit: 570b6f753e91fe0835f88a2647d1665a9b0c476e
View run

@github-actions

Copy link
Copy Markdown
Contributor

All smoke tests passed! (Fork PR)

✅ Security Scan: success
✅ Linux: success
✅ Windows: success

View run details

sunny2get and others added 11 commits May 27, 2026 11:53
…rastructure

Registers the `pipelines` command group (feature-gated behind
DATAROBOT_CLI_FEATURE_PIPELINES=true) and introduces the shared transport
layer used by all subsequent subcommand PRs:

- cmd/root.go: wire pipelines.Cmd() into the CLI root via CommandAdder
- cmd/pipelines/cmd.go: parent command with features.SetGate("pipelines")
- internal/drapi/client.go: NewHTTPClient, AuthorizeRequest helpers
- internal/drapi/get.go: resolveToken with viperx (replaces raw viper)
- internal/pipelines/transport.go: doJSON, doDelete, decodeHTTPError
- internal/pipelines/scope.go: draft/locked URL resolution
- internal/pipelines/time.go: custom Time for naive UTC datetime parsing
- docs: add pipelines entry to README.md command table and mkdocs nav

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… docs, auth refactor

- Rename internal/pipelines → internal/drapi/pipelines (reviewer: treat as
  drapi sub-package consistent with internal/drapi/filesapi)
- transport.go: replace drapi.AuthorizeRequest with drapi.SetAuthHeaders
  (the pre-existing canonical helper); inline &http.Client{Timeout: 30s}
  directly, matching the pattern used by post.go/get.go/patch.go/delete.go;
  remove internal/drapi/client.go as it is no longer needed
- internal/drapi/auth.go: route SetAuthHeaders through resolveToken() so
  --skip-auth is honoured consistently across all API paths
- cmd/pipelines/cmd.go: Use "pipeline" (singular per project convention),
  Aliases: ["pipelines"] for backward compat
- docs/mkdocs.yml: remove pipelines nav entry until feature is GA
- scope.go: use url.PathEscape on pipelineID to prevent path injection
- time_test.go: add unit tests for Time.UnmarshalJSON

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… auth.go

Move var token, GetToken/SetToken, and resolveToken from get.go into auth.go
so all token-related logic lives in one place. Update post.go, delete.go, and
patch.go to call resolveToken() instead of config.GetAPIKey() directly, making
--skip-auth work consistently for every outbound API verb. Use url.PathEscape
on pipelineID in scope.go with a failing test first to guard against path injection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…nd docs

- Rename cmd/pipelines/ → cmd/pipeline/ (Use: "pipeline", alias "pipelines")
- Rename internal/drapi/pipelines/ → internal/drapi/pipeline/ (API URLs unchanged)
- Change feature gate annotation to singular "pipeline" (env: DATAROBOT_CLI_FEATURE_PIPELINE)
- Add url.PathEscape for pipelineID in scope.go; add failing+passing path-escape tests
- Add unit tests for time.go (7 cases + struct unmarshal)
- Update docs to reference DATAROBOT_CLI_FEATURE_PIPELINE

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…EADME

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…es scope

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
scope.go and scope_test.go are first used by the graph command (crud branch),
not by the base infrastructure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Follows singular-name convention from CLAUDE.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sunny2get
sunny2get force-pushed the cmpt-5391/pipelines-base branch from 570b6f7 to b9b4326 Compare May 27, 2026 15:57
@github-actions

Copy link
Copy Markdown
Contributor

🔐 Fork smoke tests started by maintainer

⏳ Security scans passed. Running smoke tests...

Commit: b9b43267c46d0cf5f8f1b13b69b64d0fec67ca84
View run

@github-actions

Copy link
Copy Markdown
Contributor

All smoke tests passed! (Fork PR)

✅ Security Scan: success
✅ Linux: success
✅ Windows: success

View run details

@github-actions

Copy link
Copy Markdown
Contributor

🔐 Fork smoke tests started by maintainer

⏳ Security scans passed. Running smoke tests...

Commit: 434ddbbdc0c76c9bed7e17a4b4e88918de2354b8
View run

@github-actions

Copy link
Copy Markdown
Contributor

All smoke tests passed! (Fork PR)

✅ Security Scan: success
✅ Linux: success
✅ Windows: success

View run details

The double WaitFor pattern called tm.Output() twice; the second call saw
an empty buffer because both strings render on the same Bubble Tea frame.
The original single WaitFor("Variables found in") is sufficient — it only
resolves after dotenvFileUpdatedMsg is processed, meaning the save is done.
Also harden FinalModel() with Require so the real failure surfaces first.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

🔐 Fork smoke tests started by maintainer

⏳ Security scans passed. Running smoke tests...

Commit: 94a6c60591f85ecc9d628b6d0543595d7b31b918
View run

@github-actions

Copy link
Copy Markdown
Contributor

All smoke tests passed! (Fork PR)

✅ Security Scan: success
✅ Linux: success
✅ Windows: success

View run details

@ajalon1
ajalon1 merged commit 636ad26 into datarobot-oss:main May 27, 2026
20 of 21 checks passed
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