You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

action.go 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. // Copyright 2023 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package repo
  4. import (
  5. "errors"
  6. "net/http"
  7. actions_model "code.gitea.io/gitea/models/actions"
  8. "code.gitea.io/gitea/models/db"
  9. api "code.gitea.io/gitea/modules/structs"
  10. "code.gitea.io/gitea/modules/util"
  11. "code.gitea.io/gitea/modules/web"
  12. "code.gitea.io/gitea/routers/api/v1/utils"
  13. actions_service "code.gitea.io/gitea/services/actions"
  14. "code.gitea.io/gitea/services/context"
  15. secret_service "code.gitea.io/gitea/services/secrets"
  16. )
  17. // create or update one secret of the repository
  18. func CreateOrUpdateSecret(ctx *context.APIContext) {
  19. // swagger:operation PUT /repos/{owner}/{repo}/actions/secrets/{secretname} repository updateRepoSecret
  20. // ---
  21. // summary: Create or Update a secret value in a repository
  22. // consumes:
  23. // - application/json
  24. // produces:
  25. // - application/json
  26. // parameters:
  27. // - name: owner
  28. // in: path
  29. // description: owner of the repository
  30. // type: string
  31. // required: true
  32. // - name: repo
  33. // in: path
  34. // description: name of the repository
  35. // type: string
  36. // required: true
  37. // - name: secretname
  38. // in: path
  39. // description: name of the secret
  40. // type: string
  41. // required: true
  42. // - name: body
  43. // in: body
  44. // schema:
  45. // "$ref": "#/definitions/CreateOrUpdateSecretOption"
  46. // responses:
  47. // "201":
  48. // description: response when creating a secret
  49. // "204":
  50. // description: response when updating a secret
  51. // "400":
  52. // "$ref": "#/responses/error"
  53. // "404":
  54. // "$ref": "#/responses/notFound"
  55. owner := ctx.Repo.Owner
  56. repo := ctx.Repo.Repository
  57. opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
  58. _, created, err := secret_service.CreateOrUpdateSecret(ctx, owner.ID, repo.ID, ctx.Params("secretname"), opt.Data)
  59. if err != nil {
  60. if errors.Is(err, util.ErrInvalidArgument) {
  61. ctx.Error(http.StatusBadRequest, "CreateOrUpdateSecret", err)
  62. } else if errors.Is(err, util.ErrNotExist) {
  63. ctx.Error(http.StatusNotFound, "CreateOrUpdateSecret", err)
  64. } else {
  65. ctx.Error(http.StatusInternalServerError, "CreateOrUpdateSecret", err)
  66. }
  67. return
  68. }
  69. if created {
  70. ctx.Status(http.StatusCreated)
  71. } else {
  72. ctx.Status(http.StatusNoContent)
  73. }
  74. }
  75. // DeleteSecret delete one secret of the repository
  76. func DeleteSecret(ctx *context.APIContext) {
  77. // swagger:operation DELETE /repos/{owner}/{repo}/actions/secrets/{secretname} repository deleteRepoSecret
  78. // ---
  79. // summary: Delete a secret in a repository
  80. // consumes:
  81. // - application/json
  82. // produces:
  83. // - application/json
  84. // parameters:
  85. // - name: owner
  86. // in: path
  87. // description: owner of the repository
  88. // type: string
  89. // required: true
  90. // - name: repo
  91. // in: path
  92. // description: name of the repository
  93. // type: string
  94. // required: true
  95. // - name: secretname
  96. // in: path
  97. // description: name of the secret
  98. // type: string
  99. // required: true
  100. // responses:
  101. // "204":
  102. // description: delete one secret of the organization
  103. // "400":
  104. // "$ref": "#/responses/error"
  105. // "404":
  106. // "$ref": "#/responses/notFound"
  107. owner := ctx.Repo.Owner
  108. repo := ctx.Repo.Repository
  109. err := secret_service.DeleteSecretByName(ctx, owner.ID, repo.ID, ctx.Params("secretname"))
  110. if err != nil {
  111. if errors.Is(err, util.ErrInvalidArgument) {
  112. ctx.Error(http.StatusBadRequest, "DeleteSecret", err)
  113. } else if errors.Is(err, util.ErrNotExist) {
  114. ctx.Error(http.StatusNotFound, "DeleteSecret", err)
  115. } else {
  116. ctx.Error(http.StatusInternalServerError, "DeleteSecret", err)
  117. }
  118. return
  119. }
  120. ctx.Status(http.StatusNoContent)
  121. }
  122. // GetVariable get a repo-level variable
  123. func GetVariable(ctx *context.APIContext) {
  124. // swagger:operation GET /repos/{owner}/{repo}/actions/variables/{variablename} repository getRepoVariable
  125. // ---
  126. // summary: Get a repo-level variable
  127. // produces:
  128. // - application/json
  129. // parameters:
  130. // - name: owner
  131. // in: path
  132. // description: name of the owner
  133. // type: string
  134. // required: true
  135. // - name: repo
  136. // in: path
  137. // description: name of the repository
  138. // type: string
  139. // required: true
  140. // - name: variablename
  141. // in: path
  142. // description: name of the variable
  143. // type: string
  144. // required: true
  145. // responses:
  146. // "200":
  147. // "$ref": "#/responses/ActionVariable"
  148. // "400":
  149. // "$ref": "#/responses/error"
  150. // "404":
  151. // "$ref": "#/responses/notFound"
  152. v, err := actions_service.GetVariable(ctx, actions_model.FindVariablesOpts{
  153. RepoID: ctx.Repo.Repository.ID,
  154. Name: ctx.Params("variablename"),
  155. })
  156. if err != nil {
  157. if errors.Is(err, util.ErrNotExist) {
  158. ctx.Error(http.StatusNotFound, "GetVariable", err)
  159. } else {
  160. ctx.Error(http.StatusInternalServerError, "GetVariable", err)
  161. }
  162. return
  163. }
  164. variable := &api.ActionVariable{
  165. OwnerID: v.OwnerID,
  166. RepoID: v.RepoID,
  167. Name: v.Name,
  168. Data: v.Data,
  169. }
  170. ctx.JSON(http.StatusOK, variable)
  171. }
  172. // DeleteVariable delete a repo-level variable
  173. func DeleteVariable(ctx *context.APIContext) {
  174. // swagger:operation DELETE /repos/{owner}/{repo}/actions/variables/{variablename} repository deleteRepoVariable
  175. // ---
  176. // summary: Delete a repo-level variable
  177. // produces:
  178. // - application/json
  179. // parameters:
  180. // - name: owner
  181. // in: path
  182. // description: name of the owner
  183. // type: string
  184. // required: true
  185. // - name: repo
  186. // in: path
  187. // description: name of the repository
  188. // type: string
  189. // required: true
  190. // - name: variablename
  191. // in: path
  192. // description: name of the variable
  193. // type: string
  194. // required: true
  195. // responses:
  196. // "200":
  197. // "$ref": "#/responses/ActionVariable"
  198. // "201":
  199. // description: response when deleting a variable
  200. // "204":
  201. // description: response when deleting a variable
  202. // "400":
  203. // "$ref": "#/responses/error"
  204. // "404":
  205. // "$ref": "#/responses/notFound"
  206. if err := actions_service.DeleteVariableByName(ctx, 0, ctx.Repo.Repository.ID, ctx.Params("variablename")); err != nil {
  207. if errors.Is(err, util.ErrInvalidArgument) {
  208. ctx.Error(http.StatusBadRequest, "DeleteVariableByName", err)
  209. } else if errors.Is(err, util.ErrNotExist) {
  210. ctx.Error(http.StatusNotFound, "DeleteVariableByName", err)
  211. } else {
  212. ctx.Error(http.StatusInternalServerError, "DeleteVariableByName", err)
  213. }
  214. return
  215. }
  216. ctx.Status(http.StatusNoContent)
  217. }
  218. // CreateVariable create a repo-level variable
  219. func CreateVariable(ctx *context.APIContext) {
  220. // swagger:operation POST /repos/{owner}/{repo}/actions/variables/{variablename} repository createRepoVariable
  221. // ---
  222. // summary: Create a repo-level variable
  223. // produces:
  224. // - application/json
  225. // parameters:
  226. // - name: owner
  227. // in: path
  228. // description: name of the owner
  229. // type: string
  230. // required: true
  231. // - name: repo
  232. // in: path
  233. // description: name of the repository
  234. // type: string
  235. // required: true
  236. // - name: variablename
  237. // in: path
  238. // description: name of the variable
  239. // type: string
  240. // required: true
  241. // - name: body
  242. // in: body
  243. // schema:
  244. // "$ref": "#/definitions/CreateVariableOption"
  245. // responses:
  246. // "201":
  247. // description: response when creating a repo-level variable
  248. // "204":
  249. // description: response when creating a repo-level variable
  250. // "400":
  251. // "$ref": "#/responses/error"
  252. // "404":
  253. // "$ref": "#/responses/notFound"
  254. opt := web.GetForm(ctx).(*api.CreateVariableOption)
  255. repoID := ctx.Repo.Repository.ID
  256. variableName := ctx.Params("variablename")
  257. v, err := actions_service.GetVariable(ctx, actions_model.FindVariablesOpts{
  258. RepoID: repoID,
  259. Name: variableName,
  260. })
  261. if err != nil && !errors.Is(err, util.ErrNotExist) {
  262. ctx.Error(http.StatusInternalServerError, "GetVariable", err)
  263. return
  264. }
  265. if v != nil && v.ID > 0 {
  266. ctx.Error(http.StatusConflict, "VariableNameAlreadyExists", util.NewAlreadyExistErrorf("variable name %s already exists", variableName))
  267. return
  268. }
  269. if _, err := actions_service.CreateVariable(ctx, 0, repoID, variableName, opt.Value); err != nil {
  270. if errors.Is(err, util.ErrInvalidArgument) {
  271. ctx.Error(http.StatusBadRequest, "CreateVariable", err)
  272. } else {
  273. ctx.Error(http.StatusInternalServerError, "CreateVariable", err)
  274. }
  275. return
  276. }
  277. ctx.Status(http.StatusNoContent)
  278. }
  279. // UpdateVariable update a repo-level variable
  280. func UpdateVariable(ctx *context.APIContext) {
  281. // swagger:operation PUT /repos/{owner}/{repo}/actions/variables/{variablename} repository updateRepoVariable
  282. // ---
  283. // summary: Update a repo-level variable
  284. // produces:
  285. // - application/json
  286. // parameters:
  287. // - name: owner
  288. // in: path
  289. // description: name of the owner
  290. // type: string
  291. // required: true
  292. // - name: repo
  293. // in: path
  294. // description: name of the repository
  295. // type: string
  296. // required: true
  297. // - name: variablename
  298. // in: path
  299. // description: name of the variable
  300. // type: string
  301. // required: true
  302. // - name: body
  303. // in: body
  304. // schema:
  305. // "$ref": "#/definitions/UpdateVariableOption"
  306. // responses:
  307. // "201":
  308. // description: response when updating a repo-level variable
  309. // "204":
  310. // description: response when updating a repo-level variable
  311. // "400":
  312. // "$ref": "#/responses/error"
  313. // "404":
  314. // "$ref": "#/responses/notFound"
  315. opt := web.GetForm(ctx).(*api.UpdateVariableOption)
  316. v, err := actions_service.GetVariable(ctx, actions_model.FindVariablesOpts{
  317. RepoID: ctx.Repo.Repository.ID,
  318. Name: ctx.Params("variablename"),
  319. })
  320. if err != nil {
  321. if errors.Is(err, util.ErrNotExist) {
  322. ctx.Error(http.StatusNotFound, "GetVariable", err)
  323. } else {
  324. ctx.Error(http.StatusInternalServerError, "GetVariable", err)
  325. }
  326. return
  327. }
  328. if opt.Name == "" {
  329. opt.Name = ctx.Params("variablename")
  330. }
  331. if _, err := actions_service.UpdateVariable(ctx, v.ID, opt.Name, opt.Value); err != nil {
  332. if errors.Is(err, util.ErrInvalidArgument) {
  333. ctx.Error(http.StatusBadRequest, "UpdateVariable", err)
  334. } else {
  335. ctx.Error(http.StatusInternalServerError, "UpdateVariable", err)
  336. }
  337. return
  338. }
  339. ctx.Status(http.StatusNoContent)
  340. }
  341. // ListVariables list repo-level variables
  342. func ListVariables(ctx *context.APIContext) {
  343. // swagger:operation GET /repos/{owner}/{repo}/actions/variables repository getRepoVariablesList
  344. // ---
  345. // summary: Get repo-level variables list
  346. // produces:
  347. // - application/json
  348. // parameters:
  349. // - name: owner
  350. // in: path
  351. // description: name of the owner
  352. // type: string
  353. // required: true
  354. // - name: repo
  355. // in: path
  356. // description: name of the repository
  357. // type: string
  358. // required: true
  359. // - name: page
  360. // in: query
  361. // description: page number of results to return (1-based)
  362. // type: integer
  363. // - name: limit
  364. // in: query
  365. // description: page size of results
  366. // type: integer
  367. // responses:
  368. // "200":
  369. // "$ref": "#/responses/VariableList"
  370. // "400":
  371. // "$ref": "#/responses/error"
  372. // "404":
  373. // "$ref": "#/responses/notFound"
  374. vars, count, err := db.FindAndCount[actions_model.ActionVariable](ctx, &actions_model.FindVariablesOpts{
  375. RepoID: ctx.Repo.Repository.ID,
  376. ListOptions: utils.GetListOptions(ctx),
  377. })
  378. if err != nil {
  379. ctx.Error(http.StatusInternalServerError, "FindVariables", err)
  380. return
  381. }
  382. variables := make([]*api.ActionVariable, len(vars))
  383. for i, v := range vars {
  384. variables[i] = &api.ActionVariable{
  385. OwnerID: v.OwnerID,
  386. RepoID: v.RepoID,
  387. Name: v.Name,
  388. }
  389. }
  390. ctx.SetTotalCountHeader(count)
  391. ctx.JSON(http.StatusOK, variables)
  392. }