-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CodePipeline with dynamic actions always reports changes #14357
Comments
This bug causes Terraform to unnecessarily throw away all in-progress executions in an unrecoverable manner, because the CodePipeline service supercedes any in-progress executions whenever the pipeline configuration is modified (even if effectively no changes were made). The pipeline must undergo an entirely new execution to e.g. retry a failed action. For teams trying to manage multiple versions deployed to multiple deployment rings (multiple pipeline executions running concurrently with each at different stages), this can be a big productivity sink. |
I'm running into this problem without using My plans consistently perform the following:
Here's a lightly redacted definition of my Deploy stage: stage {
name = "Deploy"
action {
run_order = 1
category = "Deploy"
name = "ApiChangeSet"
owner = "AWS"
provider = "CloudFormation"
version = "1"
input_artifacts = [
"BuildArtifact"]
output_artifacts = [
"ApiChangeSet"]
configuration = {
ActionMode = "CHANGE_SET_REPLACE"
RoleArn = aws_iam_role.cloudformation.arn
StackName = aws_cloudformation_stack.api.name
ChangeSetName = "ApiChangeSet"
TemplatePath = "BuildArtifact::api-packaged.yaml"
Capabilities = "CAPABILITY_IAM"
}
}
action {
run_order = 2
category = "Deploy"
name = "ApiChangeSetExecute"
owner = "AWS"
provider = "CloudFormation"
version = "1"
input_artifacts = [
"ApiChangeSet"]
configuration = {
ActionMode = "CHANGE_SET_EXECUTE"
RoleArn = aws_iam_role.cloudformation.arn
StackName = aws_cloudformation_stack.api.name
ChangeSetName = "ApiChangeSet"
TemplatePath = "BuildArtifact::api-packaged.yaml"
}
}
action {
run_order = 1
category = "Deploy"
name = "AdminApiChangeSet"
owner = "AWS"
provider = "CloudFormation"
version = "1"
input_artifacts = [
"BuildArtifact"]
output_artifacts = [
"AdminApiChangeSet"]
configuration = {
ActionMode = "CHANGE_SET_REPLACE"
RoleArn = aws_iam_role.cloudformation.arn
StackName = aws_cloudformation_stack.admin_api.name
ChangeSetName = "AdminApiChangeSet"
TemplatePath = "BuildArtifact::admin-api-packaged.yaml"
Capabilities = "CAPABILITY_IAM"
}
}
action {
run_order = 2
category = "Deploy"
name = "AdminApiChangeSetExecute"
owner = "AWS"
provider = "CloudFormation"
version = "1"
input_artifacts = [
"BuildArtifact"]
configuration = {
ActionMode = "CHANGE_SET_EXECUTE"
RoleArn = aws_iam_role.cloudformation.arn
StackName = aws_cloudformation_stack.admin_api.name
ChangeSetName = "AdminApiChangeSet"
TemplatePath = "BuildArtifact::admin-api-packaged.yaml"
}
}
} |
After several rearrangements of my configuration, I've been able to prevent changes by ordering my actions as follows:
My actions listed in my previous comment are now in this order: stage {
name = "Deploy"
action {
run_order = 1
category = "Deploy"
name = "AdminApiChangeSet"
...
}
action {
run_order = 1
category = "Deploy"
name = "ApiChangeSet"
...
}
action {
run_order = 2
category = "Deploy"
name = "AdminApiChangeSetExecute"
...
}
action {
run_order = 2
category = "Deploy"
name = "ApiChangeSetExecute"
...
}
} I don't know if there's any way to control the order with |
Unfortunately, I'm unable to control this using the idea above from @mousedownmike - I am trying to use dynamic "action" blocks though, so that is likely the difference:
My stage definition looks like so: dynamic "stage" {
for_each = length(var.codebuild_projects) > 0 ? [1] : []
content {
name = "Build"
dynamic "action" {
for_each = length(var.codebuild_projects) > 0 ? var.codebuild_projects : []
content {
name = lookup(action.key, "action_name")
category = "Build"
owner = "AWS"
provider = "CodeBuild"
version = "1"
run_order = lookup(action.key, "run_order")
namespace = lookup(action.key, "namespace", null)
input_artifacts = ["source_output"]
output_artifacts = contains(keys(action.key), "output_artifact") ? [action.key.output_artifact] : []
configuration = {
ProjectName = lookup(action.key, "codebuild_project")
EnvironmentVariables = jsonencode([
{
name = "REPOSITORY_URI"
value = var.ecr_repository
type = "PLAINTEXT"
},
{
name = "IMAGE_TAG"
value = each.key
type = "PLAINTEXT"
}
])
}
}
}
}
} I have tried ordering the elements of my codebuild_projects = [
{
run_order = "10"
codebuild_project = aws_codebuild_project.docker_build_and_push.name
action_name = "build"
namespace = "build"
},
{
run_order = "1"
codebuild_project = aws_codebuild_project.create_cloudformation_artifact.name
action_name = "cloudformation_artifact"
output_artifact = "cloudformation_artifact"
},
{
run_order = "1"
codebuild_project = aws_codebuild_project.manage_semantic_version.name
action_name = "version"
namespace = "version"
}
] |
I've just taken a look at trying to add a diff suppress function for this, but I've been hit by a bug in the terraform plugin sdk. As these only work for strings currently I can't see how this can be fixed. If one of the maintainers or anyone else can point me at another approach I'll happily take the work on to fix this. Some background on why I was looking at a diff suppress. The AWS API although it isn't documented seems to return a default value for run_order set to 1, also it sorts the actions for a given stage first by run order, then by name. I intended to sort the "new" config in this way then compare to the "old" and if the same suppress the diff. |
This bug is really troublesome.
Terraform probably expands this to:
while AWS CodePipeline sorts it according the correct run order and returns:
|
Do we have any update on this? I'm facing the same issue with the following code resource "aws_codepipeline" "this" {
name = "${lookup(var.tags, "Environment", "")}-terraform-pipeline"
role_arn = aws_iam_role.this.arn
artifact_store {
location = data.aws_s3_bucket.codepipeline_bucket.bucket
type = "S3"
}
dynamic "stage" {
for_each = local.stages
content {
name = stage.value.name
dynamic "action" {
for_each = stage.value.action
content {
name = action.value.name
category = action.value.category
owner = action.value.owner
provider = action.value.provider
version = action.value.version
run_order = action.value.run_order
input_artifacts = action.value.input_artifacts
output_artifacts = action.value.output_artifacts
configuration = action.value.configuration
}
}
}
}
}
locals {
stages = [{
name = "Source"
action = [{
run_order = 1
category = "Source"
name = "Source"
owner = "AWS"
provider = "CodeCommit"
version = "1"
input_artifacts = []
output_artifacts = ["SourceArtifacts"]
configuration = {
BranchName = "master"
OutputArtifactFormat = "CODEBUILD_CLONE_REF"
RepositoryName = local.repo_name
ProjectName = null
}
}]
}, {
name = "dev"
action = [{
run_order = 2
category = "Build"
name = "InitAndPlan"
owner = "AWS"
provider = "CodeBuild"
version = "1"
input_artifacts = ["SourceArtifacts"]
output_artifacts = ["PlanArtifacts"]
configuration = {
BranchName = null
OutputArtifactFormat = null
RepositoryName = null
ProjectName = module.codebuild_tf_init_plan.name
}
}, {
run_order = 3
category = "Approval"
name = "Approve"
owner = "AWS"
provider = "Manual"
version = "1"
input_artifacts = []
output_artifacts = []
configuration = {
BranchName = null
OutputArtifactFormat = null
RepositoryName = null
ProjectName = null
}
}]
}]
} Versions used
|
Well, after reaching out to Stackoverflow, it seems that I had to use a As per the docs a set is
Which I guess somehow conflicted with trying to set the order of the actions? |
Hi All, faced the same issue. Does anyone have fixed or mitigated it? Is it possible to convert the |
Hi, module looks like:
and module call looks like:
|
Thanks pauliuspetka. |
I have the same issue. I use a CodePipeline to build run a bunch of different TF modules in a specific order. I dynamically generate the list of codepipeline_actions in my locals. My terraform: locals.tf
codepipline.tf
I use an ignore_changes flag to prevent the false positive changes but this is not ideal (since their aren't really any changes) |
I am working on something similar would you be willing to share your progress and how you defined your stage? I am getting to a point where I continue to hit this error message when i work with the environment variables.
|
Hi @juanpgomez-gsa. I didn't face exactly your problem, but regarding the described above issue I can say that I've fixed this problem by rewriting the code. The main idea is that in the first place there would be a stage |
@fireman777 could you share what type of variable declaration you used for the code_pipeline? |
Nevermind, I figured you use a map
Great post! I am going to create a sample GitHub repo for this. I have been looking for an answer to this for quite some time.! |
Hi @jpgomez-cwn, I've tried to change the type of the variable that contains stages but didn't have luck. |
Hey fireman777 thanks for the feedback. I will say the type of variable significantly changes how this works. specifically when people are using the EnviornmentVariables configuration. The approach pauliuspetka provided is the only variable type i have seen work to consume the stages, actions and configurations with environment variables. Map seems to be the best fit for this variable type without reaching Terraform limits that other variable types produce. |
Workaround for the problem: transform your stage datamodel to something which maintains the order. Meaning: if you have a set, or an object, transform this into a list and then order the list in the Example (pseudoishcode), you have map:
Separate this into one list per run order:
Add the lists together in order:
Then you can re-use the |
Community Note
Description
When updating an aws_codepipeline resource with dynamic actions that make use of
run_order
, the plan always reports changes.Terraform CLI and Terraform AWS Provider Version
Affected Resource(s)
Terraform Configuration Files
The following example defines a map of Terraform modules to plan and apply in a pipeline, with the order in which they should each be applied. Actions with the same order should run in parallel. A plan action and an apply action is created for each "module", and the run_order is calculated so that they all happen in the correct order.
This applies successfully however after running
terraform plan
again without making any code changes, Terraform thinks there are changes. This seems to be due to the actions being listed in the order they are generated in the code, rather than the order returned by the AWS API (which looks to be in pipeline order). Is there any way to ignore changes in the ordering of action blocks, ifrun_order
is supplied?Expected Behavior
Terraform reports no changes.
Actual Behavior
Terraform reports changes.
The text was updated successfully, but these errors were encountered: