Files
avivsinai__bitbucket-cli/pkg/bbcloud/variables.go
T

562 lines
14 KiB
Go

package bbcloud
import (
"context"
"fmt"
"net/url"
)
// PipelineVariable represents a Bitbucket Cloud pipeline variable.
type PipelineVariable struct {
UUID string `json:"uuid"`
Key string `json:"key"`
Value string `json:"value,omitempty"`
Secured bool `json:"secured"`
}
// VariableListOptions configures variable list requests.
type VariableListOptions struct {
Limit int
}
type variableListPage struct {
Values []PipelineVariable `json:"values"`
Next string `json:"next"`
}
// ListRepositoryVariables lists pipeline variables for a repository.
func (c *Client) ListRepositoryVariables(ctx context.Context, workspace, repoSlug string, opts VariableListOptions) ([]PipelineVariable, error) {
if workspace == "" || repoSlug == "" {
return nil, fmt.Errorf("workspace and repository slug are required")
}
pageLen := opts.Limit
if pageLen <= 0 || pageLen > 100 {
pageLen = 100
}
path := fmt.Sprintf("/repositories/%s/%s/pipelines_config/variables?pagelen=%d",
url.PathEscape(workspace),
url.PathEscape(repoSlug),
pageLen,
)
var variables []PipelineVariable
for path != "" {
req, err := c.http.NewRequest(ctx, "GET", path, nil)
if err != nil {
return nil, err
}
var page variableListPage
if err := c.http.Do(req, &page); err != nil {
return nil, err
}
variables = append(variables, page.Values...)
if opts.Limit > 0 && len(variables) >= opts.Limit {
variables = variables[:opts.Limit]
break
}
if page.Next == "" {
break
}
nextURL, err := url.Parse(page.Next)
if err != nil {
return nil, err
}
path = nextURL.RequestURI()
}
return variables, nil
}
// CreateRepositoryVariableInput configures repository variable creation.
type CreateRepositoryVariableInput struct {
Key string
Value string
Secured bool
}
// CreateRepositoryVariable creates a pipeline variable for a repository.
func (c *Client) CreateRepositoryVariable(ctx context.Context, workspace, repoSlug string, input CreateRepositoryVariableInput) (*PipelineVariable, error) {
if workspace == "" || repoSlug == "" {
return nil, fmt.Errorf("workspace and repository slug are required")
}
if input.Key == "" {
return nil, fmt.Errorf("variable key is required")
}
body := map[string]any{
"key": input.Key,
"value": input.Value,
"secured": input.Secured,
}
path := fmt.Sprintf("/repositories/%s/%s/pipelines_config/variables",
url.PathEscape(workspace),
url.PathEscape(repoSlug),
)
req, err := c.http.NewRequest(ctx, "POST", path, body)
if err != nil {
return nil, err
}
var variable PipelineVariable
if err := c.http.Do(req, &variable); err != nil {
return nil, err
}
return &variable, nil
}
// UpdateRepositoryVariableInput configures repository variable updates.
type UpdateRepositoryVariableInput struct {
Key string
Value string
Secured bool
}
// UpdateRepositoryVariable updates a pipeline variable for a repository.
// The variableUUID identifies the variable to update.
func (c *Client) UpdateRepositoryVariable(ctx context.Context, workspace, repoSlug, variableUUID string, input UpdateRepositoryVariableInput) (*PipelineVariable, error) {
if workspace == "" || repoSlug == "" {
return nil, fmt.Errorf("workspace and repository slug are required")
}
if variableUUID == "" {
return nil, fmt.Errorf("variable UUID is required")
}
if input.Key == "" {
return nil, fmt.Errorf("variable key is required")
}
body := map[string]any{
"key": input.Key,
"value": input.Value,
"secured": input.Secured,
}
path := fmt.Sprintf("/repositories/%s/%s/pipelines_config/variables/%s",
url.PathEscape(workspace),
url.PathEscape(repoSlug),
url.PathEscape(variableUUID),
)
req, err := c.http.NewRequest(ctx, "PUT", path, body)
if err != nil {
return nil, err
}
var variable PipelineVariable
if err := c.http.Do(req, &variable); err != nil {
return nil, err
}
return &variable, nil
}
// DeleteRepositoryVariable deletes a pipeline variable from a repository.
func (c *Client) DeleteRepositoryVariable(ctx context.Context, workspace, repoSlug, variableUUID string) error {
if workspace == "" || repoSlug == "" {
return fmt.Errorf("workspace and repository slug are required")
}
if variableUUID == "" {
return fmt.Errorf("variable UUID is required")
}
path := fmt.Sprintf("/repositories/%s/%s/pipelines_config/variables/%s",
url.PathEscape(workspace),
url.PathEscape(repoSlug),
url.PathEscape(variableUUID),
)
req, err := c.http.NewRequest(ctx, "DELETE", path, nil)
if err != nil {
return err
}
return c.http.Do(req, nil)
}
// --- Workspace-level variable methods ---
// ListWorkspaceVariables lists pipeline variables for a workspace.
func (c *Client) ListWorkspaceVariables(ctx context.Context, workspace string, opts VariableListOptions) ([]PipelineVariable, error) {
if workspace == "" {
return nil, fmt.Errorf("workspace is required")
}
pageLen := opts.Limit
if pageLen <= 0 || pageLen > 100 {
pageLen = 100
}
path := fmt.Sprintf("/workspaces/%s/pipelines-config/variables?pagelen=%d",
url.PathEscape(workspace),
pageLen,
)
var variables []PipelineVariable
for path != "" {
req, err := c.http.NewRequest(ctx, "GET", path, nil)
if err != nil {
return nil, err
}
var page variableListPage
if err := c.http.Do(req, &page); err != nil {
return nil, err
}
variables = append(variables, page.Values...)
if opts.Limit > 0 && len(variables) >= opts.Limit {
variables = variables[:opts.Limit]
break
}
if page.Next == "" {
break
}
nextURL, err := url.Parse(page.Next)
if err != nil {
return nil, err
}
path = nextURL.RequestURI()
}
return variables, nil
}
// CreateWorkspaceVariableInput configures workspace variable creation.
type CreateWorkspaceVariableInput struct {
Key string
Value string
Secured bool
}
// CreateWorkspaceVariable creates a pipeline variable for a workspace.
func (c *Client) CreateWorkspaceVariable(ctx context.Context, workspace string, input CreateWorkspaceVariableInput) (*PipelineVariable, error) {
if workspace == "" {
return nil, fmt.Errorf("workspace is required")
}
if input.Key == "" {
return nil, fmt.Errorf("variable key is required")
}
body := map[string]any{
"key": input.Key,
"value": input.Value,
"secured": input.Secured,
}
path := fmt.Sprintf("/workspaces/%s/pipelines-config/variables",
url.PathEscape(workspace),
)
req, err := c.http.NewRequest(ctx, "POST", path, body)
if err != nil {
return nil, err
}
var variable PipelineVariable
if err := c.http.Do(req, &variable); err != nil {
return nil, err
}
return &variable, nil
}
// UpdateWorkspaceVariableInput configures workspace variable updates.
type UpdateWorkspaceVariableInput struct {
Key string
Value string
Secured bool
}
// UpdateWorkspaceVariable updates a pipeline variable for a workspace.
func (c *Client) UpdateWorkspaceVariable(ctx context.Context, workspace, variableUUID string, input UpdateWorkspaceVariableInput) (*PipelineVariable, error) {
if workspace == "" {
return nil, fmt.Errorf("workspace is required")
}
if variableUUID == "" {
return nil, fmt.Errorf("variable UUID is required")
}
if input.Key == "" {
return nil, fmt.Errorf("variable key is required")
}
body := map[string]any{
"key": input.Key,
"value": input.Value,
"secured": input.Secured,
}
path := fmt.Sprintf("/workspaces/%s/pipelines-config/variables/%s",
url.PathEscape(workspace),
url.PathEscape(variableUUID),
)
req, err := c.http.NewRequest(ctx, "PUT", path, body)
if err != nil {
return nil, err
}
var variable PipelineVariable
if err := c.http.Do(req, &variable); err != nil {
return nil, err
}
return &variable, nil
}
// DeleteWorkspaceVariable deletes a pipeline variable from a workspace.
func (c *Client) DeleteWorkspaceVariable(ctx context.Context, workspace, variableUUID string) error {
if workspace == "" {
return fmt.Errorf("workspace is required")
}
if variableUUID == "" {
return fmt.Errorf("variable UUID is required")
}
path := fmt.Sprintf("/workspaces/%s/pipelines-config/variables/%s",
url.PathEscape(workspace),
url.PathEscape(variableUUID),
)
req, err := c.http.NewRequest(ctx, "DELETE", path, nil)
if err != nil {
return err
}
return c.http.Do(req, nil)
}
// --- Deployment environment variable methods ---
// DeploymentEnvironment represents a deployment environment in Bitbucket Cloud.
type DeploymentEnvironment struct {
UUID string `json:"uuid"`
Name string `json:"name"`
Slug string `json:"slug"`
EnvironmentType struct {
Name string `json:"name"`
} `json:"environment_type"`
}
type deploymentEnvironmentListPage struct {
Values []DeploymentEnvironment `json:"values"`
Next string `json:"next"`
}
// ListDeploymentEnvironments lists deployment environments for a repository.
func (c *Client) ListDeploymentEnvironments(ctx context.Context, workspace, repoSlug string) ([]DeploymentEnvironment, error) {
if workspace == "" || repoSlug == "" {
return nil, fmt.Errorf("workspace and repository slug are required")
}
path := fmt.Sprintf("/repositories/%s/%s/environments?pagelen=100",
url.PathEscape(workspace),
url.PathEscape(repoSlug),
)
var environments []DeploymentEnvironment
for path != "" {
req, err := c.http.NewRequest(ctx, "GET", path, nil)
if err != nil {
return nil, err
}
var page deploymentEnvironmentListPage
if err := c.http.Do(req, &page); err != nil {
return nil, err
}
environments = append(environments, page.Values...)
if page.Next == "" {
break
}
nextURL, err := url.Parse(page.Next)
if err != nil {
return nil, err
}
path = nextURL.RequestURI()
}
return environments, nil
}
// ListDeploymentVariables lists pipeline variables for a deployment environment.
func (c *Client) ListDeploymentVariables(ctx context.Context, workspace, repoSlug, environmentUUID string, opts VariableListOptions) ([]PipelineVariable, error) {
if workspace == "" || repoSlug == "" {
return nil, fmt.Errorf("workspace and repository slug are required")
}
if environmentUUID == "" {
return nil, fmt.Errorf("environment UUID is required")
}
pageLen := opts.Limit
if pageLen <= 0 || pageLen > 100 {
pageLen = 100
}
path := fmt.Sprintf("/repositories/%s/%s/deployments_config/environments/%s/variables?pagelen=%d",
url.PathEscape(workspace),
url.PathEscape(repoSlug),
url.PathEscape(environmentUUID),
pageLen,
)
var variables []PipelineVariable
for path != "" {
req, err := c.http.NewRequest(ctx, "GET", path, nil)
if err != nil {
return nil, err
}
var page variableListPage
if err := c.http.Do(req, &page); err != nil {
return nil, err
}
variables = append(variables, page.Values...)
if opts.Limit > 0 && len(variables) >= opts.Limit {
variables = variables[:opts.Limit]
break
}
if page.Next == "" {
break
}
nextURL, err := url.Parse(page.Next)
if err != nil {
return nil, err
}
path = nextURL.RequestURI()
}
return variables, nil
}
// CreateDeploymentVariableInput configures deployment variable creation.
type CreateDeploymentVariableInput struct {
Key string
Value string
Secured bool
}
// CreateDeploymentVariable creates a pipeline variable for a deployment environment.
func (c *Client) CreateDeploymentVariable(ctx context.Context, workspace, repoSlug, environmentUUID string, input CreateDeploymentVariableInput) (*PipelineVariable, error) {
if workspace == "" || repoSlug == "" {
return nil, fmt.Errorf("workspace and repository slug are required")
}
if environmentUUID == "" {
return nil, fmt.Errorf("environment UUID is required")
}
if input.Key == "" {
return nil, fmt.Errorf("variable key is required")
}
body := map[string]any{
"key": input.Key,
"value": input.Value,
"secured": input.Secured,
}
path := fmt.Sprintf("/repositories/%s/%s/deployments_config/environments/%s/variables",
url.PathEscape(workspace),
url.PathEscape(repoSlug),
url.PathEscape(environmentUUID),
)
req, err := c.http.NewRequest(ctx, "POST", path, body)
if err != nil {
return nil, err
}
var variable PipelineVariable
if err := c.http.Do(req, &variable); err != nil {
return nil, err
}
return &variable, nil
}
// UpdateDeploymentVariableInput configures deployment variable updates.
type UpdateDeploymentVariableInput struct {
Key string
Value string
Secured bool
}
// UpdateDeploymentVariable updates a pipeline variable for a deployment environment.
func (c *Client) UpdateDeploymentVariable(ctx context.Context, workspace, repoSlug, environmentUUID, variableUUID string, input UpdateDeploymentVariableInput) (*PipelineVariable, error) {
if workspace == "" || repoSlug == "" {
return nil, fmt.Errorf("workspace and repository slug are required")
}
if environmentUUID == "" {
return nil, fmt.Errorf("environment UUID is required")
}
if variableUUID == "" {
return nil, fmt.Errorf("variable UUID is required")
}
if input.Key == "" {
return nil, fmt.Errorf("variable key is required")
}
body := map[string]any{
"key": input.Key,
"value": input.Value,
"secured": input.Secured,
}
path := fmt.Sprintf("/repositories/%s/%s/deployments_config/environments/%s/variables/%s",
url.PathEscape(workspace),
url.PathEscape(repoSlug),
url.PathEscape(environmentUUID),
url.PathEscape(variableUUID),
)
req, err := c.http.NewRequest(ctx, "PUT", path, body)
if err != nil {
return nil, err
}
var variable PipelineVariable
if err := c.http.Do(req, &variable); err != nil {
return nil, err
}
return &variable, nil
}
// DeleteDeploymentVariable deletes a pipeline variable from a deployment environment.
func (c *Client) DeleteDeploymentVariable(ctx context.Context, workspace, repoSlug, environmentUUID, variableUUID string) error {
if workspace == "" || repoSlug == "" {
return fmt.Errorf("workspace and repository slug are required")
}
if environmentUUID == "" {
return fmt.Errorf("environment UUID is required")
}
if variableUUID == "" {
return fmt.Errorf("variable UUID is required")
}
path := fmt.Sprintf("/repositories/%s/%s/deployments_config/environments/%s/variables/%s",
url.PathEscape(workspace),
url.PathEscape(repoSlug),
url.PathEscape(environmentUUID),
url.PathEscape(variableUUID),
)
req, err := c.http.NewRequest(ctx, "DELETE", path, nil)
if err != nil {
return err
}
return c.http.Do(req, nil)
}