mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 21:16:26 +01:00 
			
		
		
		
	feat(api): enhance Actions Secrets Management API for repository (#30656)
- Add endpoint to list repository action secrets in API routes
- Implement `ListActionsSecrets` function to retrieve action secrets
from the database
- Update Swagger documentation to include the new
`/repos/{owner}/{repo}/actions/secrets` endpoint
- Add `actions` package import and define new routes for actions,
secrets, variables, and runners in `api.go`.
- Refactor action-related API functions into `Action` struct methods in
`org/action.go` and `repo/action.go`.
- Remove `actionAPI` struct and related functions, replacing them with
`NewAction()` calls.
- Rename `variables.go` to `action.go` in `org` directory.
- Delete `runners.go` and `secrets.go` in both `org` and `repo`
directories, consolidating their content into `action.go`.
- Update copyright year and add new imports in `org/action.go`.
- Implement `API` interface in `services/actions/interface.go` for
action-related methods.
- Remove individual action-related functions and replace them with
methods on the `Action` struct in `repo/action.go`.
---------
Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com>
Signed-off-by: appleboy <appleboy.tw@gmail.com>
			
			
This commit is contained in:
		
							parent
							
								
									993736d838
								
							
						
					
					
						commit
						852547d0dc
					
				@ -93,6 +93,7 @@ import (
 | 
			
		||||
	"code.gitea.io/gitea/routers/api/v1/settings"
 | 
			
		||||
	"code.gitea.io/gitea/routers/api/v1/user"
 | 
			
		||||
	"code.gitea.io/gitea/routers/common"
 | 
			
		||||
	"code.gitea.io/gitea/services/actions"
 | 
			
		||||
	"code.gitea.io/gitea/services/auth"
 | 
			
		||||
	"code.gitea.io/gitea/services/context"
 | 
			
		||||
	"code.gitea.io/gitea/services/forms"
 | 
			
		||||
@ -835,6 +836,34 @@ func Routes() *web.Route {
 | 
			
		||||
		SignInRequired: setting.Service.RequireSignInView,
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
	addActionsRoutes := func(
 | 
			
		||||
		m *web.Route,
 | 
			
		||||
		reqChecker func(ctx *context.APIContext),
 | 
			
		||||
		act actions.API,
 | 
			
		||||
	) {
 | 
			
		||||
		m.Group("/actions", func() {
 | 
			
		||||
			m.Group("/secrets", func() {
 | 
			
		||||
				m.Get("", reqToken(), reqChecker, act.ListActionsSecrets)
 | 
			
		||||
				m.Combo("/{secretname}").
 | 
			
		||||
					Put(reqToken(), reqChecker, bind(api.CreateOrUpdateSecretOption{}), act.CreateOrUpdateSecret).
 | 
			
		||||
					Delete(reqToken(), reqChecker, act.DeleteSecret)
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			m.Group("/variables", func() {
 | 
			
		||||
				m.Get("", reqToken(), reqChecker, act.ListVariables)
 | 
			
		||||
				m.Combo("/{variablename}").
 | 
			
		||||
					Get(reqToken(), reqChecker, act.GetVariable).
 | 
			
		||||
					Delete(reqToken(), reqChecker, act.DeleteVariable).
 | 
			
		||||
					Post(reqToken(), reqChecker, bind(api.CreateVariableOption{}), act.CreateVariable).
 | 
			
		||||
					Put(reqToken(), reqChecker, bind(api.UpdateVariableOption{}), act.UpdateVariable)
 | 
			
		||||
			})
 | 
			
		||||
 | 
			
		||||
			m.Group("/runners", func() {
 | 
			
		||||
				m.Get("/registration-token", reqToken(), reqChecker, act.GetRegistrationToken)
 | 
			
		||||
			})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m.Group("", func() {
 | 
			
		||||
		// Miscellaneous (no scope required)
 | 
			
		||||
		if setting.API.EnableSwagger {
 | 
			
		||||
@ -1073,26 +1102,11 @@ func Routes() *web.Route {
 | 
			
		||||
					m.Post("/accept", repo.AcceptTransfer)
 | 
			
		||||
					m.Post("/reject", repo.RejectTransfer)
 | 
			
		||||
				}, reqToken())
 | 
			
		||||
				m.Group("/actions", func() {
 | 
			
		||||
					m.Group("/secrets", func() {
 | 
			
		||||
						m.Combo("/{secretname}").
 | 
			
		||||
							Put(reqToken(), reqOwner(), bind(api.CreateOrUpdateSecretOption{}), repo.CreateOrUpdateSecret).
 | 
			
		||||
							Delete(reqToken(), reqOwner(), repo.DeleteSecret)
 | 
			
		||||
					})
 | 
			
		||||
 | 
			
		||||
					m.Group("/variables", func() {
 | 
			
		||||
						m.Get("", reqToken(), reqOwner(), repo.ListVariables)
 | 
			
		||||
						m.Combo("/{variablename}").
 | 
			
		||||
							Get(reqToken(), reqOwner(), repo.GetVariable).
 | 
			
		||||
							Delete(reqToken(), reqOwner(), repo.DeleteVariable).
 | 
			
		||||
							Post(reqToken(), reqOwner(), bind(api.CreateVariableOption{}), repo.CreateVariable).
 | 
			
		||||
							Put(reqToken(), reqOwner(), bind(api.UpdateVariableOption{}), repo.UpdateVariable)
 | 
			
		||||
					})
 | 
			
		||||
 | 
			
		||||
					m.Group("/runners", func() {
 | 
			
		||||
						m.Get("/registration-token", reqToken(), reqOwner(), repo.GetRegistrationToken)
 | 
			
		||||
					})
 | 
			
		||||
				})
 | 
			
		||||
				addActionsRoutes(
 | 
			
		||||
					m,
 | 
			
		||||
					reqOwner(),
 | 
			
		||||
					repo.NewAction(),
 | 
			
		||||
				)
 | 
			
		||||
				m.Group("/hooks/git", func() {
 | 
			
		||||
					m.Combo("").Get(repo.ListGitHooks)
 | 
			
		||||
					m.Group("/{id}", func() {
 | 
			
		||||
@ -1460,27 +1474,11 @@ func Routes() *web.Route {
 | 
			
		||||
				m.Combo("/{username}").Get(reqToken(), org.IsMember).
 | 
			
		||||
					Delete(reqToken(), reqOrgOwnership(), org.DeleteMember)
 | 
			
		||||
			})
 | 
			
		||||
			m.Group("/actions", func() {
 | 
			
		||||
				m.Group("/secrets", func() {
 | 
			
		||||
					m.Get("", reqToken(), reqOrgOwnership(), org.ListActionsSecrets)
 | 
			
		||||
					m.Combo("/{secretname}").
 | 
			
		||||
						Put(reqToken(), reqOrgOwnership(), bind(api.CreateOrUpdateSecretOption{}), org.CreateOrUpdateSecret).
 | 
			
		||||
						Delete(reqToken(), reqOrgOwnership(), org.DeleteSecret)
 | 
			
		||||
				})
 | 
			
		||||
 | 
			
		||||
				m.Group("/variables", func() {
 | 
			
		||||
					m.Get("", reqToken(), reqOrgOwnership(), org.ListVariables)
 | 
			
		||||
					m.Combo("/{variablename}").
 | 
			
		||||
						Get(reqToken(), reqOrgOwnership(), org.GetVariable).
 | 
			
		||||
						Delete(reqToken(), reqOrgOwnership(), org.DeleteVariable).
 | 
			
		||||
						Post(reqToken(), reqOrgOwnership(), bind(api.CreateVariableOption{}), org.CreateVariable).
 | 
			
		||||
						Put(reqToken(), reqOrgOwnership(), bind(api.UpdateVariableOption{}), org.UpdateVariable)
 | 
			
		||||
				})
 | 
			
		||||
 | 
			
		||||
				m.Group("/runners", func() {
 | 
			
		||||
					m.Get("/registration-token", reqToken(), reqOrgOwnership(), org.GetRegistrationToken)
 | 
			
		||||
				})
 | 
			
		||||
			})
 | 
			
		||||
			addActionsRoutes(
 | 
			
		||||
				m,
 | 
			
		||||
				reqOrgOwnership(),
 | 
			
		||||
				org.NewAction(),
 | 
			
		||||
			)
 | 
			
		||||
			m.Group("/public_members", func() {
 | 
			
		||||
				m.Get("", org.ListPublicMembers)
 | 
			
		||||
				m.Combo("/{username}").Get(org.IsPublicMember).
 | 
			
		||||
 | 
			
		||||
@ -9,16 +9,188 @@ import (
 | 
			
		||||
 | 
			
		||||
	actions_model "code.gitea.io/gitea/models/actions"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	secret_model "code.gitea.io/gitea/models/secret"
 | 
			
		||||
	api "code.gitea.io/gitea/modules/structs"
 | 
			
		||||
	"code.gitea.io/gitea/modules/util"
 | 
			
		||||
	"code.gitea.io/gitea/modules/web"
 | 
			
		||||
	"code.gitea.io/gitea/routers/api/v1/shared"
 | 
			
		||||
	"code.gitea.io/gitea/routers/api/v1/utils"
 | 
			
		||||
	actions_service "code.gitea.io/gitea/services/actions"
 | 
			
		||||
	"code.gitea.io/gitea/services/context"
 | 
			
		||||
	secret_service "code.gitea.io/gitea/services/secrets"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListActionsSecrets list an organization's actions secrets
 | 
			
		||||
func (Action) ListActionsSecrets(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation GET /orgs/{org}/actions/secrets organization orgListActionsSecrets
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: List an organization's actions secrets
 | 
			
		||||
	// produces:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// parameters:
 | 
			
		||||
	// - name: org
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of the organization
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: page
 | 
			
		||||
	//   in: query
 | 
			
		||||
	//   description: page number of results to return (1-based)
 | 
			
		||||
	//   type: integer
 | 
			
		||||
	// - name: limit
 | 
			
		||||
	//   in: query
 | 
			
		||||
	//   description: page size of results
 | 
			
		||||
	//   type: integer
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "200":
 | 
			
		||||
	//     "$ref": "#/responses/SecretList"
 | 
			
		||||
	//   "404":
 | 
			
		||||
	//     "$ref": "#/responses/notFound"
 | 
			
		||||
 | 
			
		||||
	opts := &secret_model.FindSecretsOptions{
 | 
			
		||||
		OwnerID:     ctx.Org.Organization.ID,
 | 
			
		||||
		ListOptions: utils.GetListOptions(ctx),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	secrets, count, err := db.FindAndCount[secret_model.Secret](ctx, opts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.InternalServerError(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	apiSecrets := make([]*api.Secret, len(secrets))
 | 
			
		||||
	for k, v := range secrets {
 | 
			
		||||
		apiSecrets[k] = &api.Secret{
 | 
			
		||||
			Name:    v.Name,
 | 
			
		||||
			Created: v.CreatedUnix.AsTime(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.SetTotalCountHeader(count)
 | 
			
		||||
	ctx.JSON(http.StatusOK, apiSecrets)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// create or update one secret of the organization
 | 
			
		||||
func (Action) CreateOrUpdateSecret(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation PUT /orgs/{org}/actions/secrets/{secretname} organization updateOrgSecret
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Create or Update a secret value in an organization
 | 
			
		||||
	// consumes:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// produces:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// parameters:
 | 
			
		||||
	// - name: org
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of organization
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: secretname
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of the secret
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: body
 | 
			
		||||
	//   in: body
 | 
			
		||||
	//   schema:
 | 
			
		||||
	//     "$ref": "#/definitions/CreateOrUpdateSecretOption"
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "201":
 | 
			
		||||
	//     description: response when creating a secret
 | 
			
		||||
	//   "204":
 | 
			
		||||
	//     description: response when updating a secret
 | 
			
		||||
	//   "400":
 | 
			
		||||
	//     "$ref": "#/responses/error"
 | 
			
		||||
	//   "404":
 | 
			
		||||
	//     "$ref": "#/responses/notFound"
 | 
			
		||||
 | 
			
		||||
	opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
 | 
			
		||||
 | 
			
		||||
	_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Org.Organization.ID, 0, ctx.Params("secretname"), opt.Data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, util.ErrInvalidArgument) {
 | 
			
		||||
			ctx.Error(http.StatusBadRequest, "CreateOrUpdateSecret", err)
 | 
			
		||||
		} else if errors.Is(err, util.ErrNotExist) {
 | 
			
		||||
			ctx.Error(http.StatusNotFound, "CreateOrUpdateSecret", err)
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.Error(http.StatusInternalServerError, "CreateOrUpdateSecret", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if created {
 | 
			
		||||
		ctx.Status(http.StatusCreated)
 | 
			
		||||
	} else {
 | 
			
		||||
		ctx.Status(http.StatusNoContent)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteSecret delete one secret of the organization
 | 
			
		||||
func (Action) DeleteSecret(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation DELETE /orgs/{org}/actions/secrets/{secretname} organization deleteOrgSecret
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Delete a secret in an organization
 | 
			
		||||
	// consumes:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// produces:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// parameters:
 | 
			
		||||
	// - name: org
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of organization
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: secretname
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of the secret
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "204":
 | 
			
		||||
	//     description: delete one secret of the organization
 | 
			
		||||
	//   "400":
 | 
			
		||||
	//     "$ref": "#/responses/error"
 | 
			
		||||
	//   "404":
 | 
			
		||||
	//     "$ref": "#/responses/notFound"
 | 
			
		||||
 | 
			
		||||
	err := secret_service.DeleteSecretByName(ctx, ctx.Org.Organization.ID, 0, ctx.Params("secretname"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, util.ErrInvalidArgument) {
 | 
			
		||||
			ctx.Error(http.StatusBadRequest, "DeleteSecret", err)
 | 
			
		||||
		} else if errors.Is(err, util.ErrNotExist) {
 | 
			
		||||
			ctx.Error(http.StatusNotFound, "DeleteSecret", err)
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.Error(http.StatusInternalServerError, "DeleteSecret", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Status(http.StatusNoContent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-an-organization
 | 
			
		||||
// GetRegistrationToken returns the token to register org runners
 | 
			
		||||
func (Action) GetRegistrationToken(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation GET /orgs/{org}/actions/runners/registration-token organization orgGetRunnerRegistrationToken
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Get an organization's actions runner registration token
 | 
			
		||||
	// produces:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// parameters:
 | 
			
		||||
	// - name: org
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of the organization
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "200":
 | 
			
		||||
	//     "$ref": "#/responses/RegistrationToken"
 | 
			
		||||
 | 
			
		||||
	shared.GetRegistrationToken(ctx, ctx.Org.Organization.ID, 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListVariables list org-level variables
 | 
			
		||||
func ListVariables(ctx *context.APIContext) {
 | 
			
		||||
func (Action) ListVariables(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation GET /orgs/{org}/actions/variables organization getOrgVariablesList
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Get an org-level variables list
 | 
			
		||||
@ -70,7 +242,7 @@ func ListVariables(ctx *context.APIContext) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetVariable get an org-level variable
 | 
			
		||||
func GetVariable(ctx *context.APIContext) {
 | 
			
		||||
func (Action) GetVariable(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation GET /orgs/{org}/actions/variables/{variablename} organization getOrgVariable
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Get an org-level variable
 | 
			
		||||
@ -119,7 +291,7 @@ func GetVariable(ctx *context.APIContext) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteVariable delete an org-level variable
 | 
			
		||||
func DeleteVariable(ctx *context.APIContext) {
 | 
			
		||||
func (Action) DeleteVariable(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation DELETE /orgs/{org}/actions/variables/{variablename} organization deleteOrgVariable
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Delete an org-level variable
 | 
			
		||||
@ -163,7 +335,7 @@ func DeleteVariable(ctx *context.APIContext) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateVariable create an org-level variable
 | 
			
		||||
func CreateVariable(ctx *context.APIContext) {
 | 
			
		||||
func (Action) CreateVariable(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation POST /orgs/{org}/actions/variables/{variablename} organization createOrgVariable
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Create an org-level variable
 | 
			
		||||
@ -227,7 +399,7 @@ func CreateVariable(ctx *context.APIContext) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateVariable update an org-level variable
 | 
			
		||||
func UpdateVariable(ctx *context.APIContext) {
 | 
			
		||||
func (Action) UpdateVariable(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation PUT /orgs/{org}/actions/variables/{variablename} organization updateOrgVariable
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Update an org-level variable
 | 
			
		||||
@ -289,3 +461,13 @@ func UpdateVariable(ctx *context.APIContext) {
 | 
			
		||||
 | 
			
		||||
	ctx.Status(http.StatusNoContent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ actions_service.API = new(Action)
 | 
			
		||||
 | 
			
		||||
// Action implements actions_service.API
 | 
			
		||||
type Action struct{}
 | 
			
		||||
 | 
			
		||||
// NewAction creates a new Action service
 | 
			
		||||
func NewAction() actions_service.API {
 | 
			
		||||
	return Action{}
 | 
			
		||||
}
 | 
			
		||||
@ -1,31 +0,0 @@
 | 
			
		||||
// Copyright 2023 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package org
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"code.gitea.io/gitea/routers/api/v1/shared"
 | 
			
		||||
	"code.gitea.io/gitea/services/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-an-organization
 | 
			
		||||
 | 
			
		||||
// GetRegistrationToken returns the token to register org runners
 | 
			
		||||
func GetRegistrationToken(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation GET /orgs/{org}/actions/runners/registration-token organization orgGetRunnerRegistrationToken
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Get an organization's actions runner registration token
 | 
			
		||||
	// produces:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// parameters:
 | 
			
		||||
	// - name: org
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of the organization
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "200":
 | 
			
		||||
	//     "$ref": "#/responses/RegistrationToken"
 | 
			
		||||
 | 
			
		||||
	shared.GetRegistrationToken(ctx, ctx.Org.Organization.ID, 0)
 | 
			
		||||
}
 | 
			
		||||
@ -1,166 +0,0 @@
 | 
			
		||||
// Copyright 2023 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package org
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	secret_model "code.gitea.io/gitea/models/secret"
 | 
			
		||||
	api "code.gitea.io/gitea/modules/structs"
 | 
			
		||||
	"code.gitea.io/gitea/modules/util"
 | 
			
		||||
	"code.gitea.io/gitea/modules/web"
 | 
			
		||||
	"code.gitea.io/gitea/routers/api/v1/utils"
 | 
			
		||||
	"code.gitea.io/gitea/services/context"
 | 
			
		||||
	secret_service "code.gitea.io/gitea/services/secrets"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListActionsSecrets list an organization's actions secrets
 | 
			
		||||
func ListActionsSecrets(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation GET /orgs/{org}/actions/secrets organization orgListActionsSecrets
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: List an organization's actions secrets
 | 
			
		||||
	// produces:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// parameters:
 | 
			
		||||
	// - name: org
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of the organization
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: page
 | 
			
		||||
	//   in: query
 | 
			
		||||
	//   description: page number of results to return (1-based)
 | 
			
		||||
	//   type: integer
 | 
			
		||||
	// - name: limit
 | 
			
		||||
	//   in: query
 | 
			
		||||
	//   description: page size of results
 | 
			
		||||
	//   type: integer
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "200":
 | 
			
		||||
	//     "$ref": "#/responses/SecretList"
 | 
			
		||||
	//   "404":
 | 
			
		||||
	//     "$ref": "#/responses/notFound"
 | 
			
		||||
 | 
			
		||||
	opts := &secret_model.FindSecretsOptions{
 | 
			
		||||
		OwnerID:     ctx.Org.Organization.ID,
 | 
			
		||||
		ListOptions: utils.GetListOptions(ctx),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	secrets, count, err := db.FindAndCount[secret_model.Secret](ctx, opts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.InternalServerError(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	apiSecrets := make([]*api.Secret, len(secrets))
 | 
			
		||||
	for k, v := range secrets {
 | 
			
		||||
		apiSecrets[k] = &api.Secret{
 | 
			
		||||
			Name:    v.Name,
 | 
			
		||||
			Created: v.CreatedUnix.AsTime(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.SetTotalCountHeader(count)
 | 
			
		||||
	ctx.JSON(http.StatusOK, apiSecrets)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// create or update one secret of the organization
 | 
			
		||||
func CreateOrUpdateSecret(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation PUT /orgs/{org}/actions/secrets/{secretname} organization updateOrgSecret
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Create or Update a secret value in an organization
 | 
			
		||||
	// consumes:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// produces:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// parameters:
 | 
			
		||||
	// - name: org
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of organization
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: secretname
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of the secret
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: body
 | 
			
		||||
	//   in: body
 | 
			
		||||
	//   schema:
 | 
			
		||||
	//     "$ref": "#/definitions/CreateOrUpdateSecretOption"
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "201":
 | 
			
		||||
	//     description: response when creating a secret
 | 
			
		||||
	//   "204":
 | 
			
		||||
	//     description: response when updating a secret
 | 
			
		||||
	//   "400":
 | 
			
		||||
	//     "$ref": "#/responses/error"
 | 
			
		||||
	//   "404":
 | 
			
		||||
	//     "$ref": "#/responses/notFound"
 | 
			
		||||
 | 
			
		||||
	opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
 | 
			
		||||
 | 
			
		||||
	_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Org.Organization.ID, 0, ctx.Params("secretname"), opt.Data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, util.ErrInvalidArgument) {
 | 
			
		||||
			ctx.Error(http.StatusBadRequest, "CreateOrUpdateSecret", err)
 | 
			
		||||
		} else if errors.Is(err, util.ErrNotExist) {
 | 
			
		||||
			ctx.Error(http.StatusNotFound, "CreateOrUpdateSecret", err)
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.Error(http.StatusInternalServerError, "CreateOrUpdateSecret", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if created {
 | 
			
		||||
		ctx.Status(http.StatusCreated)
 | 
			
		||||
	} else {
 | 
			
		||||
		ctx.Status(http.StatusNoContent)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteSecret delete one secret of the organization
 | 
			
		||||
func DeleteSecret(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation DELETE /orgs/{org}/actions/secrets/{secretname} organization deleteOrgSecret
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Delete a secret in an organization
 | 
			
		||||
	// consumes:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// produces:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// parameters:
 | 
			
		||||
	// - name: org
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of organization
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: secretname
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of the secret
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "204":
 | 
			
		||||
	//     description: delete one secret of the organization
 | 
			
		||||
	//   "400":
 | 
			
		||||
	//     "$ref": "#/responses/error"
 | 
			
		||||
	//   "404":
 | 
			
		||||
	//     "$ref": "#/responses/notFound"
 | 
			
		||||
 | 
			
		||||
	err := secret_service.DeleteSecretByName(ctx, ctx.Org.Organization.ID, 0, ctx.Params("secretname"))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if errors.Is(err, util.ErrInvalidArgument) {
 | 
			
		||||
			ctx.Error(http.StatusBadRequest, "DeleteSecret", err)
 | 
			
		||||
		} else if errors.Is(err, util.ErrNotExist) {
 | 
			
		||||
			ctx.Error(http.StatusNotFound, "DeleteSecret", err)
 | 
			
		||||
		} else {
 | 
			
		||||
			ctx.Error(http.StatusInternalServerError, "DeleteSecret", err)
 | 
			
		||||
		}
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Status(http.StatusNoContent)
 | 
			
		||||
}
 | 
			
		||||
@ -9,17 +9,76 @@ import (
 | 
			
		||||
 | 
			
		||||
	actions_model "code.gitea.io/gitea/models/actions"
 | 
			
		||||
	"code.gitea.io/gitea/models/db"
 | 
			
		||||
	secret_model "code.gitea.io/gitea/models/secret"
 | 
			
		||||
	api "code.gitea.io/gitea/modules/structs"
 | 
			
		||||
	"code.gitea.io/gitea/modules/util"
 | 
			
		||||
	"code.gitea.io/gitea/modules/web"
 | 
			
		||||
	"code.gitea.io/gitea/routers/api/v1/shared"
 | 
			
		||||
	"code.gitea.io/gitea/routers/api/v1/utils"
 | 
			
		||||
	actions_service "code.gitea.io/gitea/services/actions"
 | 
			
		||||
	"code.gitea.io/gitea/services/context"
 | 
			
		||||
	secret_service "code.gitea.io/gitea/services/secrets"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ListActionsSecrets list an repo's actions secrets
 | 
			
		||||
func (Action) ListActionsSecrets(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation GET /repos/{owner}/{repo}/actions/secrets repository repoListActionsSecrets
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: List an repo's actions secrets
 | 
			
		||||
	// produces:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// parameters:
 | 
			
		||||
	// - name: owner
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: owner of the repository
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: repo
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of the repository
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: page
 | 
			
		||||
	//   in: query
 | 
			
		||||
	//   description: page number of results to return (1-based)
 | 
			
		||||
	//   type: integer
 | 
			
		||||
	// - name: limit
 | 
			
		||||
	//   in: query
 | 
			
		||||
	//   description: page size of results
 | 
			
		||||
	//   type: integer
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "200":
 | 
			
		||||
	//     "$ref": "#/responses/SecretList"
 | 
			
		||||
	//   "404":
 | 
			
		||||
	//     "$ref": "#/responses/notFound"
 | 
			
		||||
 | 
			
		||||
	repo := ctx.Repo.Repository
 | 
			
		||||
 | 
			
		||||
	opts := &secret_model.FindSecretsOptions{
 | 
			
		||||
		RepoID:      repo.ID,
 | 
			
		||||
		ListOptions: utils.GetListOptions(ctx),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	secrets, count, err := db.FindAndCount[secret_model.Secret](ctx, opts)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.InternalServerError(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	apiSecrets := make([]*api.Secret, len(secrets))
 | 
			
		||||
	for k, v := range secrets {
 | 
			
		||||
		apiSecrets[k] = &api.Secret{
 | 
			
		||||
			Name:    v.Name,
 | 
			
		||||
			Created: v.CreatedUnix.AsTime(),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.SetTotalCountHeader(count)
 | 
			
		||||
	ctx.JSON(http.StatusOK, apiSecrets)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// create or update one secret of the repository
 | 
			
		||||
func CreateOrUpdateSecret(ctx *context.APIContext) {
 | 
			
		||||
func (Action) CreateOrUpdateSecret(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation PUT /repos/{owner}/{repo}/actions/secrets/{secretname} repository updateRepoSecret
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Create or Update a secret value in a repository
 | 
			
		||||
@ -82,7 +141,7 @@ func CreateOrUpdateSecret(ctx *context.APIContext) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteSecret delete one secret of the repository
 | 
			
		||||
func DeleteSecret(ctx *context.APIContext) {
 | 
			
		||||
func (Action) DeleteSecret(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation DELETE /repos/{owner}/{repo}/actions/secrets/{secretname} repository deleteRepoSecret
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Delete a secret in a repository
 | 
			
		||||
@ -133,7 +192,7 @@ func DeleteSecret(ctx *context.APIContext) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetVariable get a repo-level variable
 | 
			
		||||
func GetVariable(ctx *context.APIContext) {
 | 
			
		||||
func (Action) GetVariable(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation GET /repos/{owner}/{repo}/actions/variables/{variablename} repository getRepoVariable
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Get a repo-level variable
 | 
			
		||||
@ -186,7 +245,7 @@ func GetVariable(ctx *context.APIContext) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeleteVariable delete a repo-level variable
 | 
			
		||||
func DeleteVariable(ctx *context.APIContext) {
 | 
			
		||||
func (Action) DeleteVariable(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation DELETE /repos/{owner}/{repo}/actions/variables/{variablename} repository deleteRepoVariable
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Delete a repo-level variable
 | 
			
		||||
@ -235,7 +294,7 @@ func DeleteVariable(ctx *context.APIContext) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// CreateVariable create a repo-level variable
 | 
			
		||||
func CreateVariable(ctx *context.APIContext) {
 | 
			
		||||
func (Action) CreateVariable(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation POST /repos/{owner}/{repo}/actions/variables/{variablename} repository createRepoVariable
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Create a repo-level variable
 | 
			
		||||
@ -302,7 +361,7 @@ func CreateVariable(ctx *context.APIContext) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateVariable update a repo-level variable
 | 
			
		||||
func UpdateVariable(ctx *context.APIContext) {
 | 
			
		||||
func (Action) UpdateVariable(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation PUT /repos/{owner}/{repo}/actions/variables/{variablename} repository updateRepoVariable
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Update a repo-level variable
 | 
			
		||||
@ -369,7 +428,7 @@ func UpdateVariable(ctx *context.APIContext) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ListVariables list repo-level variables
 | 
			
		||||
func ListVariables(ctx *context.APIContext) {
 | 
			
		||||
func (Action) ListVariables(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation GET /repos/{owner}/{repo}/actions/variables repository getRepoVariablesList
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Get repo-level variables list
 | 
			
		||||
@ -423,3 +482,38 @@ func ListVariables(ctx *context.APIContext) {
 | 
			
		||||
	ctx.SetTotalCountHeader(count)
 | 
			
		||||
	ctx.JSON(http.StatusOK, variables)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetRegistrationToken returns the token to register repo runners
 | 
			
		||||
func (Action) GetRegistrationToken(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation GET /repos/{owner}/{repo}/runners/registration-token repository repoGetRunnerRegistrationToken
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Get a repository's actions runner registration token
 | 
			
		||||
	// produces:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// parameters:
 | 
			
		||||
	// - name: owner
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: owner of the repo
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: repo
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of the repo
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "200":
 | 
			
		||||
	//     "$ref": "#/responses/RegistrationToken"
 | 
			
		||||
 | 
			
		||||
	shared.GetRegistrationToken(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.ID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ actions_service.API = new(Action)
 | 
			
		||||
 | 
			
		||||
// Action implements actions_service.API
 | 
			
		||||
type Action struct{}
 | 
			
		||||
 | 
			
		||||
// NewAction creates a new Action service
 | 
			
		||||
func NewAction() actions_service.API {
 | 
			
		||||
	return Action{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,34 +0,0 @@
 | 
			
		||||
// Copyright 2023 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package repo
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"code.gitea.io/gitea/routers/api/v1/shared"
 | 
			
		||||
	"code.gitea.io/gitea/services/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetRegistrationToken returns the token to register repo runners
 | 
			
		||||
func GetRegistrationToken(ctx *context.APIContext) {
 | 
			
		||||
	// swagger:operation GET /repos/{owner}/{repo}/runners/registration-token repository repoGetRunnerRegistrationToken
 | 
			
		||||
	// ---
 | 
			
		||||
	// summary: Get a repository's actions runner registration token
 | 
			
		||||
	// produces:
 | 
			
		||||
	// - application/json
 | 
			
		||||
	// parameters:
 | 
			
		||||
	// - name: owner
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: owner of the repo
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// - name: repo
 | 
			
		||||
	//   in: path
 | 
			
		||||
	//   description: name of the repo
 | 
			
		||||
	//   type: string
 | 
			
		||||
	//   required: true
 | 
			
		||||
	// responses:
 | 
			
		||||
	//   "200":
 | 
			
		||||
	//     "$ref": "#/responses/RegistrationToken"
 | 
			
		||||
 | 
			
		||||
	shared.GetRegistrationToken(ctx, ctx.Repo.Repository.OwnerID, ctx.Repo.Repository.ID)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								services/actions/interface.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								services/actions/interface.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
// Copyright 2024 The Gitea Authors. All rights reserved.
 | 
			
		||||
// SPDX-License-Identifier: MIT
 | 
			
		||||
 | 
			
		||||
package actions
 | 
			
		||||
 | 
			
		||||
import "code.gitea.io/gitea/services/context"
 | 
			
		||||
 | 
			
		||||
// API for actions of a repository or organization
 | 
			
		||||
type API interface {
 | 
			
		||||
	// ListActionsSecrets list secrets
 | 
			
		||||
	ListActionsSecrets(*context.APIContext)
 | 
			
		||||
	// CreateOrUpdateSecret create or update a secret
 | 
			
		||||
	CreateOrUpdateSecret(*context.APIContext)
 | 
			
		||||
	// DeleteSecret delete a secret
 | 
			
		||||
	DeleteSecret(*context.APIContext)
 | 
			
		||||
	// ListVariables list variables
 | 
			
		||||
	ListVariables(*context.APIContext)
 | 
			
		||||
	// GetVariable get a variable
 | 
			
		||||
	GetVariable(*context.APIContext)
 | 
			
		||||
	// DeleteVariable delete a variable
 | 
			
		||||
	DeleteVariable(*context.APIContext)
 | 
			
		||||
	// CreateVariable create a variable
 | 
			
		||||
	CreateVariable(*context.APIContext)
 | 
			
		||||
	// UpdateVariable update a variable
 | 
			
		||||
	UpdateVariable(*context.APIContext)
 | 
			
		||||
	// GetRegistrationToken get registration token
 | 
			
		||||
	GetRegistrationToken(*context.APIContext)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								templates/swagger/v1_json.tmpl
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										48
									
								
								templates/swagger/v1_json.tmpl
									
									
									
										generated
									
									
									
								
							@ -3843,6 +3843,54 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "/repos/{owner}/{repo}/actions/secrets": {
 | 
			
		||||
      "get": {
 | 
			
		||||
        "produces": [
 | 
			
		||||
          "application/json"
 | 
			
		||||
        ],
 | 
			
		||||
        "tags": [
 | 
			
		||||
          "repository"
 | 
			
		||||
        ],
 | 
			
		||||
        "summary": "List an repo's actions secrets",
 | 
			
		||||
        "operationId": "repoListActionsSecrets",
 | 
			
		||||
        "parameters": [
 | 
			
		||||
          {
 | 
			
		||||
            "type": "string",
 | 
			
		||||
            "description": "owner of the repository",
 | 
			
		||||
            "name": "owner",
 | 
			
		||||
            "in": "path",
 | 
			
		||||
            "required": true
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            "type": "string",
 | 
			
		||||
            "description": "name of the repository",
 | 
			
		||||
            "name": "repo",
 | 
			
		||||
            "in": "path",
 | 
			
		||||
            "required": true
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            "type": "integer",
 | 
			
		||||
            "description": "page number of results to return (1-based)",
 | 
			
		||||
            "name": "page",
 | 
			
		||||
            "in": "query"
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            "type": "integer",
 | 
			
		||||
            "description": "page size of results",
 | 
			
		||||
            "name": "limit",
 | 
			
		||||
            "in": "query"
 | 
			
		||||
          }
 | 
			
		||||
        ],
 | 
			
		||||
        "responses": {
 | 
			
		||||
          "200": {
 | 
			
		||||
            "$ref": "#/responses/SecretList"
 | 
			
		||||
          },
 | 
			
		||||
          "404": {
 | 
			
		||||
            "$ref": "#/responses/notFound"
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "/repos/{owner}/{repo}/actions/secrets/{secretname}": {
 | 
			
		||||
      "put": {
 | 
			
		||||
        "consumes": [
 | 
			
		||||
 | 
			
		||||
@ -24,6 +24,12 @@ func TestAPIRepoSecrets(t *testing.T) {
 | 
			
		||||
	session := loginUser(t, user.Name)
 | 
			
		||||
	token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
 | 
			
		||||
 | 
			
		||||
	t.Run("List", func(t *testing.T) {
 | 
			
		||||
		req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/actions/secrets", repo.FullName())).
 | 
			
		||||
			AddTokenAuth(token)
 | 
			
		||||
		MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	t.Run("Create", func(t *testing.T) {
 | 
			
		||||
		cases := []struct {
 | 
			
		||||
			Name           string
 | 
			
		||||
@ -31,7 +37,7 @@ func TestAPIRepoSecrets(t *testing.T) {
 | 
			
		||||
		}{
 | 
			
		||||
			{
 | 
			
		||||
				Name:           "",
 | 
			
		||||
				ExpectedStatus: http.StatusNotFound,
 | 
			
		||||
				ExpectedStatus: http.StatusMethodNotAllowed,
 | 
			
		||||
			},
 | 
			
		||||
			{
 | 
			
		||||
				Name:           "-",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user