Commit 4ece88e6 authored by Yashesvinee V's avatar Yashesvinee V Committed by Timo Furrer
Browse files

feat: add Project Aliases API support

Changelog: Improvements
parent 5e239bc0
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -217,6 +217,7 @@ type Client struct {
	Pipelines                        PipelinesServiceInterface
	PlanLimits                       PlanLimitsServiceInterface
	ProjectAccessTokens              ProjectAccessTokensServiceInterface
	ProjectAliases                   ProjectAliasesServiceInterface
	ProjectBadges                    ProjectBadgesServiceInterface
	ProjectCluster                   ProjectClustersServiceInterface
	ProjectFeatureFlags              ProjectFeatureFlagServiceInterface
@@ -524,6 +525,7 @@ func NewAuthSourceClient(as AuthSource, options ...ClientOptionFunc) (*Client, e
	c.Pipelines = &PipelinesService{client: c}
	c.PlanLimits = &PlanLimitsService{client: c}
	c.ProjectAccessTokens = &ProjectAccessTokensService{client: c}
	c.ProjectAliases = &ProjectAliasesService{client: c}
	c.ProjectBadges = &ProjectBadgesService{client: c}
	c.ProjectCluster = &ProjectClustersService{client: c}
	c.ProjectFeatureFlags = &ProjectFeatureFlagService{client: c}
+1 −0
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ var serviceMap = map[any]any{
	&PipelinesService{}:                        (*PipelinesServiceInterface)(nil),
	&PlanLimitsService{}:                       (*PlanLimitsServiceInterface)(nil),
	&ProjectAccessTokensService{}:              (*ProjectAccessTokensServiceInterface)(nil),
	&ProjectAliasesService{}:                   (*ProjectAliasesServiceInterface)(nil),
	&ProjectBadgesService{}:                    (*ProjectBadgesServiceInterface)(nil),
	&ProjectClustersService{}:                  (*ProjectClustersServiceInterface)(nil),
	&ProjectFeatureFlagService{}:               (*ProjectFeatureFlagServiceInterface)(nil),

project_aliases.go

0 → 100644
+121 −0
Original line number Diff line number Diff line
package gitlab

import (
	"fmt"
	"net/http"
)

type (
	ProjectAliasesServiceInterface interface {
		ListProjectAliases(options ...RequestOptionFunc) ([]*ProjectAlias, *Response, error)
		GetProjectAlias(name string, options ...RequestOptionFunc) (*ProjectAlias, *Response, error)
		CreateProjectAlias(opt *CreateProjectAliasOptions, options ...RequestOptionFunc) (*ProjectAlias, *Response, error)
		DeleteProjectAlias(name string, options ...RequestOptionFunc) (*Response, error)
	}

	// ProjectAliasesService handles communication with the project aliases related methods of the GitLab API.
	//
	// GitLab API docs: https://docs.gitlab.com/api/project_aliases/
	ProjectAliasesService struct {
		client *Client
	}
)

var _ ProjectAliasesServiceInterface = (*ProjectAliasesService)(nil)

// ProjectAlias represents a GitLab project alias.
//
// GitLab API docs:
// https://docs.gitlab.com/api/project_aliases/
type ProjectAlias struct {
	ID        int    `json:"id"`
	ProjectID int    `json:"project_id"`
	Name      string `json:"name"`
}

// CreateProjectAliasOptions represents the options for creating a project alias.
//
// GitLab API docs:
// https://docs.gitlab.com/api/project_aliases/#create-a-project-alias
type CreateProjectAliasOptions struct {
	Name      *string `json:"name" url:"name,omitempty"`
	ProjectID int     `json:"project_id" url:"project_id,omitempty"`
}

// ListProjectAliases gets a list of all project aliases.
//
// GitLab API docs:
// https://docs.gitlab.com/api/project_aliases/#list-all-project-aliases
func (s *ProjectAliasesService) ListProjectAliases(options ...RequestOptionFunc) ([]*ProjectAlias, *Response, error) {
	u := "project_aliases"

	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	var aliases []*ProjectAlias
	resp, err := s.client.Do(req, &aliases)
	if err != nil {
		return nil, resp, err
	}

	return aliases, resp, nil
}

// GetProjectAlias gets details of a project alias.
//
// GitLab API docs:
// https://docs.gitlab.com/api/project_aliases/#get-project-alias-details
func (s *ProjectAliasesService) GetProjectAlias(name string, options ...RequestOptionFunc) (*ProjectAlias, *Response, error) {
	u := fmt.Sprintf("project_aliases/%s", PathEscape(name))

	req, err := s.client.NewRequest(http.MethodGet, u, nil, options)
	if err != nil {
		return nil, nil, err
	}

	aliasObj := new(ProjectAlias)
	resp, err := s.client.Do(req, aliasObj)
	if err != nil {
		return nil, resp, err
	}

	return aliasObj, resp, nil
}

// CreateProjectAlias creates a new project alias.
//
// GitLab API docs:
// https://docs.gitlab.com/api/project_aliases/#create-a-project-alias
func (s *ProjectAliasesService) CreateProjectAlias(opt *CreateProjectAliasOptions, options ...RequestOptionFunc) (*ProjectAlias, *Response, error) {
	u := "project_aliases"

	req, err := s.client.NewRequest(http.MethodPost, u, opt, options)
	if err != nil {
		return nil, nil, err
	}

	alias := new(ProjectAlias)
	resp, err := s.client.Do(req, alias)
	if err != nil {
		return nil, resp, err
	}

	return alias, resp, nil
}

// DeleteProjectAlias deletes a project alias.
//
// GitLab API docs:
// https://docs.gitlab.com/api/project_aliases/#delete-a-project-alias
func (s *ProjectAliasesService) DeleteProjectAlias(name string, options ...RequestOptionFunc) (*Response, error) {
	u := fmt.Sprintf("project_aliases/%s", PathEscape(name))

	req, err := s.client.NewRequest(http.MethodDelete, u, nil, options)
	if err != nil {
		return nil, err
	}

	return s.client.Do(req, nil)
}
+172 −0
Original line number Diff line number Diff line
package gitlab

import (
	"encoding/json"
	"io"
	"net/http"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestProjectAliasesService_CreateProjectAlias(t *testing.T) {
	mux, client := setup(t)

	mux.HandleFunc("/api/v4/project_aliases", func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "POST", r.Method)

		body, err := io.ReadAll(r.Body)
		require.NoError(t, err)

		var payload CreateProjectAliasOptions
		err = json.Unmarshal(body, &payload)
		require.NoError(t, err)

		require.NotNil(t, payload.Name)
		assert.Equal(t, "my-alias", *payload.Name)
		assert.Equal(t, 1, payload.ProjectID)

		w.WriteHeader(http.StatusCreated)
		w.Write([]byte(`{"id": 10, "name": "my-alias", "project_id": 1}`))
	})

	s := client.ProjectAliases
	opt := &CreateProjectAliasOptions{
		Name:      Ptr("my-alias"),
		ProjectID: 1,
	}
	alias, resp, err := s.CreateProjectAlias(opt)
	require.NoError(t, err)
	assert.Equal(t, 10, alias.ID)
	assert.Equal(t, "my-alias", alias.Name)
	assert.Equal(t, 1, alias.ProjectID)
	assert.Equal(t, 201, resp.StatusCode)
}

func TestProjectAliasesService_DeleteProjectAlias(t *testing.T) {
	mux, client := setup(t)

	mux.HandleFunc("/api/v4/project_aliases/my-alias", func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "DELETE", r.Method)
		w.WriteHeader(http.StatusNoContent)
	})

	s := client.ProjectAliases
	resp, err := s.DeleteProjectAlias("my-alias")
	require.NoError(t, err)
	assert.Equal(t, 204, resp.StatusCode)
}

func TestProjectAliasesService_GetProjectAlias(t *testing.T) {
	mux, client := setup(t)

	mux.HandleFunc("/api/v4/project_aliases/my-alias", func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "GET", r.Method)
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(`{"id": 10, "name": "my-alias", "project_id": 1}`))
	})

	s := client.ProjectAliases
	alias, resp, err := s.GetProjectAlias("my-alias")
	require.NoError(t, err)
	assert.Equal(t, 10, alias.ID)
	assert.Equal(t, "my-alias", alias.Name)
	assert.Equal(t, 1, alias.ProjectID)
	assert.Equal(t, 200, resp.StatusCode)
}

func TestProjectAliasesService_ListProjectAliases(t *testing.T) {
	mux, client := setup(t)

	mux.HandleFunc("/api/v4/project_aliases", func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "GET", r.Method)
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(`[{"id": 10, "name": "my-alias", "project_id": 1}]`))
	})

	s := client.ProjectAliases
	aliases, resp, err := s.ListProjectAliases()
	require.NoError(t, err)
	require.Len(t, aliases, 1)
	assert.Equal(t, 10, aliases[0].ID)
	assert.Equal(t, "my-alias", aliases[0].Name)
	assert.Equal(t, 1, aliases[0].ProjectID)
	assert.Equal(t, 200, resp.StatusCode)
}

func TestProjectAliasesService_GetProjectAlias_WithSpecialCharacters(t *testing.T) {
	mux, client := setup(t)

	aliasName := "my/alias?with=special&chars"
	expectedEscaped := "my%2Falias%3Fwith%3Dspecial%26chars"

	mux.HandleFunc("/api/v4/project_aliases/"+expectedEscaped, func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "GET", r.Method)
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(`{"id": 10, "name": "my/alias?with=special&chars", "project_id": 1}`))
	})

	s := client.ProjectAliases
	alias, resp, err := s.GetProjectAlias(aliasName)
	require.NoError(t, err)
	assert.Equal(t, 10, alias.ID)
	assert.Equal(t, "my/alias?with=special&chars", alias.Name)
	assert.Equal(t, 1, alias.ProjectID)
	assert.Equal(t, 200, resp.StatusCode)
}

func TestProjectAliasesService_DeleteProjectAlias_WithSpecialCharacters(t *testing.T) {
	mux, client := setup(t)

	aliasName := "my/alias?with=special&chars"
	expectedEscaped := "my%2Falias%3Fwith%3Dspecial%26chars"

	mux.HandleFunc("/api/v4/project_aliases/"+expectedEscaped, func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "DELETE", r.Method)
		w.WriteHeader(http.StatusNoContent)
	})

	s := client.ProjectAliases
	resp, err := s.DeleteProjectAlias(aliasName)
	require.NoError(t, err)
	assert.Equal(t, 204, resp.StatusCode)
}

func TestProjectAliasesService_GetProjectAlias_WithSpacesAndDots(t *testing.T) {
	mux, client := setup(t)

	aliasName := "my alias.name"
	expectedEscaped := "my%20alias%2Ename"

	mux.HandleFunc("/api/v4/project_aliases/"+expectedEscaped, func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "GET", r.Method)
		w.WriteHeader(http.StatusOK)
		w.Write([]byte(`{"id": 20, "name": "my alias.name", "project_id": 2}`))
	})

	s := client.ProjectAliases
	alias, resp, err := s.GetProjectAlias(aliasName)
	require.NoError(t, err)
	assert.Equal(t, 20, alias.ID)
	assert.Equal(t, "my alias.name", alias.Name)
	assert.Equal(t, 2, alias.ProjectID)
	assert.Equal(t, 200, resp.StatusCode)
}

func TestProjectAliasesService_DeleteProjectAlias_WithSpacesAndDots(t *testing.T) {
	mux, client := setup(t)

	aliasName := "my alias.name"
	expectedEscaped := "my%20alias%2Ename"

	mux.HandleFunc("/api/v4/project_aliases/"+expectedEscaped, func(w http.ResponseWriter, r *http.Request) {
		require.Equal(t, "DELETE", r.Method)
		w.WriteHeader(http.StatusNoContent)
	})

	s := client.ProjectAliases
	resp, err := s.DeleteProjectAlias(aliasName)
	require.NoError(t, err)
	assert.Equal(t, 204, resp.StatusCode)
}
+1 −0
Original line number Diff line number Diff line
@@ -101,6 +101,7 @@ package testing
//go:generate go run go.uber.org/mock/mockgen@v0.6.0 -typed -destination=pipelines_mock.go -package=testing gitlab.com/gitlab-org/api/client-go PipelinesServiceInterface
//go:generate go run go.uber.org/mock/mockgen@v0.6.0 -typed -destination=plan_limits_mock.go -package=testing gitlab.com/gitlab-org/api/client-go PlanLimitsServiceInterface
//go:generate go run go.uber.org/mock/mockgen@v0.6.0 -typed -destination=project_access_tokens_mock.go -package=testing gitlab.com/gitlab-org/api/client-go ProjectAccessTokensServiceInterface
//go:generate go run go.uber.org/mock/mockgen@v0.6.0 -typed -destination=project_aliases_mock.go -package=testing gitlab.com/gitlab-org/api/client-go ProjectAliasesServiceInterface
//go:generate go run go.uber.org/mock/mockgen@v0.6.0 -typed -destination=project_badges_mock.go -package=testing gitlab.com/gitlab-org/api/client-go ProjectBadgesServiceInterface
//go:generate go run go.uber.org/mock/mockgen@v0.6.0 -typed -destination=project_clusters_mock.go -package=testing gitlab.com/gitlab-org/api/client-go ProjectClustersServiceInterface
//go:generate go run go.uber.org/mock/mockgen@v0.6.0 -typed -destination=project_feature_flags_mock.go -package=testing gitlab.com/gitlab-org/api/client-go ProjectFeatureFlagServiceInterface
Loading