Repository: xanzy/go-gitlab
Pull request #2065 (2024-11-21 17:23:53)

Add support for hidden field to project variables
GitLab has inconsistent naming of the filed for hidden variables.
It seems for keeping UI consistant, GitLab chose to introduce different
naming for the same field. This could have been easy handled in UI by
setting two variables on API request instead of introducing combined
field for UI.

I have added 2 test cases for create and update project API as per the
gitlab.com API that I manually tested and added similar unit tests.


Patch:
diff --git a/project_variables.go b/project_variables.go
index e75c746..9dea091 100644
--- a/project_variables.go
+++ b/project_variables.go
@@ -41,6 +41,7 @@ type ProjectVariable struct {
 	VariableType     VariableTypeValue `json:"variable_type"`
 	Protected        bool              `json:"protected"`
 	Masked           bool              `json:"masked"`
+	Hidden           bool              `json:"hidden"`
 	Raw              bool              `json:"raw"`
 	EnvironmentScope string            `json:"environment_scope"`
 	Description      string            `json:"description"`
@@ -132,6 +133,7 @@ type CreateProjectVariableOptions struct {
 	Description      *string            `url:"description,omitempty" json:"description,omitempty"`
 	EnvironmentScope *string            `url:"environment_scope,omitempty" json:"environment_scope,omitempty"`
 	Masked           *bool              `url:"masked,omitempty" json:"masked,omitempty"`
+	MaskedAndHidden  *bool              `url:"masked_and_hidden,omitempty" json:"masked_and_hidden,omitempty"`
 	Protected        *bool              `url:"protected,omitempty" json:"protected,omitempty"`
 	Raw              *bool              `url:"raw,omitempty" json:"raw,omitempty"`
 	VariableType     *VariableTypeValue `url:"variable_type,omitempty" json:"variable_type,omitempty"`


Test patch:
diff --git a/project_variables_test.go b/project_variables_test.go
index 7f2cd8e..4555525 100644
--- a/project_variables_test.go
+++ b/project_variables_test.go
@@ -31,6 +31,7 @@ func TestProjectVariablesService_ListVariables(t *testing.T) {
 		VariableType:     "env_var",
 		Protected:        false,
 		Masked:           false,
+		Hidden:           false,
 		EnvironmentScope: "",
 		Description:      "test variable 1",
 	}}
@@ -69,6 +70,7 @@ func TestProjectVariablesService_GetVariable(t *testing.T) {
 				"value": "TEST_1",
 				"protected": false,
 				"masked": true,
+				"hidden": true,
 				"description": "test variable 1"
 			}
 		`)
@@ -80,6 +82,7 @@ func TestProjectVariablesService_GetVariable(t *testing.T) {
 		VariableType:     "env_var",
 		Protected:        false,
 		Masked:           true,
+		Hidden:           true,
 		EnvironmentScope: "",
 		Description:      "test variable 1",
 	}
@@ -118,6 +121,7 @@ func TestProjectVariablesService_CreateVariable(t *testing.T) {
 				"protected": false,
 				"variable_type": "env_var",
 				"masked": false,
+				"masked_and_hidden": false,
 				"environment_scope": "*",
 				"description": "new variable"
 			}
@@ -130,6 +134,57 @@ func TestProjectVariablesService_CreateVariable(t *testing.T) {
 		VariableType:     "env_var",
 		Protected:        false,
 		Masked:           false,
+		Hidden:           false,
+		EnvironmentScope: "*",
+		Description:      "new variable",
+	}
+
+	pv, resp, err := client.ProjectVariables.CreateVariable(1, &CreateProjectVariableOptions{Description: Ptr("new variable")}, nil)
+	require.NoError(t, err)
+	require.NotNil(t, resp)
+	require.Equal(t, want, pv)
+
+	pv, resp, err = client.ProjectVariables.CreateVariable(1.01, nil, nil)
+	require.EqualError(t, err, "invalid ID type 1.01, the ID must be an int or a string")
+	require.Nil(t, resp)
+	require.Nil(t, pv)
+
+	pv, resp, err = client.ProjectVariables.CreateVariable(1, nil, nil, errorOption)
+	require.EqualError(t, err, "RequestOptionFunc returns an error")
+	require.Nil(t, resp)
+	require.Nil(t, pv)
+
+	pv, resp, err = client.ProjectVariables.CreateVariable(2, nil, nil)
+	require.Error(t, err)
+	require.Nil(t, pv)
+	require.Equal(t, http.StatusNotFound, resp.StatusCode)
+}
+
+func TestProjectVariablesService_CreateVariable_MaskedAndHidden(t *testing.T) {
+	mux, client := setup(t)
+
+	mux.HandleFunc("/api/v4/projects/1/variables", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, http.MethodPost)
+		testBody(t, r, `{"description":"new variable"}`)
+		fmt.Fprintf(w, `
+			{
+				"key": "NEW_VARIABLE",
+				"protected": false,
+				"variable_type": "env_var",
+				"masked": true,
+				"hidden": true,
+				"environment_scope": "*",
+				"description": "new variable"
+			}
+		`)
+	})
+
+	want := &ProjectVariable{
+		Key:              "NEW_VARIABLE",
+		VariableType:     "env_var",
+		Protected:        false,
+		Masked:           true,
+		Hidden:           true,
 		EnvironmentScope: "*",
 		Description:      "new variable",
 	}
@@ -180,6 +235,61 @@ func TestProjectVariablesService_UpdateVariable(t *testing.T) {
 		VariableType:     "env_var",
 		Protected:        false,
 		Masked:           false,
+		Hidden:           false,
+		EnvironmentScope: "*",
+		Description:      "updated description",
+	}
+
+	pv, resp, err := client.ProjectVariables.UpdateVariable(1, "NEW_VARIABLE", &UpdateProjectVariableOptions{
+		Filter:      &VariableFilter{EnvironmentScope: "prod"},
+		Description: Ptr("updated description"),
+	}, nil)
+	require.NoError(t, err)
+	require.NotNil(t, resp)
+	require.Equal(t, want, pv)
+
+	pv, resp, err = client.ProjectVariables.UpdateVariable(1.01, "NEW_VARIABLE", nil, nil)
+	require.EqualError(t, err, "invalid ID type 1.01, the ID must be an int or a string")
+	require.Nil(t, resp)
+	require.Nil(t, pv)
+
+	pv, resp, err = client.ProjectVariables.UpdateVariable(1, "NEW_VARIABLE", nil, nil, errorOption)
+	require.EqualError(t, err, "RequestOptionFunc returns an error")
+	require.Nil(t, resp)
+	require.Nil(t, pv)
+
+	pv, resp, err = client.ProjectVariables.UpdateVariable(2, "NEW_VARIABLE", nil, nil)
+	require.Error(t, err)
+	require.Nil(t, pv)
+	require.Equal(t, http.StatusNotFound, resp.StatusCode)
+}
+
+func TestProjectVariablesService_UpdateVariable_MaskedAndHidden(t *testing.T) {
+	mux, client := setup(t)
+
+	mux.HandleFunc("/api/v4/projects/1/variables/NEW_VARIABLE", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, http.MethodPut)
+		testBody(t, r, `{"description":"updated description","filter":{"environment_scope":"prod"}}`)
+		fmt.Fprintf(w, `
+			{
+				"key": "NEW_VARIABLE",
+				"value": null,
+				"protected": false,
+				"variable_type": "env_var",
+				"masked": true,
+				"hidden": true,
+				"environment_scope": "*",
+				"description": "updated description"
+			}
+		`)
+	})
+
+	want := &ProjectVariable{
+		Key:              "NEW_VARIABLE",
+		VariableType:     "env_var",
+		Protected:        false,
+		Masked:           true,
+		Hidden:           true,
 		EnvironmentScope: "*",
 		Description:      "updated description",
 	}