Repository: xanzy/go-gitlab
Pull request #1727 (2023-05-31 15:29:36)

Add approval_rules in protected_environments
Coming from here: https://gitlab.com/gitlab-org/terraform-provider-gitlab/-/issues/1417


Patch:
diff --git a/protected_environments.go b/protected_environments.go
index 5e5962b..21820ab 100644
--- a/protected_environments.go
+++ b/protected_environments.go
@@ -38,6 +38,7 @@ type ProtectedEnvironment struct {
 	Name                  string                          `json:"name"`
 	DeployAccessLevels    []*EnvironmentAccessDescription `json:"deploy_access_levels"`
 	RequiredApprovalCount int                             `json:"required_approval_count"`
+	ApprovalRules         []*EnvironmentApprovalRule      `json:"approval_rules"`
 }
 
 // EnvironmentAccessDescription represents the access decription for a protected
@@ -46,12 +47,28 @@ type ProtectedEnvironment struct {
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/protected_environments.html
 type EnvironmentAccessDescription struct {
+	ID                     int              `json:"id"`
 	AccessLevel            AccessLevelValue `json:"access_level"`
 	AccessLevelDescription string           `json:"access_level_description"`
 	UserID                 int              `json:"user_id"`
 	GroupID                int              `json:"group_id"`
 }
 
+// EnvironmentApprovalRule represents the approval rules for a protected
+// environment.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ee/api/protected_environments.html#protect-a-single-environment
+type EnvironmentApprovalRule struct {
+	ID                     int              `json:"id"`
+	UserID                 int              `json:"user_id"`
+	GroupID                int              `json:"group_id"`
+	AccessLevel            AccessLevelValue `json:"access_level"`
+	AccessLevelDescription string           `json:"access_level_description"`
+	RequiredApprovalCount  int              `json:"required_approvals"`
+	GroupInheritanceType   int              `json:"group_inheritance_type"`
+}
+
 // ListProtectedEnvironmentsOptions represents the available
 // ListProtectedEnvironments() options.
 //
@@ -117,9 +134,10 @@ func (s *ProtectedEnvironmentsService) GetProtectedEnvironment(pid interface{},
 // GitLab API docs:
 // https://docs.gitlab.com/ee/api/protected_environments.html#protect-a-single-environment
 type ProtectRepositoryEnvironmentsOptions struct {
-	Name                  *string                      `url:"name,omitempty" json:"name,omitempty"`
-	DeployAccessLevels    *[]*EnvironmentAccessOptions `url:"deploy_access_levels,omitempty" json:"deploy_access_levels,omitempty"`
-	RequiredApprovalCount *int                         `url:"required_approval_count,omitempty" json:"required_approval_count,omitempty"`
+	Name                  *string                            `url:"name,omitempty" json:"name,omitempty"`
+	DeployAccessLevels    *[]*EnvironmentAccessOptions       `url:"deploy_access_levels,omitempty" json:"deploy_access_levels,omitempty"`
+	RequiredApprovalCount *int                               `url:"required_approval_count,omitempty" json:"required_approval_count,omitempty"`
+	ApprovalRules         *[]*EnvironmentApprovalRuleOptions `url:"approval_rules,omitempty" json:"approval_rules,omitempty"`
 }
 
 // EnvironmentAccessOptions represents the options for an access decription for
@@ -133,6 +151,20 @@ type EnvironmentAccessOptions struct {
 	GroupID     *int              `url:"group_id,omitempty" json:"group_id,omitempty"`
 }
 
+// EnvironmentApprovalRuleOptions represents the approval rules for a protected
+// environment.
+//
+// GitLab API docs:
+// https://docs.gitlab.com/ee/api/protected_environments.html#protect-a-single-environment
+type EnvironmentApprovalRuleOptions struct {
+	UserID                 *int              `url:"user_id,omitempty" json:"user_id,omitempty"`
+	GroupID                *int              `url:"group_id,omitempty" json:"group_id,omitempty"`
+	AccessLevel            *AccessLevelValue `url:"access_level,omitempty" json:"access_level,omitempty"`
+	AccessLevelDescription *string           `url:"access_level_description,omitempty" json:"access_level_description,omitempty"`
+	RequiredApprovalCount  *int              `url:"required_approvals,omitempty" json:"required_approvals,omitempty"`
+	GroupInheritanceType   *int              `url:"group_inheritance_type,omitempty" json:"group_inheritance_type,omitempty"`
+}
+
 // ProtectRepositoryEnvironments protects a single repository environment or
 // several project repository environments using wildcard protected environment.
 //


Test patch:
diff --git a/protected_environments_test.go b/protected_environments_test.go
index dac5e24..4dd8a80 100644
--- a/protected_environments_test.go
+++ b/protected_environments_test.go
@@ -37,7 +37,27 @@ func TestListProtectedEnvironments(t *testing.T) {
           "access_level_description": "Maintainers"
         }
       ],
-      "required_approval_count": 1
+      "required_approval_count": 1,
+      "approval_rules": [
+        {
+           "id": 38,
+           "user_id": 42,
+           "group_id": null,
+           "access_level": null,
+           "access_level_description": "qa-group",
+           "required_approvals": 1,
+           "group_inheritance_type": 0
+        },
+        {
+           "id": 39,
+           "user_id": null,
+           "group_id": 135,
+           "access_level": 30,
+           "access_level_description": "security-group",
+           "required_approvals": 2,
+           "group_inheritance_type": 1
+        }
+      ]
     },{
       "name":"*-release",
       "deploy_access_levels": [
@@ -59,6 +79,22 @@ func TestListProtectedEnvironments(t *testing.T) {
 				},
 			},
 			RequiredApprovalCount: 1,
+			ApprovalRules: []*EnvironmentApprovalRule{
+				{
+					ID:                     38,
+					UserID:                 42,
+					AccessLevelDescription: "qa-group",
+					RequiredApprovalCount:  1,
+				},
+				{
+					ID:                     39,
+					GroupID:                135,
+					AccessLevel:            30,
+					AccessLevelDescription: "security-group",
+					RequiredApprovalCount:  2,
+					GroupInheritanceType:   1,
+				},
+			},
 		},
 		{
 			Name: "*-release",
@@ -93,7 +129,18 @@ func TestGetProtectedEnvironment(t *testing.T) {
           "access_level_description": "Developers + Maintainers"
         }
       ],
-      "required_approval_count": 1
+      "required_approval_count": 1,
+      "approval_rules": [
+        {
+           "id": 1,
+           "user_id": null,
+           "group_id": 10,
+           "access_level": 5,
+           "access_level_description": "devops",
+           "required_approvals": 0,
+           "group_inheritance_type": 0
+        }
+      ]
     }`)
 	})
 
@@ -106,13 +153,21 @@ func TestGetProtectedEnvironment(t *testing.T) {
 			},
 		},
 		RequiredApprovalCount: 1,
+		ApprovalRules: []*EnvironmentApprovalRule{
+			{
+				ID:                     1,
+				GroupID:                10,
+				AccessLevel:            5,
+				AccessLevelDescription: "devops",
+			},
+		},
 	}
 
 	environment, _, err := client.ProtectedEnvironments.GetProtectedEnvironment(1, environmentName)
 	assert.NoError(t, err, "failed to get response")
 	assert.Equal(t, expected, environment)
 
-	// Test without RequiredApprovalCount
+	// Test without RequiredApprovalCount nor ApprovalRules
 	environmentName = "my-awesome-environment2"
 
 	mux.HandleFunc(fmt.Sprintf("/api/v4/projects/2/protected_environments/%s", environmentName), func(w http.ResponseWriter, r *http.Request) {
@@ -146,7 +201,7 @@ func TestGetProtectedEnvironment(t *testing.T) {
 func TestProtectRepositoryEnvironments(t *testing.T) {
 	mux, client := setup(t)
 
-	// Test with RequiredApprovalCount
+	// Test with RequiredApprovalCount and ApprovalRules
 	mux.HandleFunc("/api/v4/projects/1/protected_environments", func(w http.ResponseWriter, r *http.Request) {
 		testMethod(t, r, http.MethodPost)
 		fmt.Fprint(w, `{
@@ -157,7 +212,18 @@ func TestProtectRepositoryEnvironments(t *testing.T) {
           "access_level_description": "Developers + Maintainers"
         }
       ],
-      "required_approval_count": 2
+      "required_approval_count": 2,
+      "approval_rules": [
+        {
+           "id": 1,
+           "user_id": null,
+           "group_id": 10,
+           "access_level": 5,
+           "access_level_description": "devops",
+           "required_approvals": 0,
+           "group_inheritance_type": 0
+        }
+      ]
     }`)
 	})
 
@@ -170,6 +236,14 @@ func TestProtectRepositoryEnvironments(t *testing.T) {
 			},
 		},
 		RequiredApprovalCount: 2,
+		ApprovalRules: []*EnvironmentApprovalRule{
+			{
+				ID:                     1,
+				GroupID:                10,
+				AccessLevel:            5,
+				AccessLevelDescription: "devops",
+			},
+		},
 	}
 
 	opt := &ProtectRepositoryEnvironmentsOptions{
@@ -178,13 +252,20 @@ func TestProtectRepositoryEnvironments(t *testing.T) {
 			{AccessLevel: AccessLevel(30)},
 		},
 		RequiredApprovalCount: Int(2),
+		ApprovalRules: &[]*EnvironmentApprovalRuleOptions{
+			{
+				GroupID:                Int(10),
+				AccessLevel:            AccessLevel(0),
+				AccessLevelDescription: String("devops"),
+			},
+		},
 	}
 
 	environment, _, err := client.ProtectedEnvironments.ProtectRepositoryEnvironments(1, opt)
 	assert.NoError(t, err, "failed to get response")
 	assert.Equal(t, expected, environment)
 
-	// Test without RequiredApprovalCount
+	// Test without RequiredApprovalCount nor ApprovalRules
 	mux.HandleFunc("/api/v4/projects/2/protected_environments", func(w http.ResponseWriter, r *http.Request) {
 		testMethod(t, r, http.MethodPost)
 		fmt.Fprint(w, `{