Skip to content

Commit 8b65434

Browse files
committed
resource/gitlab_project: correctly handle push rules add and edit
This is a possible approach to fix #836. Even though, I am not sure if that is really that elegant of a solution ... The root problem here is that the SDK v2 doesn't support to check if an attribute value was set in config, state or the plan. During creation of push rules, we don't have a way to distinguish between the default and if the user has set the default explicitly. This makes the behavior working for all cases (AFAIK) (incl. changing the instance default push rules, no automated test possible yet). This will be possbile in the new terraform provider framework.
1 parent 0852693 commit 8b65434

File tree

2 files changed

+64
-31
lines changed

2 files changed

+64
-31
lines changed

gitlab/resource_gitlab_project.go

Lines changed: 43 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -915,129 +915,141 @@ func resourceGitlabProjectDelete(ctx context.Context, d *schema.ResourceData, me
915915
func editOrAddPushRules(ctx context.Context, client *gitlab.Client, projectID string, d *schema.ResourceData) error {
916916
log.Printf("[DEBUG] Editing push rules for project %q", projectID)
917917

918-
editOptions := expandEditProjectPushRuleOptions(d)
919-
_, _, err := client.Projects.EditProjectPushRule(projectID, editOptions, gitlab.WithContext(ctx))
920-
if err == nil {
921-
return nil
922-
}
918+
pushRules, _, err := client.Projects.GetProjectPushRules(d.Id(), gitlab.WithContext(ctx))
919+
if is404(err) || pushRules.ID == 0 {
920+
if addOptions, needToAdd := expandAddProjectPushRuleOptions(d); needToAdd {
921+
log.Printf("[DEBUG] Creating new push rules for project %q", projectID)
922+
_, _, err = client.Projects.AddProjectPushRule(projectID, addOptions, gitlab.WithContext(ctx))
923+
if err != nil {
924+
return err
925+
}
926+
} else {
927+
log.Printf("[DEBUG] Don't create new push rules for defaults for project %q", projectID)
928+
}
923929

924-
var httpErr *gitlab.ErrorResponse
925-
if !errors.As(err, &httpErr) || httpErr.Response.StatusCode != http.StatusNotFound {
926-
return err
930+
return nil
927931
}
928932

929-
// A 404 could mean that the push rules need to be re-created.
930-
931-
log.Printf("[DEBUG] Failed to edit push rules for project %q: %v", projectID, err)
932-
log.Printf("[DEBUG] Creating new push rules for project %q", projectID)
933-
934-
addOptions := expandAddProjectPushRuleOptions(d)
935-
_, _, err = client.Projects.AddProjectPushRule(projectID, addOptions, gitlab.WithContext(ctx))
936-
if err != nil {
937-
return err
933+
editOptions := expandEditProjectPushRuleOptions(d, pushRules)
934+
log.Printf("[DEBUG] Editing existing push rules for project %q", projectID)
935+
_, _, err = client.Projects.EditProjectPushRule(projectID, editOptions, gitlab.WithContext(ctx))
936+
if err == nil {
937+
return nil
938938
}
939939

940940
return nil
941941
}
942942

943-
func expandEditProjectPushRuleOptions(d *schema.ResourceData) *gitlab.EditProjectPushRuleOptions {
943+
func expandEditProjectPushRuleOptions(d *schema.ResourceData, currentPushRules *gitlab.ProjectPushRules) *gitlab.EditProjectPushRuleOptions {
944944
options := &gitlab.EditProjectPushRuleOptions{}
945945

946-
if d.HasChange("push_rules.0.author_email_regex") {
946+
if d.HasChange("push_rules.0.author_email_regex") || d.Get("push_rules.0.author_email_regex") != currentPushRules.AuthorEmailRegex {
947947
options.AuthorEmailRegex = gitlab.String(d.Get("push_rules.0.author_email_regex").(string))
948948
}
949949

950-
if d.HasChange("push_rules.0.branch_name_regex") {
950+
if d.HasChange("push_rules.0.branch_name_regex") || d.Get("push_rules.0.branch_name_regex") != currentPushRules.BranchNameRegex {
951951
options.BranchNameRegex = gitlab.String(d.Get("push_rules.0.branch_name_regex").(string))
952952
}
953953

954-
if d.HasChange("push_rules.0.commit_message_regex") {
954+
if d.HasChange("push_rules.0.commit_message_regex") || d.Get("push_rules.0.commit_message_regex") != currentPushRules.CommitMessageRegex {
955955
options.CommitMessageRegex = gitlab.String(d.Get("push_rules.0.commit_message_regex").(string))
956956
}
957957

958-
if d.HasChange("push_rules.0.commit_message_negative_regex") {
958+
if d.HasChange("push_rules.0.commit_message_negative_regex") || d.Get("push_rules.0.commit_message_negative_regex") != currentPushRules.CommitMessageNegativeRegex {
959959
options.CommitMessageNegativeRegex = gitlab.String(d.Get("push_rules.0.commit_message_negative_regex").(string))
960960
}
961961

962-
if d.HasChange("push_rules.0.file_name_regex") {
962+
if d.HasChange("push_rules.0.file_name_regex") || d.Get("push_rules.0.file_name_regex") != currentPushRules.FileNameRegex {
963963
options.FileNameRegex = gitlab.String(d.Get("push_rules.0.file_name_regex").(string))
964964
}
965965

966-
if d.HasChange("push_rules.0.commit_committer_check") {
966+
if d.HasChange("push_rules.0.commit_committer_check") || d.Get("push_rules.0.commit_committer_check") != currentPushRules.CommitCommitterCheck {
967967
options.CommitCommitterCheck = gitlab.Bool(d.Get("push_rules.0.commit_committer_check").(bool))
968968
}
969969

970-
if d.HasChange("push_rules.0.deny_delete_tag") {
970+
if d.HasChange("push_rules.0.deny_delete_tag") || d.Get("push_rules.0.deny_delete_tag") != currentPushRules.DenyDeleteTag {
971971
options.DenyDeleteTag = gitlab.Bool(d.Get("push_rules.0.deny_delete_tag").(bool))
972972
}
973973

974-
if d.HasChange("push_rules.0.member_check") {
974+
if d.HasChange("push_rules.0.member_check") || d.Get("push_rules.0.member_check") != currentPushRules.MemberCheck {
975975
options.MemberCheck = gitlab.Bool(d.Get("push_rules.0.member_check").(bool))
976976
}
977977

978-
if d.HasChange("push_rules.0.prevent_secrets") {
978+
if d.HasChange("push_rules.0.prevent_secrets") || d.Get("push_rules.0.prevent_secrets") != currentPushRules.PreventSecrets {
979979
options.PreventSecrets = gitlab.Bool(d.Get("push_rules.0.prevent_secrets").(bool))
980980
}
981981

982-
if d.HasChange("push_rules.0.reject_unsigned_commits") {
982+
if d.HasChange("push_rules.0.reject_unsigned_commits") || d.Get("push_rules.0.reject_unsigned_commits") != currentPushRules.RejectUnsignedCommits {
983983
options.RejectUnsignedCommits = gitlab.Bool(d.Get("push_rules.0.reject_unsigned_commits").(bool))
984984
}
985985

986-
if d.HasChange("push_rules.0.max_file_size") {
986+
if d.HasChange("push_rules.0.max_file_size") || d.Get("push_rules.0.max_file_size") != currentPushRules.MaxFileSize {
987987
options.MaxFileSize = gitlab.Int(d.Get("push_rules.0.max_file_size").(int))
988988
}
989989

990990
return options
991991
}
992992

993-
func expandAddProjectPushRuleOptions(d *schema.ResourceData) *gitlab.AddProjectPushRuleOptions {
993+
func expandAddProjectPushRuleOptions(d *schema.ResourceData) (*gitlab.AddProjectPushRuleOptions, bool) {
994994
options := &gitlab.AddProjectPushRuleOptions{}
995+
needToAdd := false
995996

996997
if v, ok := d.GetOk("push_rules.0.author_email_regex"); ok {
997998
options.AuthorEmailRegex = gitlab.String(v.(string))
999+
needToAdd = true
9981000
}
9991001

10001002
if v, ok := d.GetOk("push_rules.0.branch_name_regex"); ok {
10011003
options.BranchNameRegex = gitlab.String(v.(string))
1004+
needToAdd = true
10021005
}
10031006

10041007
if v, ok := d.GetOk("push_rules.0.commit_message_regex"); ok {
10051008
options.CommitMessageRegex = gitlab.String(v.(string))
1009+
needToAdd = true
10061010
}
10071011

10081012
if v, ok := d.GetOk("push_rules.0.commit_message_negative_regex"); ok {
10091013
options.CommitMessageNegativeRegex = gitlab.String(v.(string))
1014+
needToAdd = true
10101015
}
10111016

10121017
if v, ok := d.GetOk("push_rules.0.file_name_regex"); ok {
10131018
options.FileNameRegex = gitlab.String(v.(string))
1019+
needToAdd = true
10141020
}
10151021

10161022
if v, ok := d.GetOk("push_rules.0.commit_committer_check"); ok {
10171023
options.CommitCommitterCheck = gitlab.Bool(v.(bool))
1024+
needToAdd = true
10181025
}
10191026

10201027
if v, ok := d.GetOk("push_rules.0.deny_delete_tag"); ok {
10211028
options.DenyDeleteTag = gitlab.Bool(v.(bool))
1029+
needToAdd = true
10221030
}
10231031

10241032
if v, ok := d.GetOk("push_rules.0.member_check"); ok {
10251033
options.MemberCheck = gitlab.Bool(v.(bool))
1034+
needToAdd = true
10261035
}
10271036

10281037
if v, ok := d.GetOk("push_rules.0.prevent_secrets"); ok {
10291038
options.PreventSecrets = gitlab.Bool(v.(bool))
1039+
needToAdd = true
10301040
}
10311041

10321042
if v, ok := d.GetOk("push_rules.0.reject_unsigned_commits"); ok {
10331043
options.RejectUnsignedCommits = gitlab.Bool(v.(bool))
1044+
needToAdd = true
10341045
}
10351046

10361047
if v, ok := d.GetOk("push_rules.0.max_file_size"); ok {
10371048
options.MaxFileSize = gitlab.Int(v.(int))
1049+
needToAdd = true
10381050
}
10391051

1040-
return options
1052+
return options, needToAdd
10411053
}
10421054

10431055
func flattenProjectPushRules(pushRules *gitlab.ProjectPushRules) (values []map[string]interface{}) {

gitlab/resource_gitlab_project_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,27 @@ func TestAccGitlabProject_archiveOnDestroy(t *testing.T) {
398398
})
399399
}
400400

401+
func TestAccGitlabProject_setSinglePushRuleToDefault(t *testing.T) {
402+
rInt := acctest.RandInt()
403+
404+
resource.Test(t, resource.TestCase{
405+
PreCheck: func() { testAccPreCheck(t) },
406+
Providers: testAccProviders,
407+
CheckDestroy: testAccCheckGitlabProjectDestroy,
408+
Steps: []resource.TestStep{
409+
{
410+
SkipFunc: isRunningInCE,
411+
Config: testAccGitlabProjectConfigPushRules(rInt, `
412+
member_check = false
413+
`),
414+
Check: testAccCheckGitlabProjectPushRules("gitlab_project.foo", &gitlab.ProjectPushRules{
415+
MemberCheck: false,
416+
}),
417+
},
418+
},
419+
})
420+
}
421+
401422
func TestAccGitlabProject_IssueMergeRequestTemplates(t *testing.T) {
402423
var project gitlab.Project
403424
rInt := acctest.RandInt()

0 commit comments

Comments
 (0)