Skip to content

Commit 944a927

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 944a927

File tree

2 files changed

+63
-29
lines changed

2 files changed

+63
-29
lines changed

gitlab/resource_gitlab_project.go

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -915,129 +915,142 @@ 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+
// NOTE: push rules id `0` indicates that there haven't been any push rules set.
920+
if err != nil || is404(err) || pushRules.ID == 0 {
921+
if addOptions, needToAdd := expandAddProjectPushRuleOptions(d); needToAdd {
922+
log.Printf("[DEBUG] Creating new push rules for project %q", projectID)
923+
_, _, err = client.Projects.AddProjectPushRule(projectID, addOptions, gitlab.WithContext(ctx))
924+
if err != nil {
925+
return err
926+
}
927+
} else {
928+
log.Printf("[DEBUG] Don't create new push rules for defaults for project %q", projectID)
929+
}
923930

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

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))
934+
editOptions := expandEditProjectPushRuleOptions(d, pushRules)
935+
log.Printf("[DEBUG] Editing existing push rules for project %q", projectID)
936+
_, _, err = client.Projects.EditProjectPushRule(projectID, editOptions, gitlab.WithContext(ctx))
936937
if err != nil {
937938
return err
938939
}
939940

940941
return nil
941942
}
942943

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

946-
if d.HasChange("push_rules.0.author_email_regex") {
947+
if d.HasChange("push_rules.0.author_email_regex") || d.Get("push_rules.0.author_email_regex") != currentPushRules.AuthorEmailRegex {
947948
options.AuthorEmailRegex = gitlab.String(d.Get("push_rules.0.author_email_regex").(string))
948949
}
949950

950-
if d.HasChange("push_rules.0.branch_name_regex") {
951+
if d.HasChange("push_rules.0.branch_name_regex") || d.Get("push_rules.0.branch_name_regex") != currentPushRules.BranchNameRegex {
951952
options.BranchNameRegex = gitlab.String(d.Get("push_rules.0.branch_name_regex").(string))
952953
}
953954

954-
if d.HasChange("push_rules.0.commit_message_regex") {
955+
if d.HasChange("push_rules.0.commit_message_regex") || d.Get("push_rules.0.commit_message_regex") != currentPushRules.CommitMessageRegex {
955956
options.CommitMessageRegex = gitlab.String(d.Get("push_rules.0.commit_message_regex").(string))
956957
}
957958

958-
if d.HasChange("push_rules.0.commit_message_negative_regex") {
959+
if d.HasChange("push_rules.0.commit_message_negative_regex") || d.Get("push_rules.0.commit_message_negative_regex") != currentPushRules.CommitMessageNegativeRegex {
959960
options.CommitMessageNegativeRegex = gitlab.String(d.Get("push_rules.0.commit_message_negative_regex").(string))
960961
}
961962

962-
if d.HasChange("push_rules.0.file_name_regex") {
963+
if d.HasChange("push_rules.0.file_name_regex") || d.Get("push_rules.0.file_name_regex") != currentPushRules.FileNameRegex {
963964
options.FileNameRegex = gitlab.String(d.Get("push_rules.0.file_name_regex").(string))
964965
}
965966

966-
if d.HasChange("push_rules.0.commit_committer_check") {
967+
if d.HasChange("push_rules.0.commit_committer_check") || d.Get("push_rules.0.commit_committer_check") != currentPushRules.CommitCommitterCheck {
967968
options.CommitCommitterCheck = gitlab.Bool(d.Get("push_rules.0.commit_committer_check").(bool))
968969
}
969970

970-
if d.HasChange("push_rules.0.deny_delete_tag") {
971+
if d.HasChange("push_rules.0.deny_delete_tag") || d.Get("push_rules.0.deny_delete_tag") != currentPushRules.DenyDeleteTag {
971972
options.DenyDeleteTag = gitlab.Bool(d.Get("push_rules.0.deny_delete_tag").(bool))
972973
}
973974

974-
if d.HasChange("push_rules.0.member_check") {
975+
if d.HasChange("push_rules.0.member_check") || d.Get("push_rules.0.member_check") != currentPushRules.MemberCheck {
975976
options.MemberCheck = gitlab.Bool(d.Get("push_rules.0.member_check").(bool))
976977
}
977978

978-
if d.HasChange("push_rules.0.prevent_secrets") {
979+
if d.HasChange("push_rules.0.prevent_secrets") || d.Get("push_rules.0.prevent_secrets") != currentPushRules.PreventSecrets {
979980
options.PreventSecrets = gitlab.Bool(d.Get("push_rules.0.prevent_secrets").(bool))
980981
}
981982

982-
if d.HasChange("push_rules.0.reject_unsigned_commits") {
983+
if d.HasChange("push_rules.0.reject_unsigned_commits") || d.Get("push_rules.0.reject_unsigned_commits") != currentPushRules.RejectUnsignedCommits {
983984
options.RejectUnsignedCommits = gitlab.Bool(d.Get("push_rules.0.reject_unsigned_commits").(bool))
984985
}
985986

986-
if d.HasChange("push_rules.0.max_file_size") {
987+
if d.HasChange("push_rules.0.max_file_size") || d.Get("push_rules.0.max_file_size") != currentPushRules.MaxFileSize {
987988
options.MaxFileSize = gitlab.Int(d.Get("push_rules.0.max_file_size").(int))
988989
}
989990

990991
return options
991992
}
992993

993-
func expandAddProjectPushRuleOptions(d *schema.ResourceData) *gitlab.AddProjectPushRuleOptions {
994+
func expandAddProjectPushRuleOptions(d *schema.ResourceData) (*gitlab.AddProjectPushRuleOptions, bool) {
994995
options := &gitlab.AddProjectPushRuleOptions{}
996+
needToAdd := false
995997

996998
if v, ok := d.GetOk("push_rules.0.author_email_regex"); ok {
997999
options.AuthorEmailRegex = gitlab.String(v.(string))
1000+
needToAdd = true
9981001
}
9991002

10001003
if v, ok := d.GetOk("push_rules.0.branch_name_regex"); ok {
10011004
options.BranchNameRegex = gitlab.String(v.(string))
1005+
needToAdd = true
10021006
}
10031007

10041008
if v, ok := d.GetOk("push_rules.0.commit_message_regex"); ok {
10051009
options.CommitMessageRegex = gitlab.String(v.(string))
1010+
needToAdd = true
10061011
}
10071012

10081013
if v, ok := d.GetOk("push_rules.0.commit_message_negative_regex"); ok {
10091014
options.CommitMessageNegativeRegex = gitlab.String(v.(string))
1015+
needToAdd = true
10101016
}
10111017

10121018
if v, ok := d.GetOk("push_rules.0.file_name_regex"); ok {
10131019
options.FileNameRegex = gitlab.String(v.(string))
1020+
needToAdd = true
10141021
}
10151022

10161023
if v, ok := d.GetOk("push_rules.0.commit_committer_check"); ok {
10171024
options.CommitCommitterCheck = gitlab.Bool(v.(bool))
1025+
needToAdd = true
10181026
}
10191027

10201028
if v, ok := d.GetOk("push_rules.0.deny_delete_tag"); ok {
10211029
options.DenyDeleteTag = gitlab.Bool(v.(bool))
1030+
needToAdd = true
10221031
}
10231032

10241033
if v, ok := d.GetOk("push_rules.0.member_check"); ok {
10251034
options.MemberCheck = gitlab.Bool(v.(bool))
1035+
needToAdd = true
10261036
}
10271037

10281038
if v, ok := d.GetOk("push_rules.0.prevent_secrets"); ok {
10291039
options.PreventSecrets = gitlab.Bool(v.(bool))
1040+
needToAdd = true
10301041
}
10311042

10321043
if v, ok := d.GetOk("push_rules.0.reject_unsigned_commits"); ok {
10331044
options.RejectUnsignedCommits = gitlab.Bool(v.(bool))
1045+
needToAdd = true
10341046
}
10351047

10361048
if v, ok := d.GetOk("push_rules.0.max_file_size"); ok {
10371049
options.MaxFileSize = gitlab.Int(v.(int))
1050+
needToAdd = true
10381051
}
10391052

1040-
return options
1053+
return options, needToAdd
10411054
}
10421055

10431056
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)