Skip to content

Commit 278f2b3

Browse files
authored
Merge pull request #908 from timofurrer/bugfix/issue-906
resource/gitlab_project: fix waiting for default branch protection during creation
2 parents acbd41c + 7fa7807 commit 278f2b3

File tree

3 files changed

+80
-24
lines changed

3 files changed

+80
-24
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 3.11.1 (2022-03-02)
2+
3+
BUG FIXES:
4+
5+
* resource/gitlab_project: fix waiting for default branch protection during creation ([#908](https://github.com/gitlabhq/terraform-provider-gitlab/pull/908))
6+
17
## 3.11.0 (2022-03-01)
28

39
FEATURES:

internal/provider/resource_gitlab_project.go

+48-24
Original file line numberDiff line numberDiff line change
@@ -667,33 +667,42 @@ func resourceGitlabProjectCreate(ctx context.Context, d *schema.ResourceData, me
667667
}
668668
}
669669

670-
// Branch protection for a newly created branch is an async action, so use WaitForState to ensure it's protected
671-
// before we continue. Note this check should only be required when there is a custom default branch set
672-
// See issue 800: https://github.com/gitlabhq/terraform-provider-gitlab/issues/800
673-
stateConf := &resource.StateChangeConf{
674-
Pending: []string{"false"},
675-
Target: []string{"true"},
676-
Timeout: 2 * time.Minute, //The async action usually completes very quickly, within seconds. Don't wait too long.
677-
Refresh: func() (interface{}, string, error) {
678-
branch, _, err := client.Branches.GetBranch(project.ID, project.DefaultBranch, gitlab.WithContext(ctx))
679-
if err != nil {
680-
if is404(err) {
681-
// When we hit a 404 here, it means the default branch wasn't created at all as part of the project
682-
// this will happen when "default_branch" isn't set, or "initialize_with_readme" is set to false.
683-
// We don't need to wait anymore, so return "true" to exist the wait loop.
684-
return branch, "true", nil
685-
}
670+
// If the project is assigned to a group namespace and the group has *default branch protection*
671+
// disabled (`default_branch_protection = 0`) then we don't have to wait for one.
672+
waitForDefaultBranchProtection, err := expectDefaultBranchProtection(ctx, client, project)
673+
if err != nil {
674+
return diag.Errorf("Failed to fetch group the project %d is owned by: %+v", project.ID, err)
675+
}
686676

687-
//This is legit error, return the error.
688-
return nil, "", err
689-
}
677+
if waitForDefaultBranchProtection {
678+
// Branch protection for a newly created branch is an async action, so use WaitForState to ensure it's protected
679+
// before we continue. Note this check should only be required when there is a custom default branch set
680+
// See issue 800: https://github.com/gitlabhq/terraform-provider-gitlab/issues/800
681+
stateConf := &resource.StateChangeConf{
682+
Pending: []string{"false"},
683+
Target: []string{"true"},
684+
Timeout: 2 * time.Minute, //The async action usually completes very quickly, within seconds. Don't wait too long.
685+
Refresh: func() (interface{}, string, error) {
686+
branch, _, err := client.Branches.GetBranch(project.ID, project.DefaultBranch, gitlab.WithContext(ctx))
687+
if err != nil {
688+
if is404(err) {
689+
// When we hit a 404 here, it means the default branch wasn't created at all as part of the project
690+
// this will happen when "default_branch" isn't set, or "initialize_with_readme" is set to false.
691+
// We don't need to wait anymore, so return "true" to exist the wait loop.
692+
return branch, "true", nil
693+
}
690694

691-
return branch, strconv.FormatBool(branch.Protected), nil
692-
},
693-
}
695+
//This is legit error, return the error.
696+
return nil, "", err
697+
}
698+
699+
return branch, strconv.FormatBool(branch.Protected), nil
700+
},
701+
}
694702

695-
if _, err := stateConf.WaitForStateContext(ctx); err != nil {
696-
return diag.Errorf("error while waiting for branch %s to reach 'protected' status, %s", project.DefaultBranch, err)
703+
if _, err := stateConf.WaitForStateContext(ctx); err != nil {
704+
return diag.Errorf("error while waiting for branch %s to reach 'protected' status, %s", project.DefaultBranch, err)
705+
}
697706
}
698707

699708
var editProjectOptions gitlab.EditProjectOptions
@@ -1178,3 +1187,18 @@ func flattenProjectPushRules(pushRules *gitlab.ProjectPushRules) (values []map[s
11781187
func namespaceOrPathChanged(ctx context.Context, d *schema.ResourceDiff, meta interface{}) bool {
11791188
return d.HasChange("namespace_id") || d.HasChange("path")
11801189
}
1190+
1191+
func expectDefaultBranchProtection(ctx context.Context, client *gitlab.Client, project *gitlab.Project) (bool, error) {
1192+
if project.Namespace.Kind == "group" {
1193+
group, _, err := client.Groups.GetGroup(project.Namespace.ID, nil, gitlab.WithContext(ctx))
1194+
if err != nil {
1195+
return false, err
1196+
}
1197+
1198+
return group.DefaultBranchProtection != 0, nil
1199+
}
1200+
1201+
// projects which are not assigned to a group can't have a "no branch protection" default,
1202+
// thus, we always expect a default branch protection.
1203+
return true, nil
1204+
}

internal/provider/resource_gitlab_project_test.go

+26
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,14 @@ func TestAccGitlabProject_groupWithoutDefaultBranchProtection(t *testing.T) {
428428
Config: testAccGitlabProjectConfigWithoutDefaultBranchProtection(rInt),
429429
Check: testAccCheckGitlabProjectExists("gitlab_project.foo", &project),
430430
},
431+
{
432+
Config: testAccGitlabProjectConfigWithoutDefaultBranchProtection(rInt),
433+
Destroy: true,
434+
},
435+
{
436+
Config: testAccGitlabProjectConfigWithoutDefaultBranchProtectionInitializeReadme(rInt),
437+
Check: testAccCheckGitlabProjectExists("gitlab_project.foo", &project),
438+
},
431439
},
432440
})
433441
}
@@ -1176,6 +1184,24 @@ resource "gitlab_project" "foo" {
11761184
`, rInt, rInt, rInt)
11771185
}
11781186

1187+
func testAccGitlabProjectConfigWithoutDefaultBranchProtectionInitializeReadme(rInt int) string {
1188+
return fmt.Sprintf(`
1189+
resource "gitlab_group" "foo" {
1190+
name = "foogroup2-%d"
1191+
path = "foogroup2-%d"
1192+
default_branch_protection = 0
1193+
visibility_level = "public"
1194+
}
1195+
1196+
resource "gitlab_project" "foo" {
1197+
name = "foo-%d"
1198+
description = "Terraform acceptance tests"
1199+
namespace_id = "${gitlab_group.foo.id}"
1200+
initialize_with_readme = true
1201+
}
1202+
`, rInt, rInt, rInt)
1203+
}
1204+
11791205
func testAccGitlabProjectTransferBetweenGroupsBefore(rInt int) string {
11801206
return fmt.Sprintf(`
11811207
resource "gitlab_group" "foo" {

0 commit comments

Comments
 (0)