diff --git a/forgejo/org_action.go b/forgejo/org_action.go index a392c45..2e8ce53 100644 --- a/forgejo/org_action.go +++ b/forgejo/org_action.go @@ -9,7 +9,10 @@ package forgejo import ( + "bytes" + "encoding/json" "fmt" + "net/http" "net/url" ) @@ -31,3 +34,58 @@ func (c *Client) ListOrgActionSecret(org string, opt ListOrgActionSecretOption) resp, err := c.getParsedResponse("GET", link.String(), jsonHeader, nil, &secrets) return secrets, resp, err } + +// CreateSecretOption represents the options for creating a secret. +type CreateSecretOption struct { + Name string `json:"name"` // Name is the name of the secret. + Data string `json:"data"` // Data is the data of the secret. +} + +// Validate checks if the CreateSecretOption is valid. +// It returns an error if any of the validation checks fail. +func (opt *CreateSecretOption) Validate() error { + if len(opt.Name) == 0 { + return fmt.Errorf("name required") + } + if len(opt.Name) > 30 { + return fmt.Errorf("name to long") + } + if len(opt.Data) == 0 { + return fmt.Errorf("data required") + } + return nil +} + +// CreateOrgActionSecret creates a secret for the specified organization in the Gitea Actions. +// It takes the organization name and the secret options as parameters. +// The function returns the HTTP response and an error, if any. +func (c *Client) CreateOrgActionSecret(org string, opt CreateSecretOption) (*Response, error) { + if err := escapeValidatePathSegments(&org); err != nil { + return nil, err + } + if err := (&opt).Validate(); err != nil { + return nil, err + } + body, err := json.Marshal(&opt) + if err != nil { + return nil, err + } + + status, resp, err := c.getStatusCode("PUT", fmt.Sprintf("/orgs/%s/actions/secrets/%s", org, opt.Name), jsonHeader, bytes.NewReader(body)) + if err != nil { + return nil, err + } + + switch status { + case http.StatusCreated: + return resp, nil + case http.StatusNoContent: + return resp, nil + case http.StatusNotFound: + return resp, fmt.Errorf("forbidden") + case http.StatusBadRequest: + return resp, fmt.Errorf("bad request") + default: + return resp, fmt.Errorf("unexpected Status: %d", status) + } +} diff --git a/forgejo/org_action_test.go b/forgejo/org_action_test.go new file mode 100644 index 0000000..c910e62 --- /dev/null +++ b/forgejo/org_action_test.go @@ -0,0 +1,43 @@ +// Copyright 2024 The Forgejo Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +// Copyright 2024 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package forgejo + +import ( + "log" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCreateOrgActionSecret(t *testing.T) { + log.Println("== TestCreateOrgActionSecret ==") + c := newTestClient() + + user := createTestUser(t, "org_action_user", c) + c.SetSudo(user.UserName) + newOrg, _, err := c.CreateOrg(CreateOrgOption{Name: "ActionOrg"}) + assert.NoError(t, err) + assert.NotNil(t, newOrg) + + // create secret + resp, err := c.CreateOrgActionSecret(newOrg.UserName, CreateSecretOption{Name: "test", Data: "test"}) + assert.NoError(t, err) + assert.Equal(t, http.StatusCreated, resp.StatusCode) + + // update secret + resp, err = c.CreateOrgActionSecret(newOrg.UserName, CreateSecretOption{Name: "test", Data: "test2"}) + assert.NoError(t, err) + assert.Equal(t, http.StatusNoContent, resp.StatusCode) + + // list secrets + secrets, _, err := c.ListOrgActionSecret(newOrg.UserName, ListOrgActionSecretOption{}) + assert.NoError(t, err) + assert.Len(t, secrets, 1) +} diff --git a/forgejo/secret.go b/forgejo/secret.go index 94054c2..22cee7f 100644 --- a/forgejo/secret.go +++ b/forgejo/secret.go @@ -1,4 +1,4 @@ -// Copyright 2024 The Forgjo Authors. All rights reserved. +// Copyright 2024 The Forgejo Authors. All rights reserved. // Use of this source code is governed by a MIT-style // license that can be found in the LICENSE file. @@ -13,6 +13,8 @@ import "time" type Secret struct { // the secret's name Name string `json:"name"` + // the secret's data + Data string `json:"data"` // Date and Time of secret creation Created time.Time `json:"created_at"` }