Add workspace project reassignment and full API coverage#7
Conversation
…pdate Add -project-id flag to workspace update for moving workspaces between projects, and expand both workspace create and workspace update to support all fields from the go-tfe WorkspaceCreateOptions and WorkspaceUpdateOptions structs. New flags include execution-mode, working-directory, agent-pool-id, VCS repo management (with -remove-vcs for update), trigger prefixes and patterns, auto-destroy settings, tags (create), source tracking (create), and all boolean toggle fields (allow-destroy-plan, assessments-enabled, queue-all-runs, speculative-enabled, etc). Closes #6 Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
There was a problem hiding this comment.
Pull request overview
This pull request adds workspace project reassignment support and expands the workspace create/update commands with full API coverage for all fields from go-tfe's WorkspaceCreateOptions and WorkspaceUpdateOptions. The changes directly address issue #6 by adding the -project-id flag and significantly expand the CLI's workspace management capabilities.
Changes:
- Adds
-project-idflag to bothworkspace createandworkspace updatecommands for project assignment/reassignment - Expands workspace update from 6 flags to 27+ flags covering execution mode, VCS configuration, triggers, boolean toggles, and auto-destroy settings
- Expands workspace create from 4 flags to 25+ flags with similar coverage plus create-specific fields like tags and source tracking
- Adds comprehensive test coverage (14 tests for update, 11 for create) covering the new functionality
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| command/workspace_update.go | Implements expanded flag set with validation, adds helper functions parseBoolFlag and splitCommaList, includes VCS removal support and auto-destroy configuration |
| command/workspace_update_test.go | Adds 10 new tests covering project-id, execution-mode, working-directory, VCS configuration, trigger prefixes, boolean flags, and auto-destroy-at |
| command/workspace_create.go | Mirrors workspace_update expansion with create-specific fields (tags, source-name, source-url, migration-environment), but critically missing helper function definitions |
| command/workspace_create_test.go | Adds 8 new tests covering similar scenarios as update tests plus tags, source fields, and trigger prefixes |
Comments suppressed due to low confidence (2)
command/workspace_update_test.go:414
- The test uses a date of "2025-12-31T23:59:59Z" which is in the past (current date is February 2026). While this won't cause the test to fail, using a date in the past for testing auto-destroy functionality may not reflect realistic usage. Consider updating to a future date like "2027-12-31T23:59:59Z" to better represent how this feature would be used in practice.
destroyTime := "2025-12-31T23:59:59Z"
command/workspace_create.go:275
- The workspace create command doesn't support "none" as a value for -auto-destroy-at like workspace update does (workspace_update.go line 276). While this might be intentional (since you can't clear a value that doesn't exist yet during creation), the help text should clarify this difference if it's deliberate. Alternatively, for consistency, workspace_create could accept and silently ignore "none".
if c.autoDestroyAt != "" {
t, parseErr := time.Parse(time.RFC3339, c.autoDestroyAt)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
|
|
||
| for _, bf := range boolFlags { | ||
| parsed, parseErr := parseBoolFlag(bf.value, bf.flagName) |
There was a problem hiding this comment.
The function parseBoolFlag is called here but is not defined in this file. It's only defined in workspace_update.go. This will cause a compilation error. The helper functions parseBoolFlag and splitCommaList should either be defined in a shared utility file or duplicated in both files.
|
|
||
| // Trigger prefixes/patterns | ||
| if c.triggerPrefixes != "" { | ||
| options.TriggerPrefixes = splitCommaList(c.triggerPrefixes) |
There was a problem hiding this comment.
The function splitCommaList is called here but is not defined in this file. It's only defined in workspace_update.go. This will cause a compilation error. Consider moving these helper functions to a shared utility file (e.g., command/workspace_helpers.go) or adding them to this file as well.
| vcsRepo.OAuthTokenID = tfe.String(c.vcsOAuthTokenID) | ||
| } | ||
| if c.vcsIngressSubmodules != "" { | ||
| parsed, parseErr := parseBoolFlag(c.vcsIngressSubmodules, "vcs-ingress-submodules") |
There was a problem hiding this comment.
The parseBoolFlag function is called here for VCS ingress submodules parsing, but this function is not defined in this file. This will cause a compilation error.
| flags.StringVar(&c.speculativeEnabled, "speculative-enabled", "", "Enable speculative plans (true/false)") | ||
| flags.StringVar(&c.structuredRunOutputEnabled, "structured-run-output-enabled", "", "Enable structured run output (true/false)") | ||
| flags.StringVar(&c.inheritsProjectAutoDestroy, "inherits-project-auto-destroy", "", "Inherit project auto-destroy settings (true/false)") | ||
| flags.StringVar(&c.hyokEnabled, "hyok-enabled", "", "Enable HYOK (true only; cannot be disabled)") |
There was a problem hiding this comment.
The help text states "Enable HYOK (true only; cannot be disabled)" but workspace_create.go allows "true/false" for this flag (line 99: "Enable HYOK (true/false)"). For consistency and correctness, workspace_create.go should either: 1) have the same validation as workspace_update.go (lines 149-159) that disallows false and only accepts true, or 2) the help text should match the actual behavior. Currently, there's an inconsistency between the two commands.
| // Validate HYOK: only "true" is allowed | ||
| if c.hyokEnabled != "" { | ||
| if c.hyokEnabled == "false" { | ||
| c.Ui.Error("Error: HYOK cannot be disabled once enabled") | ||
| return 1 | ||
| } | ||
| if c.hyokEnabled != "true" { | ||
| c.Ui.Error("Error: -hyok-enabled must be 'true'") | ||
| return 1 | ||
| } | ||
| } |
There was a problem hiding this comment.
The HYOK validation logic (lines 149-159) has special requirements (only allows "true", disallows "false", provides specific error messages) but lacks test coverage. Consider adding tests that verify: 1) -hyok-enabled=true succeeds, 2) -hyok-enabled=false returns the specific error "HYOK cannot be disabled once enabled", 3) -hyok-enabled=invalid returns the error "must be 'true'".
| flags.StringVar(&c.executionMode, "execution-mode", "", "Execution mode: remote, local, or agent") | ||
| flags.StringVar(&c.workingDirectory, "working-directory", "", "Working directory") | ||
| flags.StringVar(&c.projectID, "project-id", "", "Project ID to move the workspace into") | ||
| flags.StringVar(&c.agentPoolID, "agent-pool-id", "", "Agent pool ID (required when execution-mode is agent)") |
There was a problem hiding this comment.
The help text states that -agent-pool-id is "required when execution-mode is agent" (line 79 and 380), but there's no validation in the code that enforces this requirement. If this is a server-side validation, the help text should clarify that. Otherwise, consider adding client-side validation after line 147 to check: if execution-mode is "agent" and agent-pool-id is empty, return an error. This would provide better user experience with immediate feedback rather than waiting for an API error.
| flags.StringVar(&c.agentPoolID, "agent-pool-id", "", "Agent pool ID (required when execution-mode is agent)") | |
| flags.StringVar(&c.agentPoolID, "agent-pool-id", "", "Agent pool ID (required by server when execution-mode is agent)") |
| flags.StringVar(&c.executionMode, "execution-mode", "", "Execution mode: remote, local, or agent") | ||
| flags.StringVar(&c.workingDirectory, "working-directory", "", "Working directory") | ||
| flags.StringVar(&c.projectID, "project-id", "", "Project ID to assign the workspace to") | ||
| flags.StringVar(&c.agentPoolID, "agent-pool-id", "", "Agent pool ID (required when execution-mode is agent)") |
There was a problem hiding this comment.
The help text states that -agent-pool-id is "required when execution-mode is agent", but there's no validation in the code that enforces this requirement. Consider adding the same validation that should be added to workspace_update.go for consistency. This would provide better user experience with immediate feedback rather than waiting for an API error.
Summary
-project-idflag tohcptf workspace updateso workspaces can be moved between projectsworkspace createandworkspace updateto expose all fields from the go-tfeWorkspaceCreateOptionsandWorkspaceUpdateOptionsstructsNew flags on
workspace update(was 6, now 27+):-execution-mode,-working-directory,-agent-pool-id,-project-id-allow-destroy-plan,-assessments-enabled,-auto-apply-run-trigger,-file-triggers-enabled,-global-remote-state,-project-remote-state,-queue-all-runs,-speculative-enabled,-structured-run-output-enabled,-inherits-project-auto-destroy,-hyok-enabled-vcs-identifier,-vcs-branch,-vcs-oauth-token-id,-vcs-ingress-submodules,-vcs-tags-regex,-vcs-gha-installation-id,-remove-vcs-trigger-prefixes,-trigger-patterns,-auto-destroy-at,-auto-destroy-activity-durationNew flags on
workspace create(was 4, now 25+):-source-name,-source-url,-migration-environment,-tagsTests
workspace update: 14 tests (was 4)workspace create: 11 tests (was 3)Closes #6
Test plan
hcptf workspace update -org=pthrasher_v2 -name=<ws> -project-id=prj-LNB4hVb551oyRzxd🤖 Generated with Claude Code