Skip to content

Commit 9cb5889

Browse files
authored
Merge pull request #862 from PatrickRice-KSC/fix_flakey_project_resource
resolves #800: Add WaitForState support for resource_gitlab_project branch protection
2 parents 3c5083e + 3dfbdd8 commit 9cb5889

File tree

1 file changed

+41
-16
lines changed

1 file changed

+41
-16
lines changed

internal/provider/resource_gitlab_project.go

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ package provider
22

33
import (
44
"context"
5-
"errors"
65
"fmt"
76
"log"
8-
"net/http"
7+
"strconv"
98
"time"
109

1110
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -564,12 +563,11 @@ func resourceGitlabProjectCreate(ctx context.Context, d *schema.ResourceData, me
564563

565564
if _, ok := d.GetOk("push_rules"); ok {
566565
err := editOrAddPushRules(ctx, client, d.Id(), d)
567-
var httpError *gitlab.ErrorResponse
568-
if errors.As(err, &httpError) && httpError.Response.StatusCode == http.StatusNotFound {
569-
log.Printf("[DEBUG] Failed to edit push rules for project %q: %v", d.Id(), err)
570-
return diag.Errorf("Project push rules are not supported in your version of GitLab")
571-
}
572566
if err != nil {
567+
if is404(err) {
568+
log.Printf("[DEBUG] Failed to edit push rules for project %q: %v", d.Id(), err)
569+
return diag.Errorf("Project push rules are not supported in your version of GitLab")
570+
}
573571
return diag.Errorf("Failed to edit push rules for project %q: %s", d.Id(), err)
574572
}
575573
}
@@ -629,6 +627,35 @@ func resourceGitlabProjectCreate(ctx context.Context, d *schema.ResourceData, me
629627
}
630628
}
631629

630+
// Branch protection for a newly created branch is an async action, so use WaitForState to ensure it's protected
631+
// before we continue. Note this check should only be required when there is a custom default branch set
632+
// See issue 800: https://github.com/gitlabhq/terraform-provider-gitlab/issues/800
633+
stateConf := &resource.StateChangeConf{
634+
Pending: []string{"false"},
635+
Target: []string{"true"},
636+
Timeout: 2 * time.Minute, //The async action usually completes very quickly, within seconds. Don't wait too long.
637+
Refresh: func() (interface{}, string, error) {
638+
branch, _, err := client.Branches.GetBranch(project.ID, project.DefaultBranch, gitlab.WithContext(ctx))
639+
if err != nil {
640+
if is404(err) {
641+
// When we hit a 404 here, it means the default branch wasn't created at all as part of the project
642+
// this will happen when "default_branch" isn't set, or "initialize_with_readme" is set to false.
643+
// We don't need to wait anymore, so return "true" to exist the wait loop.
644+
return branch, "true", nil
645+
}
646+
647+
//This is legit error, return the error.
648+
return nil, "", err
649+
}
650+
651+
return branch, strconv.FormatBool(branch.Protected), nil
652+
},
653+
}
654+
655+
if _, err := stateConf.WaitForStateContext(ctx); err != nil {
656+
return diag.Errorf("error while waiting for branch %s to reach 'protected' status, %s", project.DefaultBranch, err)
657+
}
658+
632659
var editProjectOptions gitlab.EditProjectOptions
633660

634661
if v, ok := d.GetOk("mirror_overwrites_diverged_branches"); ok {
@@ -679,8 +706,7 @@ func resourceGitlabProjectRead(ctx context.Context, d *schema.ResourceData, meta
679706
log.Printf("[DEBUG] read gitlab project %q push rules", d.Id())
680707

681708
pushRules, _, err := client.Projects.GetProjectPushRules(d.Id(), gitlab.WithContext(ctx))
682-
var httpError *gitlab.ErrorResponse
683-
if errors.As(err, &httpError) && httpError.Response.StatusCode == http.StatusNotFound {
709+
if is404(err) {
684710
log.Printf("[DEBUG] Failed to get push rules for project %q: %v", d.Id(), err)
685711
} else if err != nil {
686712
return diag.Errorf("Failed to get push rules for project %q: %s", d.Id(), err)
@@ -868,12 +894,11 @@ func resourceGitlabProjectUpdate(ctx context.Context, d *schema.ResourceData, me
868894

869895
if d.HasChange("push_rules") {
870896
err := editOrAddPushRules(ctx, client, d.Id(), d)
871-
var httpError *gitlab.ErrorResponse
872-
if errors.As(err, &httpError) && httpError.Response.StatusCode == http.StatusNotFound {
873-
log.Printf("[DEBUG] Failed to get push rules for project %q: %v", d.Id(), err)
874-
return diag.Errorf("Project push rules are not supported in your version of GitLab")
875-
}
876897
if err != nil {
898+
if is404(err) {
899+
log.Printf("[DEBUG] Failed to get push rules for project %q: %v", d.Id(), err)
900+
return diag.Errorf("Project push rules are not supported in your version of GitLab")
901+
}
877902
return diag.Errorf("Failed to edit push rules for project %q: %s", d.Id(), err)
878903
}
879904
}
@@ -897,9 +922,9 @@ func resourceGitlabProjectDelete(ctx context.Context, d *schema.ResourceData, me
897922
Pending: []string{"Deleting"},
898923
Target: []string{"Deleted"},
899924
Refresh: func() (interface{}, string, error) {
900-
out, response, err := client.Projects.GetProject(d.Id(), nil, gitlab.WithContext(ctx))
925+
out, _, err := client.Projects.GetProject(d.Id(), nil, gitlab.WithContext(ctx))
901926
if err != nil {
902-
if response.StatusCode == 404 {
927+
if is404(err) {
903928
return out, "Deleted", nil
904929
}
905930
log.Printf("[ERROR] Received error: %#v", err)

0 commit comments

Comments
 (0)