Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 933fdac

Browse files
feat: Add Git trigger functionality
1 parent d009e07 commit 933fdac

File tree

7 files changed

+548
-3
lines changed

7 files changed

+548
-3
lines changed

docs/resources/git_trigger.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
---
2+
# generated by https://github.com/hashicorp/terraform-plugin-docs
3+
page_title: "octopusdeploy_git_trigger Resource - terraform-provider-octopusdeploy"
4+
subcategory: ""
5+
description: |-
6+
This resource manages Git triggers in Octopus Deploy
7+
---
8+
9+
# octopusdeploy_git_trigger (Resource)
10+
11+
This resource manages Git triggers in Octopus Deploy
12+
13+
14+
15+
<!-- schema generated by tfplugindocs -->
16+
## Schema
17+
18+
### Required
19+
20+
- `channel_id` (String) The ID of the channel in which the release will be created if the action type is CreateRelease.
21+
- `name` (String) The name of this resource.
22+
- `project_id` (String) The ID of the project to attach the trigger.
23+
- `sources` (Attributes List) (see [below for nested schema](#nestedatt--sources))
24+
25+
### Optional
26+
27+
- `description` (String) The description of this Git trigger..
28+
- `is_disabled` (Boolean) Disables the trigger from being run when set.
29+
- `space_id` (String) The space ID associated with this Git trigger.
30+
31+
### Read-Only
32+
33+
- `id` (String) The unique ID for this resource.
34+
35+
<a id="nestedatt--sources"></a>
36+
### Nested Schema for `sources`
37+
38+
Required:
39+
40+
- `deployment_action_slug` (String) The deployment action slug.
41+
- `exclude_file_paths` (List of String) The file paths to exclude.
42+
- `git_dependency_name` (String) The git dependency name.
43+
- `include_file_paths` (List of String) The file paths to include.
44+
45+

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/OctopusDeploy/terraform-provider-octopusdeploy
33
go 1.21
44

55
require (
6-
github.com/OctopusDeploy/go-octopusdeploy/v2 v2.60.0
6+
github.com/OctopusDeploy/go-octopusdeploy/v2 v2.63.0
77
github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240729041805-46db6fb717b4
88
github.com/google/uuid v1.6.0
99
github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ github.com/Microsoft/hcsshim v0.12.4 h1:Ev7YUMHAHoWNm+aDSPzc5W9s6E2jyL1szpVDJeZ/
2020
github.com/Microsoft/hcsshim v0.12.4/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ=
2121
github.com/OctopusDeploy/go-octodiff v1.0.0 h1:U+ORg6azniwwYo+O44giOw6TiD5USk8S4VDhOQ0Ven0=
2222
github.com/OctopusDeploy/go-octodiff v1.0.0/go.mod h1:Mze0+EkOWTgTmi8++fyUc6r0aLZT7qD9gX+31t8MmIU=
23-
github.com/OctopusDeploy/go-octopusdeploy/v2 v2.60.0 h1:9j4IQ1UcAuaTytlBzQ7Mmoy/dLtofYfSGNiM22+sLXs=
24-
github.com/OctopusDeploy/go-octopusdeploy/v2 v2.60.0/go.mod h1:ggvOXzMnq+w0pLg6C9zdjz6YBaHfO3B3tqmmB7JQdaw=
23+
github.com/OctopusDeploy/go-octopusdeploy/v2 v2.63.0 h1:TshwN+IqKt21uY9aXzj0ou0Ew92uIi3+ZGTccVd9Z8g=
24+
github.com/OctopusDeploy/go-octopusdeploy/v2 v2.63.0/go.mod h1:ggvOXzMnq+w0pLg6C9zdjz6YBaHfO3B3tqmmB7JQdaw=
2525
github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240729041805-46db6fb717b4 h1:QfbVf0bOIRMp/WHAWsuVDB7KHoWnRsGbvDuOf2ua7k4=
2626
github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240729041805-46db6fb717b4/go.mod h1:Oq9KbiRNDBB5jFmrwnrgLX0urIqR/1ptY18TzkqXm7M=
2727
github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg=

octopusdeploy_framework/framework_provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ func (p *octopusDeployFrameworkProvider) Resources(ctx context.Context) []func()
127127
NewScriptModuleResource,
128128
NewUserResource,
129129
NewServiceAccountOIDCIdentity,
130+
NewGitTriggerResource,
130131
}
131132
}
132133

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
package octopusdeploy_framework
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/actions"
7+
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/filters"
8+
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects"
9+
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/triggers"
10+
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/internal/errors"
11+
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/schemas"
12+
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/octopusdeploy_framework/util"
13+
"github.com/hashicorp/terraform-plugin-framework/attr"
14+
"github.com/hashicorp/terraform-plugin-framework/path"
15+
"github.com/hashicorp/terraform-plugin-framework/resource"
16+
"github.com/hashicorp/terraform-plugin-framework/types"
17+
"github.com/hashicorp/terraform-plugin-log/tflog"
18+
)
19+
20+
type gitTriggerResource struct {
21+
*Config
22+
}
23+
24+
func NewGitTriggerResource() resource.Resource {
25+
return &gitTriggerResource{}
26+
}
27+
28+
var _ resource.ResourceWithImportState = &gitTriggerResource{}
29+
30+
func (r *gitTriggerResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
31+
resp.TypeName = util.GetTypeName("git_trigger")
32+
}
33+
34+
func (r *gitTriggerResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
35+
resp.Schema = schemas.GitTriggerSchema{}.GetResourceSchema()
36+
}
37+
38+
func (r *gitTriggerResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
39+
r.Config = ResourceConfiguration(req, resp)
40+
}
41+
42+
func (r *gitTriggerResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
43+
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
44+
}
45+
46+
func (r *gitTriggerResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
47+
var data *schemas.GitTriggerResourceModel
48+
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
49+
if resp.Diagnostics.HasError() {
50+
return
51+
}
52+
53+
gitTriggerSources := convertListToGitTriggerSources(data.Sources)
54+
55+
action := actions.NewCreateReleaseAction(data.ChannelId.ValueString())
56+
filter := filters.NewGitTriggerFilter(gitTriggerSources)
57+
58+
client := r.Config.Client
59+
60+
project, err := projects.GetByID(client, data.SpaceId.ValueString(), data.ProjectId.ValueString())
61+
62+
if err != nil {
63+
resp.Diagnostics.AddError("error finding project", err.Error())
64+
return
65+
}
66+
67+
tflog.Info(ctx, fmt.Sprintf("creating Git trigger: %s", data.Name.ValueString()))
68+
69+
projectTrigger := triggers.NewProjectTrigger(data.Name.ValueString(), data.Description.ValueString(), data.IsDisabled.ValueBool(), project, action, filter)
70+
71+
createdGitTrigger, err := client.ProjectTriggers.Add(projectTrigger)
72+
73+
if err != nil {
74+
resp.Diagnostics.AddError("unable to create Git trigger", err.Error())
75+
return
76+
}
77+
78+
data.ID = types.StringValue(createdGitTrigger.GetID())
79+
data.Name = types.StringValue(createdGitTrigger.Name)
80+
data.ProjectId = types.StringValue(createdGitTrigger.ProjectID)
81+
data.SpaceId = types.StringValue(createdGitTrigger.SpaceID)
82+
data.IsDisabled = types.BoolValue(createdGitTrigger.IsDisabled)
83+
data.Sources = convertGitTriggerSourcesToList(createdGitTrigger.Filter.(*filters.GitTriggerFilter).Sources)
84+
85+
tflog.Info(ctx, fmt.Sprintf("Git trigger created (%s)", data.ID))
86+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
87+
}
88+
89+
func (r *gitTriggerResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
90+
var data *schemas.GitTriggerResourceModel
91+
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
92+
if resp.Diagnostics.HasError() {
93+
return
94+
}
95+
96+
tflog.Info(ctx, fmt.Sprintf("reading Git Trigger (%s)", data.ID))
97+
98+
client := r.Config.Client
99+
100+
gitTrigger, err := client.ProjectTriggers.GetByID(data.ID.ValueString())
101+
if err != nil {
102+
if err := errors.ProcessApiErrorV2(ctx, resp, data, err, "error retrieving Git Trigger"); err != nil {
103+
resp.Diagnostics.AddError("unable to load Git Trigger", err.Error())
104+
}
105+
return
106+
}
107+
108+
data.ID = types.StringValue(gitTrigger.GetID())
109+
data.Name = types.StringValue(gitTrigger.Name)
110+
data.ProjectId = types.StringValue(gitTrigger.ProjectID)
111+
data.SpaceId = types.StringValue(gitTrigger.SpaceID)
112+
data.IsDisabled = types.BoolValue(gitTrigger.IsDisabled)
113+
data.Sources = convertGitTriggerSourcesToList(gitTrigger.Filter.(*filters.GitTriggerFilter).Sources)
114+
115+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
116+
}
117+
118+
func (r *gitTriggerResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
119+
var data, state *schemas.GitTriggerResourceModel
120+
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
121+
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
122+
if resp.Diagnostics.HasError() {
123+
return
124+
}
125+
126+
tflog.Debug(ctx, fmt.Sprintf("updating Git Trigger '%s'", data.ID.ValueString()))
127+
128+
client := r.Config.Client
129+
130+
gitTrigger, err := client.ProjectTriggers.GetByID(data.ID.ValueString())
131+
if err != nil {
132+
resp.Diagnostics.AddError("unable to load Git Trigger", err.Error())
133+
return
134+
}
135+
136+
gitTriggerSources := convertListToGitTriggerSources(data.Sources)
137+
action := actions.NewCreateReleaseAction(data.ChannelId.ValueString())
138+
filter := filters.NewGitTriggerFilter(gitTriggerSources)
139+
project, err := projects.GetByID(client, data.SpaceId.ValueString(), data.ProjectId.ValueString())
140+
141+
if err != nil {
142+
resp.Diagnostics.AddError("error finding project", err.Error())
143+
return
144+
}
145+
146+
updatedGitTrigger := triggers.NewProjectTrigger(data.Name.ValueString(), data.Description.ValueString(), data.IsDisabled.ValueBool(), project, action, filter)
147+
updatedGitTrigger.ID = gitTrigger.ID
148+
149+
updatedGitTrigger, err = client.ProjectTriggers.Update(updatedGitTrigger)
150+
tflog.Info(ctx, fmt.Sprintf("Git Trigger updated (%s)", data.ID))
151+
152+
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
153+
}
154+
155+
func (r *gitTriggerResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
156+
var data schemas.GitTriggerResourceModel
157+
158+
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
159+
if resp.Diagnostics.HasError() {
160+
return
161+
}
162+
163+
client := r.Config.Client
164+
165+
if err := client.ProjectTriggers.DeleteByID(data.ID.ValueString()); err != nil {
166+
resp.Diagnostics.AddError("unable to delete Git Trigger", err.Error())
167+
return
168+
}
169+
}
170+
171+
func convertListToGitTriggerSources(list types.List) []filters.GitTriggerSource {
172+
var gitTriggerSources []filters.GitTriggerSource
173+
174+
for _, elem := range list.Elements() {
175+
obj := elem.(types.Object)
176+
attrs := obj.Attributes()
177+
178+
deploymentActionSlug := attrs["deployment_action_slug"].(types.String).ValueString()
179+
gitDependencyName := attrs["git_dependency_name"].(types.String).ValueString()
180+
includeFilePaths := convertToStringSlice(attrs["include_file_paths"].(types.List))
181+
excludeFilePaths := convertToStringSlice(attrs["exclude_file_paths"].(types.List))
182+
183+
gitTriggerSource := filters.GitTriggerSource{
184+
DeploymentActionSlug: deploymentActionSlug,
185+
GitDependencyName: gitDependencyName,
186+
IncludeFilePaths: includeFilePaths,
187+
ExcludeFilePaths: excludeFilePaths,
188+
}
189+
190+
gitTriggerSources = append(gitTriggerSources, gitTriggerSource)
191+
}
192+
193+
return gitTriggerSources
194+
}
195+
196+
func convertToStringSlice(list types.List) []string {
197+
var result []string
198+
for _, elem := range list.Elements() {
199+
result = append(result, elem.(types.String).ValueString())
200+
}
201+
return result
202+
}
203+
204+
func convertGitTriggerSourcesToList(gitTriggerSources []filters.GitTriggerSource) types.List {
205+
var elements []attr.Value
206+
207+
for _, source := range gitTriggerSources {
208+
attributes := map[string]attr.Value{
209+
"deployment_action_slug": types.StringValue(source.DeploymentActionSlug),
210+
"git_dependency_name": types.StringValue(source.GitDependencyName),
211+
"include_file_paths": convertStringSliceToList(source.IncludeFilePaths),
212+
"exclude_file_paths": convertStringSliceToList(source.ExcludeFilePaths),
213+
}
214+
objectValue, _ := types.ObjectValue(sourcesObjectType(), attributes)
215+
elements = append(elements, objectValue)
216+
}
217+
218+
listValue, _ := types.ListValue(types.ObjectType{AttrTypes: sourcesObjectType()}, elements)
219+
return listValue
220+
}
221+
222+
func convertStringSliceToList(strings []string) types.List {
223+
var elements []attr.Value
224+
225+
for _, str := range strings {
226+
elements = append(elements, types.StringValue(str))
227+
}
228+
229+
listValue, _ := types.ListValue(types.StringType, elements)
230+
return listValue
231+
}
232+
233+
func sourcesObjectType() map[string]attr.Type {
234+
return map[string]attr.Type{
235+
"deployment_action_slug": types.StringType,
236+
"git_dependency_name": types.StringType,
237+
"include_file_paths": types.ListType{ElemType: types.StringType},
238+
"exclude_file_paths": types.ListType{ElemType: types.StringType},
239+
}
240+
}

0 commit comments

Comments
 (0)