From 799061007476fac17feb59e0c9fb46033478b347 Mon Sep 17 00:00:00 2001
From: Lourens de Jager <165963988+lourens-octopus@users.noreply.github.com>
Date: Tue, 12 Nov 2024 10:00:10 +1300
Subject: [PATCH] feat: Add Git Triggers
---
docs/resources/git_trigger.md | 65 +++++++++
.../octopusdeploy_git_trigger/import.sh | 1 +
.../octopusdeploy_git_trigger/resource.tf | 12 ++
go.mod | 2 +-
go.sum | 4 +-
octopusdeploy/provider.go | 1 +
octopusdeploy/resource_git_trigger.go | 130 ++++++++++++++++++
octopusdeploy/schema_git_trigger.go | 42 ++++++
.../schema_git_trigger_source_package.go | 66 +++++++++
9 files changed, 320 insertions(+), 3 deletions(-)
create mode 100644 docs/resources/git_trigger.md
create mode 100644 examples/resources/octopusdeploy_git_trigger/import.sh
create mode 100644 examples/resources/octopusdeploy_git_trigger/resource.tf
create mode 100644 octopusdeploy/resource_git_trigger.go
create mode 100644 octopusdeploy/schema_git_trigger.go
create mode 100644 octopusdeploy/schema_git_trigger_source_package.go
diff --git a/docs/resources/git_trigger.md b/docs/resources/git_trigger.md
new file mode 100644
index 00000000..f0f17868
--- /dev/null
+++ b/docs/resources/git_trigger.md
@@ -0,0 +1,65 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "octopusdeploy_git_trigger Resource - terraform-provider-octopusdeploy"
+subcategory: ""
+description: |-
+ This resource manages Git repository triggers in Octopus Deploy.
+---
+
+# octopusdeploy_git_trigger (Resource)
+
+This resource manages Git repository triggers in Octopus Deploy.
+
+## Example Usage
+
+```terraform
+resource "octopusdeploy_git_trigger" "my_trigger" {
+ name = "My Git trigger"
+ space_id = "Spaces-1"
+ project_id = "Projects-1"
+ channel_id = "Channels-1"
+ sources {
+ deployment_action_slug = "deploy-action-slug"
+ git_dependency_name = ""
+ include_file_paths = ["include/me", "include/me/too"]
+ exclude_file_paths = ["exclude/me", "exclude/me/too"]
+ }
+}
+```
+
+
+## Schema
+
+### Required
+
+- `channel_id` (String) The ID of the channel in which the release will be created if the action type is CreateRelease.
+- `name` (String) The name of this resource.
+- `project_id` (String) The ID of the project to attach the trigger.
+
+### Optional
+
+- `is_disabled` (Boolean) Disables the trigger from being run when set.
+- `sources` (Block List) List of Git trigger sources. Contains details of the deployment action slug, the git dependency and what file paths to monitor. (see [below for nested schema](#nestedblock--sources))
+- `space_id` (String) The space ID associated with the project to attach the trigger.
+
+### Read-Only
+
+- `id` (String) The ID of this resource.
+
+
+### Nested Schema for `sources`
+
+Required:
+
+- `deployment_action_slug` (String)
+- `exclude_file_paths` (List of String)
+- `git_dependency_name` (String)
+- `include_file_paths` (List of String)
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+terraform import [options] octopusdeploy_git_trigger.
+```
diff --git a/examples/resources/octopusdeploy_git_trigger/import.sh b/examples/resources/octopusdeploy_git_trigger/import.sh
new file mode 100644
index 00000000..38f0466b
--- /dev/null
+++ b/examples/resources/octopusdeploy_git_trigger/import.sh
@@ -0,0 +1 @@
+terraform import [options] octopusdeploy_git_trigger.
\ No newline at end of file
diff --git a/examples/resources/octopusdeploy_git_trigger/resource.tf b/examples/resources/octopusdeploy_git_trigger/resource.tf
new file mode 100644
index 00000000..bed9184d
--- /dev/null
+++ b/examples/resources/octopusdeploy_git_trigger/resource.tf
@@ -0,0 +1,12 @@
+resource "octopusdeploy_git_trigger" "my_trigger" {
+ name = "My Git trigger"
+ space_id = "Spaces-1"
+ project_id = "Projects-1"
+ channel_id = "Channels-1"
+ sources {
+ deployment_action_slug = "deploy-action-slug"
+ git_dependency_name = ""
+ include_file_paths = ["include/me", "include/me/too"]
+ exclude_file_paths = ["exclude/me", "exclude/me/too"]
+ }
+}
diff --git a/go.mod b/go.mod
index 8dcc68c2..b7605719 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/OctopusDeploy/terraform-provider-octopusdeploy
go 1.21
require (
- github.com/OctopusDeploy/go-octopusdeploy/v2 v2.55.0
+ github.com/OctopusDeploy/go-octopusdeploy/v2 v2.56.0
github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240729041805-46db6fb717b4
github.com/google/uuid v1.6.0
github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637
diff --git a/go.sum b/go.sum
index 7a39471c..996851f8 100644
--- a/go.sum
+++ b/go.sum
@@ -20,8 +20,8 @@ github.com/Microsoft/hcsshim v0.12.4 h1:Ev7YUMHAHoWNm+aDSPzc5W9s6E2jyL1szpVDJeZ/
github.com/Microsoft/hcsshim v0.12.4/go.mod h1:Iyl1WVpZzr+UkzjekHZbV8o5Z9ZkxNGx6CtY2Qg/JVQ=
github.com/OctopusDeploy/go-octodiff v1.0.0 h1:U+ORg6azniwwYo+O44giOw6TiD5USk8S4VDhOQ0Ven0=
github.com/OctopusDeploy/go-octodiff v1.0.0/go.mod h1:Mze0+EkOWTgTmi8++fyUc6r0aLZT7qD9gX+31t8MmIU=
-github.com/OctopusDeploy/go-octopusdeploy/v2 v2.55.0 h1:kX6qRRy8AgbqTiYdenqVNe69pGhntwJGEgJx9rtn9/8=
-github.com/OctopusDeploy/go-octopusdeploy/v2 v2.55.0/go.mod h1:ggvOXzMnq+w0pLg6C9zdjz6YBaHfO3B3tqmmB7JQdaw=
+github.com/OctopusDeploy/go-octopusdeploy/v2 v2.56.0 h1:KALIOWdky6FR8a2npBo6wdYG0Rg08e3C++1kEHWFex4=
+github.com/OctopusDeploy/go-octopusdeploy/v2 v2.56.0/go.mod h1:ggvOXzMnq+w0pLg6C9zdjz6YBaHfO3B3tqmmB7JQdaw=
github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240729041805-46db6fb717b4 h1:QfbVf0bOIRMp/WHAWsuVDB7KHoWnRsGbvDuOf2ua7k4=
github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20240729041805-46db6fb717b4/go.mod h1:Oq9KbiRNDBB5jFmrwnrgLX0urIqR/1ptY18TzkqXm7M=
github.com/ProtonMail/go-crypto v1.1.0-alpha.2 h1:bkyFVUP+ROOARdgCiJzNQo2V2kiB97LyUpzH9P6Hrlg=
diff --git a/octopusdeploy/provider.go b/octopusdeploy/provider.go
index 58a85a55..362bfcb7 100644
--- a/octopusdeploy/provider.go
+++ b/octopusdeploy/provider.go
@@ -46,6 +46,7 @@ func Provider() *schema.Provider {
"octopusdeploy_deployment_process": resourceDeploymentProcess(),
"octopusdeploy_dynamic_worker_pool": resourceDynamicWorkerPool(),
"octopusdeploy_gcp_account": resourceGoogleCloudPlatformAccount(),
+ "octopusdeploy_git_trigger": resourceGitTrigger(),
"octopusdeploy_kubernetes_agent_deployment_target": resourceKubernetesAgentDeploymentTarget(),
"octopusdeploy_kubernetes_agent_worker": resourceKubernetesAgentWorker(),
"octopusdeploy_kubernetes_cluster_deployment_target": resourceKubernetesClusterDeploymentTarget(),
diff --git a/octopusdeploy/resource_git_trigger.go b/octopusdeploy/resource_git_trigger.go
new file mode 100644
index 00000000..6aa51ce7
--- /dev/null
+++ b/octopusdeploy/resource_git_trigger.go
@@ -0,0 +1,130 @@
+package octopusdeploy
+
+import (
+ "context"
+ "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects"
+ "log"
+
+ "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/actions"
+ "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client"
+ "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/filters"
+ "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/triggers"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func resourceGitTrigger() *schema.Resource {
+ return &schema.Resource{
+ CreateContext: resourceGitTriggerCreate,
+ DeleteContext: resourceGitTriggerDelete,
+ Description: "This resource manages Git repository triggers in Octopus Deploy.",
+ Importer: getImporter(),
+ ReadContext: resourceGitTriggerRead,
+ Schema: getGitTriggerSchema(),
+ UpdateContext: resourceGitTriggerUpdate,
+ }
+}
+
+func buildGitTriggerResource(d *schema.ResourceData, client *client.Client) (*triggers.ProjectTrigger, error) {
+ name := d.Get("name").(string)
+ spaceId := d.Get("space_id").(string)
+ projectId := d.Get("project_id").(string)
+ channelId := d.Get("channel_id").(string)
+
+ isDisabled := false
+ if v, ok := d.GetOk("is_disabled"); ok {
+ isDisabled = v.(bool)
+ }
+
+ flattenedGitTriggerSources := d.Get("sources")
+ gitTriggerSources := expandGitTriggerSources(flattenedGitTriggerSources)
+
+ action := actions.NewCreateReleaseAction(channelId)
+ filter := filters.NewGitTriggerFilter(gitTriggerSources)
+
+ project, err := projects.GetByID(client, spaceId, projectId)
+ if err != nil {
+ return nil, err
+ }
+
+ createReleaseTrigger := triggers.NewProjectTrigger(name, "", isDisabled, project, action, filter)
+
+ return createReleaseTrigger, nil
+}
+
+func resourceGitTriggerCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ client := m.(*client.Client)
+
+ projectTrigger, err := buildGitTriggerResource(d, client)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ resource, err := client.ProjectTriggers.Add(projectTrigger)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ if isEmpty(resource.GetID()) {
+ log.Println("ID is nil")
+ } else {
+ d.SetId(resource.GetID())
+ }
+
+ return nil
+}
+
+func resourceGitTriggerRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ id := d.Id()
+
+ client := m.(*client.Client)
+ projectTrigger, err := client.ProjectTriggers.GetByID(id)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ if projectTrigger == nil {
+ d.SetId("")
+ return nil
+ }
+
+ action := projectTrigger.Action.(*actions.CreateReleaseAction)
+ filter := projectTrigger.Filter.(*filters.GitTriggerFilter)
+
+ d.Set("name", projectTrigger.Name)
+ d.Set("space_id", projectTrigger.SpaceID)
+ d.Set("project_id", projectTrigger.ProjectID)
+ d.Set("is_disabled", projectTrigger.IsDisabled)
+ d.Set("channel_id", action.ChannelID)
+ d.Set("sources", flattenGitTriggerSources(filter.Sources))
+
+ return nil
+}
+
+func resourceGitTriggerUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ client := m.(*client.Client)
+ projectTrigger, err := buildGitTriggerResource(d, client)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+ projectTrigger.ID = d.Id() // set ID so Octopus API knows which project trigger to update
+
+ resource, err := client.ProjectTriggers.Update(projectTrigger)
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ d.SetId(resource.GetID())
+
+ return nil
+}
+
+func resourceGitTriggerDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
+ client := m.(*client.Client)
+ err := client.ProjectTriggers.DeleteByID(d.Id())
+ if err != nil {
+ return diag.FromErr(err)
+ }
+
+ d.SetId("")
+ return nil
+}
diff --git a/octopusdeploy/schema_git_trigger.go b/octopusdeploy/schema_git_trigger.go
new file mode 100644
index 00000000..2b83dbd7
--- /dev/null
+++ b/octopusdeploy/schema_git_trigger.go
@@ -0,0 +1,42 @@
+package octopusdeploy
+
+import (
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
+)
+
+func getGitTriggerSchema() map[string]*schema.Schema {
+ return map[string]*schema.Schema{
+ "name": getNameSchema(true),
+ "space_id": {
+ Optional: true,
+ Description: "The space ID associated with the project to attach the trigger.",
+ Type: schema.TypeString,
+ ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace),
+ },
+ "project_id": {
+ Description: "The ID of the project to attach the trigger.",
+ Required: true,
+ Type: schema.TypeString,
+ ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace),
+ },
+ "channel_id": {
+ Description: "The ID of the channel in which the release will be created if the action type is CreateRelease.",
+ Required: true,
+ Type: schema.TypeString,
+ ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotWhiteSpace),
+ },
+ "sources": {
+ Description: "List of Git trigger sources. Contains details of the deployment action slug, the git dependency and what file paths to monitor.",
+ Optional: true,
+ Type: schema.TypeList,
+ Elem: &schema.Resource{Schema: getGitTriggerSourceSchema()},
+ },
+ "is_disabled": {
+ Description: "Disables the trigger from being run when set.",
+ Optional: true,
+ Default: false,
+ Type: schema.TypeBool,
+ },
+ }
+}
diff --git a/octopusdeploy/schema_git_trigger_source_package.go b/octopusdeploy/schema_git_trigger_source_package.go
new file mode 100644
index 00000000..60a9fe5a
--- /dev/null
+++ b/octopusdeploy/schema_git_trigger_source_package.go
@@ -0,0 +1,66 @@
+package octopusdeploy
+
+import (
+ "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/filters"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
+)
+
+func expandGitTriggerSources(values interface{}) []filters.GitTriggerSource {
+ if values == nil {
+ return nil
+ }
+
+ var gitTriggerSources []filters.GitTriggerSource
+ for _, v := range values.([]interface{}) {
+ flattenedMap := v.(map[string]interface{})
+ gitTriggerSources = append(gitTriggerSources, filters.GitTriggerSource{
+ DeploymentActionSlug: flattenedMap["deployment_action_slug"].(string),
+ GitDependencyName: flattenedMap["git_dependency_name"].(string),
+ IncludeFilePaths: flattenedMap["include_file_paths"].([]string),
+ ExcludeFilePaths: flattenedMap["exclude_file_paths"].([]string),
+ })
+ }
+
+ return gitTriggerSources
+}
+
+func flattenGitTriggerSources(gitTriggerSources []filters.GitTriggerSource) []interface{} {
+ if len(gitTriggerSources) == 0 {
+ return nil
+ }
+
+ flattenedGitTriggerSources := []interface{}{}
+ for _, v := range gitTriggerSources {
+ flattenedGitTriggerSources = append(flattenedGitTriggerSources, map[string]interface{}{
+ "deployment_action_slug": v.DeploymentActionSlug,
+ "git_dependency_name": v.GitDependencyName,
+ "include_file_paths": v.IncludeFilePaths,
+ "exclude_file_paths": v.ExcludeFilePaths,
+ })
+ }
+
+ return flattenedGitTriggerSources
+}
+
+func getGitTriggerSourceSchema() map[string]*schema.Schema {
+ return map[string]*schema.Schema{
+ "deployment_action_slug": {
+ Required: true,
+ Type: schema.TypeString,
+ },
+ "git_dependency_name": {
+ Required: true,
+ Type: schema.TypeString,
+ },
+ "include_file_paths": {
+ Required: true,
+ Type: schema.TypeList,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ "exclude_file_paths": {
+ Required: true,
+ Type: schema.TypeList,
+ Elem: &schema.Schema{Type: schema.TypeString},
+ },
+ }
+}