Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API for Variables #29520

Merged
merged 25 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d20280e
feat: create and update user scope variable
sillyguodong Mar 1, 2024
7fb32af
chore: lint and typo
sillyguodong Mar 1, 2024
eacaba1
feat: delete and get user-level var
sillyguodong Mar 8, 2024
c0ccc4b
Merge branch 'main' into feat/api_for_variables
sillyguodong Mar 11, 2024
a4a0102
chore: generate swagger
sillyguodong Mar 11, 2024
ca218ad
feat: org-level var api
sillyguodong Mar 12, 2024
b23a836
feat: repo-level var api
sillyguodong Mar 12, 2024
e931674
revert Makefile
sillyguodong Mar 12, 2024
6e1548c
lint swagger
sillyguodong Mar 12, 2024
a4c633e
chore: add new line at end of swgger file
sillyguodong Mar 12, 2024
512d062
feat: list variables
sillyguodong Mar 13, 2024
73f483c
chore: tab to space
sillyguodong Mar 14, 2024
0dd5c00
Merge branch 'main' into feat/api_for_variables
sillyguodong Mar 14, 2024
473cff7
Merge branch 'main' into feat/api_for_variables
sillyguodong Mar 14, 2024
77624df
Merge branch 'main' into feat/api_for_variables
silverwind Mar 14, 2024
1806ad7
fix: no check null for owner_id and repo_id
sillyguodong Mar 25, 2024
ef5f9f5
Merge branch 'main' into feat/api_for_variables
sillyguodong Mar 26, 2024
bf807a6
chore: add integration test
sillyguodong Mar 26, 2024
da18636
chore: add comment for opts
sillyguodong Mar 26, 2024
6e21046
fix: misspelling
sillyguodong Mar 26, 2024
75d96f1
fix: test case
sillyguodong Mar 26, 2024
48f23c9
chore: mv func to util pkg
sillyguodong Mar 27, 2024
dec6da3
chore: re-run actions
sillyguodong Mar 27, 2024
a869bcc
Merge branch 'main' into feat/api_for_variables
techknowlogick Mar 28, 2024
1e3224b
Merge branch 'main' into feat/api_for_variables
GiteaBot Mar 28, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions models/actions/variable.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ package actions
import (
"context"
"errors"
"fmt"
"strings"

"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"

"xorm.io/builder"
)
Expand Down Expand Up @@ -55,24 +53,24 @@ type FindVariablesOpts struct {
db.ListOptions
OwnerID int64
RepoID int64
Name string
}

func (opts FindVariablesOpts) ToConds() builder.Cond {
cond := builder.NewCond()
// Since we now support instance-level variables,
// there is no need to check for null values for `owner_id` and `repo_id`
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})

if opts.Name != "" {
cond = cond.And(builder.Eq{"name": strings.ToUpper(opts.Name)})
}
return cond
}

func GetVariableByID(ctx context.Context, variableID int64) (*ActionVariable, error) {
var variable ActionVariable
has, err := db.GetEngine(ctx).Where("id=?", variableID).Get(&variable)
if err != nil {
return nil, err
} else if !has {
return nil, fmt.Errorf("variable with id %d: %w", variableID, util.ErrNotExist)
}
return &variable, nil
func FindVariables(ctx context.Context, opts FindVariablesOpts) ([]*ActionVariable, error) {
return db.Find[ActionVariable](ctx, opts)
}

func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error) {
Expand All @@ -84,6 +82,13 @@ func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error)
return count != 0, err
}

func DeleteVariable(ctx context.Context, id int64) error {
if _, err := db.DeleteByID[ActionVariable](ctx, id); err != nil {
return err
}
return nil
}

func GetVariablesOfRun(ctx context.Context, run *ActionRun) (map[string]string, error) {
variables := map[string]string{}

Expand Down
37 changes: 37 additions & 0 deletions modules/structs/variable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package structs

// CreateVariableOption the option when creating variable
// swagger:model
type CreateVariableOption struct {
// Value of the variable to create
//
// required: true
Value string `json:"value" binding:"Required"`
}

// UpdateVariableOption the option when updating variable
// swagger:model
type UpdateVariableOption struct {
// New name for the variable. If the field is empty, the variable name won't be updated.
Name string `json:"name"`
// Value of the variable to update
//
// required: true
Value string `json:"value" binding:"Required"`
}

// ActionVariable return value of the query API
// swagger:model
type ActionVariable struct {
// the owner to which the variable belongs
OwnerID int64 `json:"owner_id"`
// the repository to which the variable belongs
RepoID int64 `json:"repo_id"`
// the name of the variable
Name string `json:"name"`
// the value of the variable
Data string `json:"data"`
}
9 changes: 9 additions & 0 deletions modules/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,12 @@ func IfZero[T comparable](v, def T) T {
}
return v
}

func ReserveLineBreakForTextarea(input string) string {
// Since the content is from a form which is a textarea, the line endings are \r\n.
// It's a standard behavior of HTML.
// But we want to store them as \n like what GitHub does.
// And users are unlikely to really need to keep the \r.
// Other than this, we should respect the original content, even leading or trailing spaces.
return strings.ReplaceAll(input, "\r\n", "\n")
}
5 changes: 5 additions & 0 deletions modules/util/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,8 @@ func TestToPointer(t *testing.T) {
val123 := 123
assert.False(t, &val123 == ToPointer(val123))
}

func TestReserveLineBreakForTextarea(t *testing.T) {
assert.Equal(t, ReserveLineBreakForTextarea("test\r\ndata"), "test\ndata")
assert.Equal(t, ReserveLineBreakForTextarea("test\r\ndata\r\n"), "test\ndata\n")
}
27 changes: 27 additions & 0 deletions routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -955,6 +955,15 @@ func Routes() *web.Route {
Delete(user.DeleteSecret)
})

m.Group("/variables", func() {
m.Get("", user.ListVariables)
m.Combo("/{variablename}").
Get(user.GetVariable).
Delete(user.DeleteVariable).
Post(bind(api.CreateVariableOption{}), user.CreateVariable).
sillyguodong marked this conversation as resolved.
Show resolved Hide resolved
Put(bind(api.UpdateVariableOption{}), user.UpdateVariable)
})

m.Group("/runners", func() {
m.Get("/registration-token", reqToken(), user.GetRegistrationToken)
})
Expand Down Expand Up @@ -1073,6 +1082,15 @@ func Routes() *web.Route {
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)
})
Expand Down Expand Up @@ -1452,6 +1470,15 @@ func Routes() *web.Route {
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)
})
Expand Down
Loading