diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c2f058..4b07dbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,5 +10,6 @@ All notable changes to this project will be documented in this file. - Added organizations data-source. - Added repositories data-source. - Added repository actions secret resource. +- Added repository actions variable resource. - Added teams data-source. - Added users data-source. diff --git a/docs/resources/repository_actions_variable.md b/docs/resources/repository_actions_variable.md new file mode 100644 index 0000000..509e29d --- /dev/null +++ b/docs/resources/repository_actions_variable.md @@ -0,0 +1,32 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "forgejo_repository_actions_variable Resource - terraform-provider-forgejo" +subcategory: "" +description: |- + Use this resource to create and manage a repository actions variable. +--- + +# forgejo_repository_actions_variable (Resource) + +Use this resource to create and manage a repository actions variable. + +## Example Usage + +```terraform +resource "forgejo_repository_actions_variable" { + data = "value" + name = "test" + owner = "adyxax" + repository = "example" +} +``` + + +## Schema + +### Required + +- `data` (String) The variable's data. +- `name` (String) The variable's name. It must be uppercase or the plan will not be idempotent. +- `owner` (String) The variable's owner. +- `repository` (String) The variable's repository. diff --git a/examples/resources/forgejo_repository_actions_variable/resource.tf b/examples/resources/forgejo_repository_actions_variable/resource.tf new file mode 100644 index 0000000..03bd656 --- /dev/null +++ b/examples/resources/forgejo_repository_actions_variable/resource.tf @@ -0,0 +1,6 @@ +resource "forgejo_repository_actions_variable" { + data = "value" + name = "test" + owner = "adyxax" + repository = "example" +} diff --git a/internal/client/repository_actions_variables.go b/internal/client/repository_actions_variables.go new file mode 100644 index 0000000..e165f2e --- /dev/null +++ b/internal/client/repository_actions_variables.go @@ -0,0 +1,58 @@ +package client + +import ( + "context" + "fmt" + "net/url" + "path" +) + +type RepositoryActionsVariable struct { + Data string `json:"data"` + Name string `json:"name"` + OwnerId int64 `json:"owner_id"` + RepoId int64 `json:"repo_id"` +} + +func (c *Client) RepositoryActionsVariableCreate(ctx context.Context, owner string, repo string, name string, value string) error { + uriRef := url.URL{Path: path.Join("api/v1/repos", owner, repo, "actions/variables", name)} + type Payload struct { + Value string `json:"value"` + } + payload := Payload{Value: value} + if _, err := c.send(ctx, "POST", &uriRef, &payload, nil); err != nil { + return fmt.Errorf("failed to create repository actions variable: %w", err) + } + return nil +} + +func (c *Client) RepositoryActionsVariableDelete(ctx context.Context, owner string, repo string, name string) (*RepositoryActionsVariable, error) { + uriRef := url.URL{Path: path.Join("api/v1/repos", owner, repo, "actions/variables", name)} + response := RepositoryActionsVariable{} + if _, err := c.send(ctx, "DELETE", &uriRef, nil, &response); err != nil { + return nil, fmt.Errorf("failed to delete repository actions variable: %w", err) + } + return &response, nil +} + +func (c *Client) RepositoryActionsVariableGet(ctx context.Context, owner string, repo string, name string) (*RepositoryActionsVariable, error) { + uriRef := url.URL{Path: path.Join("api/v1/repos", owner, repo, "actions/variables", name)} + response := RepositoryActionsVariable{} + if _, err := c.send(ctx, "GET", &uriRef, nil, &response); err != nil { + return nil, fmt.Errorf("failed to get repository actions variable: %w", err) + } + return &response, nil +} + +func (c *Client) RepositoryActionsVariableUpdate(ctx context.Context, owner string, repo string, oldName string, newName string, value string) error { + uriRef := url.URL{Path: path.Join("api/v1/repos", owner, repo, "actions/variables", oldName)} + type Payload struct { + Name string `json:"name"` + Value string `json:"value"` + } + payload := Payload{Name: newName, Value: value} + if _, err := c.send(ctx, "PUT", &uriRef, &payload, nil); err != nil { + return fmt.Errorf("failed to update repository actions variable: %w", err) + } + return nil +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 89da0af..88fcb1b 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -77,6 +77,7 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest, func (p *Provider) Resources(ctx context.Context) []func() resource.Resource { return []func() resource.Resource{ NewRepositoryActionsSecretResource, + NewRepositoryActionsVariableResource, } } diff --git a/internal/provider/repository_actions_variable_resource.go b/internal/provider/repository_actions_variable_resource.go new file mode 100644 index 0000000..a88f656 --- /dev/null +++ b/internal/provider/repository_actions_variable_resource.go @@ -0,0 +1,145 @@ +package provider + +import ( + "context" + "fmt" + + "git.adyxax.org/adyxax/terraform-provider-forgejo/internal/client" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +type RepositoryActionsVariableResource struct { + client *client.Client +} + +var _ resource.Resource = &RepositoryActionsVariableResource{} // Ensure provider defined types fully satisfy framework interfaces +func NewRepositoryActionsVariableResource() resource.Resource { + return &RepositoryActionsVariableResource{} +} + +type RepositoryActionsVariableResourceModel struct { + Data types.String `tfsdk:"data"` + Name types.String `tfsdk:"name"` + Owner types.String `tfsdk:"owner"` + Repository types.String `tfsdk:"repository"` +} + +func (d *RepositoryActionsVariableResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_repository_actions_variable" +} + +func (d *RepositoryActionsVariableResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "data": schema.StringAttribute{ + MarkdownDescription: "The variable's data.", + Required: true, + }, + "name": schema.StringAttribute{ + MarkdownDescription: "The variable's name. It must be uppercase or the plan will not be idempotent.", + Required: true, + }, + "owner": schema.StringAttribute{ + MarkdownDescription: "The variable's owner.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Required: true, + }, + "repository": schema.StringAttribute{ + MarkdownDescription: "The variable's repository.", + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Required: true, + }, + }, + MarkdownDescription: "Use this resource to create and manage a repository actions variable.", + } +} + +func (d *RepositoryActionsVariableResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + d.client, _ = req.ProviderData.(*client.Client) +} + +func (d *RepositoryActionsVariableResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data RepositoryActionsVariableResourceModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + err := d.client.RepositoryActionsVariableCreate( + ctx, + data.Owner.ValueString(), + data.Repository.ValueString(), + data.Name.ValueString(), + data.Data.ValueString()) + if err != nil { + resp.Diagnostics.AddError("CreateRepositoryActionsVariable", fmt.Sprintf("failed to create repository actions variable: %s", err)) + return + } + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (d *RepositoryActionsVariableResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data RepositoryActionsVariableResourceModel + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + _, err := d.client.RepositoryActionsVariableDelete( + ctx, + data.Owner.ValueString(), + data.Repository.ValueString(), + data.Name.ValueString()) + if err != nil { + resp.Diagnostics.AddError("DeleteRepositoryActionsVariable", fmt.Sprintf("failed to delete repository actions variable: %s", err)) + return + } +} + +func (d *RepositoryActionsVariableResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data RepositoryActionsVariableResourceModel + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + variable, err := d.client.RepositoryActionsVariableGet( + ctx, + data.Owner.ValueString(), + data.Repository.ValueString(), + data.Name.ValueString()) + if err != nil { + resp.Diagnostics.AddError("ReadRepositoryActionsVariable", fmt.Sprintf("failed to get repository actions variable: %s", err)) + return + } + data.Data = types.StringValue(variable.Data) + data.Name = types.StringValue(variable.Name) + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (d *RepositoryActionsVariableResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var plannedData RepositoryActionsVariableResourceModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plannedData)...) + var stateData RepositoryActionsVariableResourceModel + resp.Diagnostics.Append(req.State.Get(ctx, &stateData)...) + if resp.Diagnostics.HasError() { + return + } + err := d.client.RepositoryActionsVariableUpdate( + ctx, + plannedData.Owner.ValueString(), + plannedData.Repository.ValueString(), + stateData.Name.ValueString(), + plannedData.Name.ValueString(), + plannedData.Data.ValueString()) + if err != nil { + resp.Diagnostics.AddError("UpdateRepositoryActionsVariable", fmt.Sprintf("failed to update repository actions variable %s %s: %s", stateData.Name.ValueString(), err)) + return + } + resp.Diagnostics.Append(resp.State.Set(ctx, &plannedData)...) +}