fix(vars:set): allow creating action-scoped variables#21
Merged
Conversation
vars:set built the API payload with three independent if-blocks, so
`--pipeline=X --action=Y` emitted BOTH a `pipeline` and an `action`
scope object. Buddy's API accepts only one scope object and rejected
the request ("Only one scope is allowed: project, pipeline, action,
sandbox"). Combined with `--action` requiring `--pipeline`, there was
no accepted invocation that could ever produce an action-scoped
variable.
Emit exactly one scope object via an if/elseif chain (most-specific
wins: action > pipeline > project > workspace). For action scope, send
only the `action` reference; `--pipeline` is used solely as routing
context for the existing-variable lookup, not as a second scope.
Also disambiguate scope selectors (--project/--pipeline/--action) from
routing context (--workspace, never a scope) in the help text.
Tests now assert the actual payload shape per scope (the prior
action-scope test passed only because it mocked createVariable without
checking what was sent). Verified end-to-end against the live Buddy
API: created an action-scoped var on pipeline 506857 / action 1558732,
confirmed Scope=action:1558732, then deleted it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes vars:set scope handling so action-scoped variables can be created/updated by ensuring the API payload contains exactly one scope object (action > pipeline > project > workspace), while still requiring --pipeline as routing context when --action is used.
Changes:
- Update
SetCommandto emit a single scope object via anif/elseifchain and adjust filters for existing-variable lookup. - Improve
vars:sethelp text to clarify scope selectors vs--workspacerouting context, including an action-scope example. - Strengthen/add integration tests to assert the exact payload passed to
createVariable()for pipeline/action/project scopes.
Notes (blocking to keep bundled docs in sync):
- The bundled Claude plugin contains at least one now-misleading statement about
vars:setscope rules (e.g.,claude-plugin/agents/cicd-specialist.md“use --project OR --pipeline” omits the valid--pipeline + --actionpairing). Since this PR changes CLI behavior, the plugin should be updated in the same PR to avoid stale guidance. README.mdcurrently documentsvars:setbut doesn’t mention action-scoped variables; consider updating it to include the now-working--pipeline --actionusage.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/Commands/Variables/SetCommand.php |
Fixes scope payload construction to allow action-scoped variables and updates help text accordingly. |
tests/Integration/Commands/VariablesCommandsTest.php |
Adds payload-capture assertions to ensure the correct scope object is sent to the API for each scope. |
Comment on lines
+119
to
+122
| // Pipeline scope emits exactly one scope object: pipeline. | ||
| $this->assertSame(['id' => 123], $captured['pipeline'] ?? null); | ||
| $this->assertArrayNotHasKey('action', $captured); | ||
| $this->assertArrayNotHasKey('project', $captured); |
Comment on lines
+153
to
+157
| // a payload carrying both `pipeline` and `action` ("Only one scope is allowed"). | ||
| // --pipeline is routing/context for resolving the action, not a second scope. | ||
| $this->assertSame(['id' => 456], $captured['action'] ?? null); | ||
| $this->assertArrayNotHasKey('pipeline', $captured); | ||
| $this->assertArrayNotHasKey('project', $captured); |
Comment on lines
+184
to
+186
| $this->assertSame(['name' => 'my-project'], $captured['project'] ?? null); | ||
| $this->assertArrayNotHasKey('pipeline', $captured); | ||
| $this->assertArrayNotHasKey('action', $captured); |
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.
Problem
It was impossible to create an action-scoped environment variable with
buddy vars:set. Two validations contradicted each other:buddy vars:set --pipeline=506857 --action=1558732 -- KEY VAL→Failed to set variable: Only one scope is allowed: project, pipeline, action, sandboxbuddy vars:set --action=1558732 -- KEY VAL→--action requires --pipeline. An action belongs to a specific pipeline.--actionrequires--pipeline, but supplying both was rejected as "only one scope" — so no invocation could ever yield an action-scoped variable. (Pipeline scope alone worked fine; only action scope was broken.)Root cause
SetCommand::execute()built the API payload with three independentifblocks:So
--pipeline --actionwrote both scope objects. The Buddy API accepts only one scope object per variable and rejected the payload.The bug was invisible to the test suite because the existing action-scope test mocked
createVariableand never asserted the payload it received.The fix
Emit exactly one scope object via an
if/elseifchain (most-specific wins:action > pipeline > project > workspace):action: {id}.--pipelineis used purely as routing/context for the existing-variable lookup (pipelineId+actionIdfilters), never as a second scope object.--actionstill requires--pipeline(an action needs its pipeline to route the lookup), but the two no longer collide.--projectremains mutually exclusive with--pipeline/--action— they are genuinely different scopes.--project/--pipeline/--action) from routing context (--workspace, which is never a scope).Tests
createVariable, and added a project-scope payload test. The action-scope assertion fails against the old code (proper TDD red → green).pint --testclean.Live API verification
Confirmed end-to-end against the real Buddy API (then cleaned up — the caller's existing pipeline-scoped
NODE_OPTIONSwas left untouched):Now-working command
🤖 Generated with Claude Code