Skip to content

Commit 60a040c

Browse files
Gcb allow build step failure (#7866) (#14498)
* Add allowFailure and allowExitCodes to CloudBuild Trigger * Add examples * fix typo * Update tests Signed-off-by: Modular Magician <[email protected]>
1 parent dd8ea1a commit 60a040c

File tree

4 files changed

+426
-12
lines changed

4 files changed

+426
-12
lines changed

.changelog/7866.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
cloudbuild: Added `allow_failure` and `allow_exit_codes` to `build.step` in `google_cloudbuild_trigger` resource
3+
```

google/resource_cloudbuild_trigger.go

+65-12
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,27 @@ you attempt to use them.
233233
If you built an image in a previous build step, it will be stored in the
234234
host's Docker daemon's cache and is available to use as the name for a
235235
later build step.`,
236+
},
237+
"allow_exit_codes": {
238+
Type: schema.TypeList,
239+
Optional: true,
240+
Description: `Allow this build step to fail without failing the entire build if and
241+
only if the exit code is one of the specified codes.
242+
243+
If 'allowFailure' is also specified, this field will take precedence.`,
244+
Elem: &schema.Schema{
245+
Type: schema.TypeInt,
246+
},
247+
},
248+
"allow_failure": {
249+
Type: schema.TypeBool,
250+
Optional: true,
251+
Description: `Allow this build step to fail without failing the entire build.
252+
If false, the entire build will fail if this step fails. Otherwise, the
253+
build will succeed, but this step will still have a failure status.
254+
Error information will be reported in the 'failureDetail' field.
255+
256+
'allowExitCodes' takes precedence over this field.`,
236257
},
237258
"args": {
238259
Type: schema.TypeList,
@@ -2394,18 +2415,20 @@ func flattenCloudBuildTriggerBuildStep(v interface{}, d *schema.ResourceData, co
23942415
continue
23952416
}
23962417
transformed = append(transformed, map[string]interface{}{
2397-
"name": flattenCloudBuildTriggerBuildStepName(original["name"], d, config),
2398-
"args": flattenCloudBuildTriggerBuildStepArgs(original["args"], d, config),
2399-
"env": flattenCloudBuildTriggerBuildStepEnv(original["env"], d, config),
2400-
"id": flattenCloudBuildTriggerBuildStepId(original["id"], d, config),
2401-
"entrypoint": flattenCloudBuildTriggerBuildStepEntrypoint(original["entrypoint"], d, config),
2402-
"dir": flattenCloudBuildTriggerBuildStepDir(original["dir"], d, config),
2403-
"secret_env": flattenCloudBuildTriggerBuildStepSecretEnv(original["secretEnv"], d, config),
2404-
"timeout": flattenCloudBuildTriggerBuildStepTimeout(original["timeout"], d, config),
2405-
"timing": flattenCloudBuildTriggerBuildStepTiming(original["timing"], d, config),
2406-
"volumes": flattenCloudBuildTriggerBuildStepVolumes(original["volumes"], d, config),
2407-
"wait_for": flattenCloudBuildTriggerBuildStepWaitFor(original["waitFor"], d, config),
2408-
"script": flattenCloudBuildTriggerBuildStepScript(original["script"], d, config),
2418+
"name": flattenCloudBuildTriggerBuildStepName(original["name"], d, config),
2419+
"args": flattenCloudBuildTriggerBuildStepArgs(original["args"], d, config),
2420+
"env": flattenCloudBuildTriggerBuildStepEnv(original["env"], d, config),
2421+
"id": flattenCloudBuildTriggerBuildStepId(original["id"], d, config),
2422+
"entrypoint": flattenCloudBuildTriggerBuildStepEntrypoint(original["entrypoint"], d, config),
2423+
"dir": flattenCloudBuildTriggerBuildStepDir(original["dir"], d, config),
2424+
"secret_env": flattenCloudBuildTriggerBuildStepSecretEnv(original["secretEnv"], d, config),
2425+
"timeout": flattenCloudBuildTriggerBuildStepTimeout(original["timeout"], d, config),
2426+
"timing": flattenCloudBuildTriggerBuildStepTiming(original["timing"], d, config),
2427+
"volumes": flattenCloudBuildTriggerBuildStepVolumes(original["volumes"], d, config),
2428+
"wait_for": flattenCloudBuildTriggerBuildStepWaitFor(original["waitFor"], d, config),
2429+
"script": flattenCloudBuildTriggerBuildStepScript(original["script"], d, config),
2430+
"allow_failure": flattenCloudBuildTriggerBuildStepAllowFailure(original["allowFailure"], d, config),
2431+
"allow_exit_codes": flattenCloudBuildTriggerBuildStepAllowExitCodes(original["allowExitCodes"], d, config),
24092432
})
24102433
}
24112434
return transformed
@@ -2481,6 +2504,14 @@ func flattenCloudBuildTriggerBuildStepScript(v interface{}, d *schema.ResourceDa
24812504
return v
24822505
}
24832506

2507+
func flattenCloudBuildTriggerBuildStepAllowFailure(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
2508+
return v
2509+
}
2510+
2511+
func flattenCloudBuildTriggerBuildStepAllowExitCodes(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
2512+
return v
2513+
}
2514+
24842515
func flattenCloudBuildTriggerBuildArtifacts(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
24852516
if v == nil {
24862517
return nil
@@ -3840,6 +3871,20 @@ func expandCloudBuildTriggerBuildStep(v interface{}, d TerraformResourceData, co
38403871
transformed["script"] = transformedScript
38413872
}
38423873

3874+
transformedAllowFailure, err := expandCloudBuildTriggerBuildStepAllowFailure(original["allow_failure"], d, config)
3875+
if err != nil {
3876+
return nil, err
3877+
} else if val := reflect.ValueOf(transformedAllowFailure); val.IsValid() && !isEmptyValue(val) {
3878+
transformed["allowFailure"] = transformedAllowFailure
3879+
}
3880+
3881+
transformedAllowExitCodes, err := expandCloudBuildTriggerBuildStepAllowExitCodes(original["allow_exit_codes"], d, config)
3882+
if err != nil {
3883+
return nil, err
3884+
} else if val := reflect.ValueOf(transformedAllowExitCodes); val.IsValid() && !isEmptyValue(val) {
3885+
transformed["allowExitCodes"] = transformedAllowExitCodes
3886+
}
3887+
38433888
req = append(req, transformed)
38443889
}
38453890
return req, nil
@@ -3926,6 +3971,14 @@ func expandCloudBuildTriggerBuildStepScript(v interface{}, d TerraformResourceDa
39263971
return v, nil
39273972
}
39283973

3974+
func expandCloudBuildTriggerBuildStepAllowFailure(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
3975+
return v, nil
3976+
}
3977+
3978+
func expandCloudBuildTriggerBuildStepAllowExitCodes(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
3979+
return v, nil
3980+
}
3981+
39293982
func expandCloudBuildTriggerBuildArtifacts(v interface{}, d TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
39303983
l := v.([]interface{})
39313984
if len(l) == 0 || l[0] == nil {

google/resource_cloudbuild_trigger_generated_test.go

+192
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,198 @@ resource "google_cloudbuild_trigger" "bbs-pull-request-trigger" {
534534
`, context)
535535
}
536536

537+
func TestAccCloudBuildTrigger_cloudbuildTriggerAllowFailureExample(t *testing.T) {
538+
t.Parallel()
539+
540+
context := map[string]interface{}{
541+
"random_suffix": RandString(t, 10),
542+
}
543+
544+
VcrTest(t, resource.TestCase{
545+
PreCheck: func() { acctest.AccTestPreCheck(t) },
546+
ProtoV5ProviderFactories: ProtoV5ProviderFactories(t),
547+
CheckDestroy: testAccCheckCloudBuildTriggerDestroyProducer(t),
548+
Steps: []resource.TestStep{
549+
{
550+
Config: testAccCloudBuildTrigger_cloudbuildTriggerAllowFailureExample(context),
551+
},
552+
{
553+
ResourceName: "google_cloudbuild_trigger.allow-failure-trigger",
554+
ImportState: true,
555+
ImportStateVerify: true,
556+
ImportStateVerifyIgnore: []string{"location"},
557+
},
558+
},
559+
})
560+
}
561+
562+
func testAccCloudBuildTrigger_cloudbuildTriggerAllowFailureExample(context map[string]interface{}) string {
563+
return Nprintf(`
564+
resource "google_cloudbuild_trigger" "allow-failure-trigger" {
565+
location = "global"
566+
567+
trigger_template {
568+
branch_name = "main"
569+
repo_name = "my-repo"
570+
}
571+
572+
build {
573+
step {
574+
name = "ubuntu"
575+
args = ["-c", "exit 1"]
576+
allow_failure = true
577+
}
578+
579+
source {
580+
storage_source {
581+
bucket = "mybucket"
582+
object = "source_code.tar.gz"
583+
}
584+
}
585+
tags = ["build", "newFeature"]
586+
substitutions = {
587+
_FOO = "bar"
588+
_BAZ = "qux"
589+
}
590+
queue_ttl = "20s"
591+
logs_bucket = "gs://mybucket/logs"
592+
secret {
593+
kms_key_name = "projects/myProject/locations/global/keyRings/keyring-name/cryptoKeys/key-name"
594+
secret_env = {
595+
PASSWORD = "ZW5jcnlwdGVkLXBhc3N3b3JkCg=="
596+
}
597+
}
598+
available_secrets {
599+
secret_manager {
600+
env = "MY_SECRET"
601+
version_name = "projects/myProject/secrets/mySecret/versions/latest"
602+
}
603+
}
604+
artifacts {
605+
images = ["gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA"]
606+
objects {
607+
location = "gs://bucket/path/to/somewhere/"
608+
paths = ["path"]
609+
}
610+
}
611+
options {
612+
source_provenance_hash = ["MD5"]
613+
requested_verify_option = "VERIFIED"
614+
machine_type = "N1_HIGHCPU_8"
615+
disk_size_gb = 100
616+
substitution_option = "ALLOW_LOOSE"
617+
dynamic_substitutions = true
618+
log_streaming_option = "STREAM_OFF"
619+
worker_pool = "pool"
620+
logging = "LEGACY"
621+
env = ["ekey = evalue"]
622+
secret_env = ["secretenv = svalue"]
623+
volumes {
624+
name = "v1"
625+
path = "v1"
626+
}
627+
}
628+
}
629+
}
630+
`, context)
631+
}
632+
633+
func TestAccCloudBuildTrigger_cloudbuildTriggerAllowExitCodesExample(t *testing.T) {
634+
t.Parallel()
635+
636+
context := map[string]interface{}{
637+
"random_suffix": RandString(t, 10),
638+
}
639+
640+
VcrTest(t, resource.TestCase{
641+
PreCheck: func() { acctest.AccTestPreCheck(t) },
642+
ProtoV5ProviderFactories: ProtoV5ProviderFactories(t),
643+
CheckDestroy: testAccCheckCloudBuildTriggerDestroyProducer(t),
644+
Steps: []resource.TestStep{
645+
{
646+
Config: testAccCloudBuildTrigger_cloudbuildTriggerAllowExitCodesExample(context),
647+
},
648+
{
649+
ResourceName: "google_cloudbuild_trigger.allow-exit-codes-trigger",
650+
ImportState: true,
651+
ImportStateVerify: true,
652+
ImportStateVerifyIgnore: []string{"location"},
653+
},
654+
},
655+
})
656+
}
657+
658+
func testAccCloudBuildTrigger_cloudbuildTriggerAllowExitCodesExample(context map[string]interface{}) string {
659+
return Nprintf(`
660+
resource "google_cloudbuild_trigger" "allow-exit-codes-trigger" {
661+
location = "global"
662+
663+
trigger_template {
664+
branch_name = "main"
665+
repo_name = "my-repo"
666+
}
667+
668+
build {
669+
step {
670+
name = "ubuntu"
671+
args = ["-c", "exit 1"]
672+
allow_exit_codes = [1,3]
673+
}
674+
675+
source {
676+
storage_source {
677+
bucket = "mybucket"
678+
object = "source_code.tar.gz"
679+
}
680+
}
681+
tags = ["build", "newFeature"]
682+
substitutions = {
683+
_FOO = "bar"
684+
_BAZ = "qux"
685+
}
686+
queue_ttl = "20s"
687+
logs_bucket = "gs://mybucket/logs"
688+
secret {
689+
kms_key_name = "projects/myProject/locations/global/keyRings/keyring-name/cryptoKeys/key-name"
690+
secret_env = {
691+
PASSWORD = "ZW5jcnlwdGVkLXBhc3N3b3JkCg=="
692+
}
693+
}
694+
available_secrets {
695+
secret_manager {
696+
env = "MY_SECRET"
697+
version_name = "projects/myProject/secrets/mySecret/versions/latest"
698+
}
699+
}
700+
artifacts {
701+
images = ["gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA"]
702+
objects {
703+
location = "gs://bucket/path/to/somewhere/"
704+
paths = ["path"]
705+
}
706+
}
707+
options {
708+
source_provenance_hash = ["MD5"]
709+
requested_verify_option = "VERIFIED"
710+
machine_type = "N1_HIGHCPU_8"
711+
disk_size_gb = 100
712+
substitution_option = "ALLOW_LOOSE"
713+
dynamic_substitutions = true
714+
log_streaming_option = "STREAM_OFF"
715+
worker_pool = "pool"
716+
logging = "LEGACY"
717+
env = ["ekey = evalue"]
718+
secret_env = ["secretenv = svalue"]
719+
volumes {
720+
name = "v1"
721+
path = "v1"
722+
}
723+
}
724+
}
725+
}
726+
`, context)
727+
}
728+
537729
func testAccCheckCloudBuildTriggerDestroyProducer(t *testing.T) func(s *terraform.State) error {
538730
return func(s *terraform.State) error {
539731
for name, rs := range s.RootModule().Resources {

0 commit comments

Comments
 (0)