diff --git a/CHANGELOG.md b/CHANGELOG.md index 902929d..05c71de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 17.11.2024, Version 2.11.0 + +- feature/deployment-pipeline in [#96](https://github.com/iLert/terraform-provider-ilert/pull/96) + ## 01.10.2024, Version 2.10.0 - feature/alert-action-conditions-field in [#94](https://github.com/iLert/terraform-provider-ilert/pull/94) diff --git a/examples/deployment_pipeline/README.md b/examples/deployment_pipeline/README.md new file mode 100644 index 0000000..44d01ac --- /dev/null +++ b/examples/deployment_pipeline/README.md @@ -0,0 +1,16 @@ +# Deployment pipeline example + +This demos [deployment pipeline](https://docs.ilert.com/deployment-integrations). + +This example will create a deployment pipeline resource in the specified organization. See https://registry.terraform.io/providers/iLert/ilert/latest/docs for details on configuring [`providers.tf`](./providers.tf) accordingly. + +Alternatively, you may use variables passed via command line: + +```sh +export ILERT_API_TOKEN= +``` + +```sh +terraform apply \ + -var "api_token=${ILERT_API_TOKEN}" \ +``` diff --git a/examples/deployment_pipeline/main.tf b/examples/deployment_pipeline/main.tf new file mode 100644 index 0000000..1d0e84f --- /dev/null +++ b/examples/deployment_pipeline/main.tf @@ -0,0 +1,8 @@ +resource "ilert_deployment_pipeline" "example" { + name = "example" + integration_type = "GITHUB" + github { + branch_filter = ["main", "master"] + event_filter = ["release"] + } +} diff --git a/examples/deployment_pipeline/providers.tf b/examples/deployment_pipeline/providers.tf new file mode 100644 index 0000000..da9d102 --- /dev/null +++ b/examples/deployment_pipeline/providers.tf @@ -0,0 +1,13 @@ +terraform { + required_providers { + ilert = { + source = "iLert/ilert" + version = "~> 2.0" + } + } +} + +provider "ilert" { + endpoint = var.endpoint + api_token = var.api_token +} diff --git a/examples/deployment_pipeline/variables.tf b/examples/deployment_pipeline/variables.tf new file mode 100644 index 0000000..a97c921 --- /dev/null +++ b/examples/deployment_pipeline/variables.tf @@ -0,0 +1,10 @@ +variable "api_token" { + description = "ilert API token used to configure the provider" + type = string +} + +variable "endpoint" { + description = "ilert organization used to configure the provider" + type = string + default = "https://api.ilert.com" +} diff --git a/go.mod b/go.mod index 566d108..b3ec654 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( github.com/hashicorp/terraform-plugin-sdk/v2 v2.25.0 - github.com/iLert/ilert-go/v3 v3.10.1 + github.com/iLert/ilert-go/v3 v3.11.0 ) require ( diff --git a/go.sum b/go.sum index c84a99f..23834a4 100644 --- a/go.sum +++ b/go.sum @@ -103,8 +103,8 @@ github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/iLert/ilert-go/v3 v3.10.1 h1:VNzm+WIBj8wgNOKNQFs/XEhTjoHR4IskbXiA/RKDQKY= -github.com/iLert/ilert-go/v3 v3.10.1/go.mod h1:xHJ8qdmthK4HExcQOd3V5JARed/EBKTdX86MqrJ1yJ0= +github.com/iLert/ilert-go/v3 v3.11.0 h1:h2FFGRO2fIaI6Ot24KXQ2/idUVBpcY2YBXbZaIUDiUU= +github.com/iLert/ilert-go/v3 v3.11.0/go.mod h1:xHJ8qdmthK4HExcQOd3V5JARed/EBKTdX86MqrJ1yJ0= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= diff --git a/ilert/data_source_deployment_pipeline.go b/ilert/data_source_deployment_pipeline.go new file mode 100644 index 0000000..b93fc0f --- /dev/null +++ b/ilert/data_source_deployment_pipeline.go @@ -0,0 +1,65 @@ +package ilert + +import ( + "context" + "fmt" + "log" + "strconv" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/iLert/ilert-go/v3" +) + +func dataSourceDeploymentPipeline() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceDeploymentPipelineRead, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + }, + }, + } +} + +func dataSourceDeploymentPipelineRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + client := meta.(*ilert.Client) + + log.Printf("[DEBUG] Reading ilert deployment pipeline") + + searchName := d.Get("name").(string) + + err := resource.RetryContext(ctx, d.Timeout(schema.TimeoutRead), func() *resource.RetryError { + resp, err := client.SearchDeploymentPipeline(&ilert.SearchDeploymentPipelineInput{DeploymentPipelineName: &searchName}) + if err != nil { + if _, ok := err.(*ilert.RetryableAPIError); ok { + time.Sleep(2 * time.Second) + return resource.RetryableError(fmt.Errorf("waiting for deployment pipeline with name '%s' to be read, error: %s", searchName, err.Error())) + } + return resource.NonRetryableError(fmt.Errorf("could not read a deployment pipeline with name: %s, error: %s", searchName, err.Error())) + } + + found := resp.DeploymentPipeline + + if found == nil { + return resource.NonRetryableError( + fmt.Errorf("unable to locate any deployment pipeline with the name: %s", searchName), + ) + } + + d.SetId(strconv.FormatInt(found.ID, 10)) + d.Set("name", found.Name) + + return nil + }) + + if err != nil { + return diag.FromErr(err) + } + + return nil +} diff --git a/ilert/provider.go b/ilert/provider.go index 1e4194b..2c17cc2 100644 --- a/ilert/provider.go +++ b/ilert/provider.go @@ -45,6 +45,7 @@ func Provider() *schema.Provider { "ilert_alert_source": dataSourceAlertSource(), "ilert_connection": dataSourceConnection(), "ilert_connector": dataSourceConnector(), + "ilert_deployment_pipeline": dataSourceDeploymentPipeline(), "ilert_escalation_policy": dataSourceEscalationPolicy(), "ilert_incident_template": dataSourceIncidentTemplate(), "ilert_metric": dataSourceMetric(), @@ -66,6 +67,7 @@ func Provider() *schema.Provider { "ilert_automation_rule": resourceAutomationRule(), "ilert_connection": resourceConnection(), "ilert_connector": resourceConnector(), + "ilert_deployment_pipeline": resourceDeploymentPipeline(), "ilert_escalation_policy": resourceEscalationPolicy(), "ilert_incident_template": resourceIncidentTemplate(), "ilert_metric": resourceMetric(), diff --git a/ilert/resource_deployment_pipeline.go b/ilert/resource_deployment_pipeline.go new file mode 100644 index 0000000..ac0f3cd --- /dev/null +++ b/ilert/resource_deployment_pipeline.go @@ -0,0 +1,374 @@ +package ilert + +import ( + "context" + "fmt" + "log" + "strconv" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" + "github.com/iLert/ilert-go/v3" +) + +func resourceDeploymentPipeline() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringLenBetween(1, 255), + }, + "integration_type": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringInSlice(ilert.DeploymentPipelineIntegrationTypeAll, false), + }, + "integration_key": { + Type: schema.TypeString, + Computed: true, + }, + "team": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeInt, + Required: true, + }, + "name": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringLenBetween(1, 255), + }, + }, + }, + }, + "created_at": { + Type: schema.TypeString, + Computed: true, + }, + "updated_at": { + Type: schema.TypeString, + Computed: true, + }, + "integration_url": { + Type: schema.TypeString, + Computed: true, + }, + "github": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "branch_filter": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "event_filter": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + CreateContext: resourceDeploymentPipelineCreate, + ReadContext: resourceDeploymentPipelineRead, + UpdateContext: resourceDeploymentPipelineUpdate, + DeleteContext: resourceDeploymentPipelineDelete, + Exists: resourceDeploymentPipelineExists, + Importer: &schema.ResourceImporter{ + StateContext: schema.ImportStatePassthroughContext, + }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(10 * time.Minute), + Read: schema.DefaultTimeout(30 * time.Minute), + Update: schema.DefaultTimeout(10 * time.Minute), + Delete: schema.DefaultTimeout(5 * time.Minute), + }, + } +} + +func buildDeploymentPipeline(d *schema.ResourceData) (*ilert.DeploymentPipeline, error) { + name := d.Get("name").(string) + integrationType := d.Get("integration_type").(string) + + deploymentPipeline := &ilert.DeploymentPipeline{ + Name: name, + IntegrationType: integrationType, + } + + if val, ok := d.GetOk("team"); ok { + vL := val.([]interface{}) + tms := make([]ilert.TeamShort, 0) + for _, m := range vL { + v := m.(map[string]interface{}) + tm := ilert.TeamShort{ + ID: int64(v["id"].(int)), + } + if v["name"] != nil && v["name"].(string) != "" { + tm.Name = v["name"].(string) + } + tms = append(tms, tm) + } + deploymentPipeline.Teams = tms + } + + if val, ok := d.GetOk("github"); ok && integrationType == ilert.DeploymentPipelineIntegrationType.GitHub { + vL := val.([]interface{}) + if len(vL) > 0 { + v := vL[0].(map[string]interface{}) + params := &ilert.DeploymentPipelineGitHubParams{} + if vL, ok := v["branch_filter"].([]interface{}); ok && len(vL) > 0 { + sL := make([]string, 0) + for _, m := range vL { + if v, ok := m.(string); ok && v != "" { + sL = append(sL, v) + } + } + params.BranchFilters = sL + } + if vL, ok := v["event_filter"].([]interface{}); ok && len(vL) > 0 { + sL := make([]string, 0) + for _, m := range vL { + if v, ok := m.(string); ok && v != "" { + sL = append(sL, v) + } + } + params.EventFilters = sL + } + deploymentPipeline.Params = params + } + } + + return deploymentPipeline, nil +} + +func resourceDeploymentPipelineCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + client := m.(*ilert.Client) + + deploymentPipeline, err := buildDeploymentPipeline(d) + if err != nil { + log.Printf("[ERROR] Building deployment pipeline error %s", err.Error()) + return diag.FromErr(err) + } + + log.Printf("[INFO] Creating deployment pipeline %s", deploymentPipeline.Name) + + result := &ilert.CreateDeploymentPipelineOutput{} + err = resource.RetryContext(ctx, d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { + includes := []*string{ilert.String("integrationUrl")} + r, err := client.CreateDeploymentPipeline(&ilert.CreateDeploymentPipelineInput{DeploymentPipeline: deploymentPipeline, Include: includes}) + if err != nil { + if _, ok := err.(*ilert.RetryableAPIError); ok { + log.Printf("[ERROR] Creating ilert deployment pipeline error '%s', so retry again", err.Error()) + time.Sleep(2 * time.Second) + return resource.RetryableError(fmt.Errorf("waiting for deployment pipeline to be created, error: %s", err.Error())) + } + return resource.NonRetryableError(fmt.Errorf("could not create a deployment pipeline with ID %s, error: %s", d.Id(), err.Error())) + } + result = r + return nil + }) + if err != nil { + log.Printf("[ERROR] Creating ilert deployment pipeline error %s", err.Error()) + return diag.FromErr(err) + } + + if result == nil || result.DeploymentPipeline == nil { + log.Printf("[ERROR] Creating ilert deployment pipeline error: empty response") + return diag.Errorf("deployment pipeline response is empty") + } + + d.SetId(strconv.FormatInt(result.DeploymentPipeline.ID, 10)) + + return resourceDeploymentPipelineRead(ctx, d, m) +} + +func resourceDeploymentPipelineRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + client := m.(*ilert.Client) + + deploymentPipelineID, err := strconv.ParseInt(d.Id(), 10, 64) + if err != nil { + log.Printf("[ERROR] Could not parse deployment pipeline id %s", err.Error()) + return diag.FromErr(unconvertibleIDErr(d.Id(), err)) + } + log.Printf("[DEBUG] Reading deployment pipeline: %s", d.Id()) + result := &ilert.GetDeploymentPipelineOutput{} + err = resource.RetryContext(ctx, d.Timeout(schema.TimeoutRead), func() *resource.RetryError { + includes := []*string{ilert.String("integrationUrl")} + r, err := client.GetDeploymentPipeline(&ilert.GetDeploymentPipelineInput{DeploymentPipelineID: ilert.Int64(deploymentPipelineID), Include: includes}) + if err != nil { + if _, ok := err.(*ilert.NotFoundAPIError); ok { + log.Printf("[WARN] Removing deployment pipeline %s from state because it no longer exist", d.Id()) + d.SetId("") + return nil + } + if _, ok := err.(*ilert.RetryableAPIError); ok { + time.Sleep(2 * time.Second) + return resource.RetryableError(fmt.Errorf("waiting for deployment pipeline with id '%s' to be read, error: %s", d.Id(), err.Error())) + } + return resource.NonRetryableError(fmt.Errorf("could not read an deployment pipeline with ID %s, error: %s", d.Id(), err.Error())) + } + result = r + return nil + }) + + if err != nil { + log.Printf("[ERROR] Reading ilert deployment pipeline error: %s", err.Error()) + return diag.FromErr(err) + } + + if result == nil || result.DeploymentPipeline == nil { + log.Printf("[ERROR] Reading ilert deployment pipeline error: empty response") + return diag.Errorf("deployment pipeline response is empty") + } + + d.Set("name", result.DeploymentPipeline.Name) + d.Set("integration_type", result.DeploymentPipeline.IntegrationType) + d.Set("integration_key", result.DeploymentPipeline.IntegrationKey) + + teams, err := flattenTeamShortList(result.DeploymentPipeline.Teams, d) + if err != nil { + return diag.FromErr(err) + } + if err := d.Set("team", teams); err != nil { + return diag.Errorf("error setting teams: %s", err) + } + + d.Set("created_at", result.DeploymentPipeline.CreatedAt) + d.Set("updated_at", result.DeploymentPipeline.UpdatedAt) + d.Set("integration_url", result.DeploymentPipeline.IntegrationUrl) + + if result.DeploymentPipeline.IntegrationType == ilert.DeploymentPipelineIntegrationType.GitHub { + d.Set("github", []interface{}{ + map[string]interface{}{ + "branch_filter": result.DeploymentPipeline.Params.BranchFilters, + "event_filter": result.DeploymentPipeline.Params.EventFilters, + }, + }) + } + + return nil +} + +func resourceDeploymentPipelineUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + client := m.(*ilert.Client) + + deploymentPipeline, err := buildDeploymentPipeline(d) + if err != nil { + log.Printf("[ERROR] Building deployment pipeline error %s", err.Error()) + return diag.FromErr(err) + } + + // API expects integration key to be always set, even if not allowed to be set by user + deploymentPipeline.IntegrationKey = d.Get("integration_key").(string) + + deploymentPipelineID, err := strconv.ParseInt(d.Id(), 10, 64) + if err != nil { + log.Printf("[ERROR] Could not parse deployment pipeline id %s", err.Error()) + return diag.FromErr(unconvertibleIDErr(d.Id(), err)) + } + log.Printf("[DEBUG] Updating deployment pipeline: %s", d.Id()) + + err = resource.RetryContext(ctx, d.Timeout(schema.TimeoutUpdate), func() *resource.RetryError { + _, err = client.UpdateDeploymentPipeline(&ilert.UpdateDeploymentPipelineInput{DeploymentPipeline: deploymentPipeline, DeploymentPipelineID: ilert.Int64(deploymentPipelineID)}) + if err != nil { + if _, ok := err.(*ilert.RetryableAPIError); ok { + time.Sleep(2 * time.Second) + return resource.RetryableError(fmt.Errorf("waiting for deployment pipeline with id '%s' to be updated, error: %s", d.Id(), err.Error())) + } + return resource.NonRetryableError(fmt.Errorf("could not update an deployment pipeline with ID %s, error: %s", d.Id(), err.Error())) + } + return nil + }) + + if err != nil { + log.Printf("[ERROR] Updating ilert deployment pipeline error %s", err.Error()) + return diag.FromErr(err) + } + + return resourceDeploymentPipelineRead(ctx, d, m) +} + +func resourceDeploymentPipelineDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { + client := m.(*ilert.Client) + + deploymentPipelineID, err := strconv.ParseInt(d.Id(), 10, 64) + if err != nil { + log.Printf("[ERROR] Could not parse deployment pipeline id %s", err.Error()) + return diag.FromErr(unconvertibleIDErr(d.Id(), err)) + } + log.Printf("[DEBUG] Deleting deployment pipeline: %s", d.Id()) + err = resource.RetryContext(ctx, d.Timeout(schema.TimeoutDelete), func() *resource.RetryError { + _, err = client.DeleteDeploymentPipeline(&ilert.DeleteDeploymentPipelineInput{DeploymentPipelineID: ilert.Int64(deploymentPipelineID)}) + if err != nil { + if _, ok := err.(*ilert.RetryableAPIError); ok { + time.Sleep(2 * time.Second) + return resource.RetryableError(fmt.Errorf("waiting for deployment pipeline with id '%s' to be deleted, error: %s", d.Id(), err.Error())) + } + return resource.NonRetryableError(fmt.Errorf("could not delete an deployment pipeline with ID %s, error: %s", d.Id(), err.Error())) + } + return nil + }) + if err != nil { + log.Printf("[ERROR] Deleting ilert deployment pipeline error %s", err.Error()) + return diag.FromErr(err) + } + + d.SetId("") + return nil +} + +func resourceDeploymentPipelineExists(d *schema.ResourceData, m interface{}) (bool, error) { + client := m.(*ilert.Client) + + deploymentPipelineID, err := strconv.ParseInt(d.Id(), 10, 64) + if err != nil { + log.Printf("[ERROR] Could not parse deployment pipeline id %s", err.Error()) + return false, unconvertibleIDErr(d.Id(), err) + } + log.Printf("[DEBUG] Reading deployment pipeline: %s", d.Id()) + ctx := context.Background() + result := false + err = resource.RetryContext(ctx, d.Timeout(schema.TimeoutCreate), func() *resource.RetryError { + _, err := client.GetDeploymentPipeline(&ilert.GetDeploymentPipelineInput{DeploymentPipelineID: ilert.Int64(deploymentPipelineID)}) + if err != nil { + if _, ok := err.(*ilert.NotFoundAPIError); ok { + result = false + return nil + } + if _, ok := err.(*ilert.RetryableAPIError); ok { + log.Printf("[ERROR] Reading ilert deployment pipeline error '%s', so retry again", err.Error()) + time.Sleep(2 * time.Second) + return resource.RetryableError(fmt.Errorf("waiting for deployment pipeline to be read, error: %s", err.Error())) + } + return resource.NonRetryableError(fmt.Errorf("could not read a deployment pipeline with ID %s, error: %s", d.Id(), err.Error())) + } + result = true + return nil + }) + + if err != nil { + log.Printf("[ERROR] Reading ilert deployment pipeline error: %s", err.Error()) + return false, err + } + return result, nil +} diff --git a/website/docs/d/deployment_pipeline.html.markdown b/website/docs/d/deployment_pipeline.html.markdown new file mode 100644 index 0000000..74511d3 --- /dev/null +++ b/website/docs/d/deployment_pipeline.html.markdown @@ -0,0 +1,32 @@ +--- +layout: "ilert" +page_title: "ilert: ilert_deployment_pipeline" +sidebar_current: "docs-ilert-data-source-deployment-pipeline" +description: |- + Get information about a deployment pipeline that you have created. +--- + +# ilert_deployment_pipeline + +Use this data source to get information about a specific [deployment pipeline][1]. + +## Example Usage + +```hcl +data "ilert_deployment_pipeline" "example" { + name = "example" +} +``` + +## Argument Reference + +The following arguments are supported: + +- `name` - (Required) The deployment pipeline name to use to find a deployment pipeline in the ilert API. + +## Attributes Reference + +- `id` - The ID of the found deployment pipeline. +- `name` - The name of the found deployment pipeline. + +[1]: https://api.ilert.com/api-docs/#tag/deployment-pipelines diff --git a/website/docs/r/deployment_pipeline.html.markdown b/website/docs/r/deployment_pipeline.html.markdown new file mode 100644 index 0000000..b440ff0 --- /dev/null +++ b/website/docs/r/deployment_pipeline.html.markdown @@ -0,0 +1,55 @@ +--- +layout: "ilert" +page_title: "ilert: ilert_deployment_pipeline" +sidebar_current: "docs-ilert-resource-deployment-pipeline" +description: |- + Creates and manages a deployment pipeline in ilert. +--- + +# ilert_deployment_pipeline + +A [deployment pipeline](https://api.ilert.com/api-docs/#tag/deployment-pipelines) enables you to send deployment events to ilert. + +## Example Usage + +```hcl +resource "ilert_deployment_pipeline" "example" { + name = "example" + integration_type = "GITHUB" + github { + branch_filter = ["main", "master"] + event_filter = ["release"] + } +} +``` + +## Argument Reference + +The following arguments are supported: + +- `name` - (Required) The name of the deployment pipeline. +- `integration_type` - (Required) The integration type of the deployment pipeline. Allowed values are `GITHUB` or `API`. +- `integration_key` - (Computed) The integration key of the deployment pipeline. +- `team` - (Optional) One or more [team](#team-arguments) blocks. +- `created_at` - (Computed) The creation date of the deployment pipeline. +- `updated_at` - (Computed) The latest date the deployment pipeline was updated at. +- `integration_url` - (Computed) The integration url of the deployment pipeline. Deployment events are sent to this URL. +- `github` - The [github](#github-arguments) block allows configuring parameters for GitHub. + +#### Team Arguments + +- `id` - (Required) The ID of the team. +- `name` - (Optional) The name of the team. + +#### GitHub Arguments + +- `branch_filter` - One or more branch filters to only accept events on specified branches. +- `event_filter` - One or more event filters to only accept events on specified actions. Allowed values are `pull_request`, `push` and `release`. + +## Import + +Deployment pipelines can be imported using the `id`, e.g. + +```sh +$ terraform import ilert_deployment_pipeline.main 123456789 +```