Repository: xanzy/go-gitlab
Pull request #2054 (2024-11-02 20:43:41)

Add expires_at field when creating project deploy keys
Fixes https://github.com/xanzy/go-gitlab/issues/2020

The code in this area was a bit confusing. There are two similar endpoints:
- https://docs.gitlab.com/ee/api/deploy_keys.html#add-deploy-key
- https://docs.gitlab.com/ee/api/deploy_keys.html#add-deploy-key-for-a-project

The code linked to the documentation for the first one and was named like it was the first one, but it was actually the second one.

I've updated the documentation link, but adding support for the first one will be difficult in future given it's name is already taken.


Patch:
diff --git a/deploy_keys.go b/deploy_keys.go
index e343bef..8834edb 100644
--- a/deploy_keys.go
+++ b/deploy_keys.go
@@ -67,6 +67,7 @@ type ProjectDeployKey struct {
 	Key       string     `json:"key"`
 	CreatedAt *time.Time `json:"created_at"`
 	CanPush   bool       `json:"can_push"`
+	ExpiresAt *time.Time `json:"expires_at"`
 }
 
 func (k ProjectDeployKey) String() string {
@@ -162,11 +163,12 @@ func (s *DeployKeysService) GetDeployKey(pid interface{}, deployKey int, options
 // AddDeployKeyOptions represents the available ADDDeployKey() options.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ee/api/deploy_keys.html#add-deploy-key
+// https://docs.gitlab.com/ee/api/deploy_keys.html#add-deploy-key-for-a-project
 type AddDeployKeyOptions struct {
-	Title   *string `url:"title,omitempty" json:"title,omitempty"`
-	Key     *string `url:"key,omitempty" json:"key,omitempty"`
-	CanPush *bool   `url:"can_push,omitempty" json:"can_push,omitempty"`
+	Key       *string    `url:"key,omitempty" json:"key,omitempty"`
+	Title     *string    `url:"title,omitempty" json:"title,omitempty"`
+	CanPush   *bool      `url:"can_push,omitempty" json:"can_push,omitempty"`
+	ExpiresAt *time.Time `url:"expires_at,omitempty" json:"expires_at,omitempty"`
 }
 
 // AddDeployKey creates a new deploy key for a project. If deploy key already
@@ -174,7 +176,7 @@ type AddDeployKeyOptions struct {
 // original one was is accessible by same user.
 //
 // GitLab API docs:
-// https://docs.gitlab.com/ee/api/deploy_keys.html#add-deploy-key
+// https://docs.gitlab.com/ee/api/deploy_keys.html#add-deploy-key-for-a-project
 func (s *DeployKeysService) AddDeployKey(pid interface{}, opt *AddDeployKeyOptions, options ...RequestOptionFunc) (*ProjectDeployKey, *Response, error) {
 	project, err := parseID(pid)
 	if err != nil {


Test patch:
diff --git a/deploy_keys_test.go b/deploy_keys_test.go
index 260ee1c..d760bc6 100644
--- a/deploy_keys_test.go
+++ b/deploy_keys_test.go
@@ -225,7 +225,8 @@ func TestAddDeployKey(t *testing.T) {
 			"id" : 12,
 			"title" : "My deploy key",
 			"can_push": true,
-			"created_at" : "2015-08-29T12:44:31.550Z"
+			"created_at" : "2015-08-29T12:44:31.550Z",
+			"expires_at": null
 		 }`)
 	})
 
@@ -256,6 +257,55 @@ func TestAddDeployKey(t *testing.T) {
 	}
 }
 
+func TestAddDeployKey_withExpiresAt(t *testing.T) {
+	mux, client := setup(t)
+
+	mux.HandleFunc("/api/v4/projects/5/deploy_keys", func(w http.ResponseWriter, r *http.Request) {
+		testMethod(t, r, http.MethodPost)
+		fmt.Fprintf(w, `{
+			"key" : "ssh-rsa AAAA...",
+			"id" : 12,
+			"title" : "My deploy key",
+			"can_push": true,
+			"created_at" : "2015-08-29T12:44:31.550Z",
+			"expires_at": "2999-03-01T00:00:00.000Z"
+		 }`)
+	})
+
+	expiresAt, err := time.Parse(timeLayout, "2999-03-01T00:00:00.000Z")
+	if err != nil {
+		t.Errorf("DeployKeys.AddDeployKey returned an error while parsing time: %v", err)
+	}
+
+	opt := &AddDeployKeyOptions{
+		Key:       Ptr("ssh-rsa AAAA..."),
+		Title:     Ptr("My deploy key"),
+		CanPush:   Ptr(true),
+		ExpiresAt: &expiresAt,
+	}
+	deployKey, _, err := client.DeployKeys.AddDeployKey(5, opt)
+	if err != nil {
+		t.Errorf("DeployKey.AddDeployKey returned error: %v", err)
+	}
+
+	createdAt, err := time.Parse(timeLayout, "2015-08-29T12:44:31.550Z")
+	if err != nil {
+		t.Errorf("DeployKeys.AddDeployKey returned an error while parsing time: %v", err)
+	}
+
+	want := &ProjectDeployKey{
+		Title:     "My deploy key",
+		ID:        12,
+		Key:       "ssh-rsa AAAA...",
+		CreatedAt: &createdAt,
+		CanPush:   true,
+		ExpiresAt: &expiresAt,
+	}
+	if !reflect.DeepEqual(want, deployKey) {
+		t.Errorf("DeployKeys.AddDeployKey returned %+v, want %+v", deployKey, want)
+	}
+}
+
 func TestDeleteDeployKey(t *testing.T) {
 	mux, client := setup(t)