1
1
mirror of https://github.com/go-gitea/gitea synced 2025-07-23 02:38:35 +00:00

Added Description Field for Secrets and Variables (#33526)

Fixes #33484

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
John Smith
2025-03-18 03:24:54 +08:00
committed by GitHub
parent 9d7c02f9f7
commit 8f051d598c
20 changed files with 247 additions and 63 deletions

View File

@@ -6,10 +6,12 @@ package actions
import (
"context"
"strings"
"unicode/utf8"
"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"
)
@@ -32,26 +34,39 @@ type ActionVariable struct {
RepoID int64 `xorm:"INDEX UNIQUE(owner_repo_name)"`
Name string `xorm:"UNIQUE(owner_repo_name) NOT NULL"`
Data string `xorm:"LONGTEXT NOT NULL"`
Description string `xorm:"TEXT"`
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
}
const (
VariableDataMaxLength = 65536
VariableDescriptionMaxLength = 4096
)
func init() {
db.RegisterModel(new(ActionVariable))
}
func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data string) (*ActionVariable, error) {
func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data, description string) (*ActionVariable, error) {
if ownerID != 0 && repoID != 0 {
// It's trying to create a variable that belongs to a repository, but OwnerID has been set accidentally.
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
ownerID = 0
}
if utf8.RuneCountInString(data) > VariableDataMaxLength {
return nil, util.NewInvalidArgumentErrorf("data too long")
}
description = util.TruncateRunes(description, VariableDescriptionMaxLength)
variable := &ActionVariable{
OwnerID: ownerID,
RepoID: repoID,
Name: strings.ToUpper(name),
Data: data,
OwnerID: ownerID,
RepoID: repoID,
Name: strings.ToUpper(name),
Data: data,
Description: description,
}
return variable, db.Insert(ctx, variable)
}
@@ -96,6 +111,12 @@ func FindVariables(ctx context.Context, opts FindVariablesOpts) ([]*ActionVariab
}
func UpdateVariableCols(ctx context.Context, variable *ActionVariable, cols ...string) (bool, error) {
if utf8.RuneCountInString(variable.Data) > VariableDataMaxLength {
return false, util.NewInvalidArgumentErrorf("data too long")
}
variable.Description = util.TruncateRunes(variable.Description, VariableDescriptionMaxLength)
variable.Name = strings.ToUpper(variable.Name)
count, err := db.GetEngine(ctx).
ID(variable.ID).

View File

@@ -376,6 +376,7 @@ func prepareMigrationTasks() []*migration {
newMigration(313, "Move PinOrder from issue table to a new table issue_pin", v1_24.MovePinOrderToTableIssuePin),
newMigration(314, "Update OwnerID as zero for repository level action tables", v1_24.UpdateOwnerIDOfRepoLevelActionsTables),
newMigration(315, "Add Ephemeral to ActionRunner", v1_24.AddEphemeralToActionRunner),
newMigration(316, "Add description for secrets and variables", v1_24.AddDescriptionForSecretsAndVariables),
}
return preparedMigrations
}

View File

@@ -0,0 +1,20 @@
// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_24 //nolint
import (
"xorm.io/xorm"
)
func AddDescriptionForSecretsAndVariables(x *xorm.Engine) error {
type Secret struct {
Description string `xorm:"TEXT"`
}
type ActionVariable struct {
Description string `xorm:"TEXT"`
}
return x.Sync(new(Secret), new(ActionVariable))
}

View File

@@ -40,9 +40,15 @@ type Secret struct {
RepoID int64 `xorm:"INDEX UNIQUE(owner_repo_name) NOT NULL DEFAULT 0"`
Name string `xorm:"UNIQUE(owner_repo_name) NOT NULL"`
Data string `xorm:"LONGTEXT"` // encrypted data
Description string `xorm:"TEXT"`
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
}
const (
SecretDataMaxLength = 65536
SecretDescriptionMaxLength = 4096
)
// ErrSecretNotFound represents a "secret not found" error.
type ErrSecretNotFound struct {
Name string
@@ -57,7 +63,7 @@ func (err ErrSecretNotFound) Unwrap() error {
}
// InsertEncryptedSecret Creates, encrypts, and validates a new secret with yet unencrypted data and insert into database
func InsertEncryptedSecret(ctx context.Context, ownerID, repoID int64, name, data string) (*Secret, error) {
func InsertEncryptedSecret(ctx context.Context, ownerID, repoID int64, name, data, description string) (*Secret, error) {
if ownerID != 0 && repoID != 0 {
// It's trying to create a secret that belongs to a repository, but OwnerID has been set accidentally.
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
@@ -67,15 +73,23 @@ func InsertEncryptedSecret(ctx context.Context, ownerID, repoID int64, name, dat
return nil, fmt.Errorf("%w: ownerID and repoID cannot be both zero, global secrets are not supported", util.ErrInvalidArgument)
}
if len(data) > SecretDataMaxLength {
return nil, util.NewInvalidArgumentErrorf("data too long")
}
description = util.TruncateRunes(description, SecretDescriptionMaxLength)
encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
if err != nil {
return nil, err
}
secret := &Secret{
OwnerID: ownerID,
RepoID: repoID,
Name: strings.ToUpper(name),
Data: encrypted,
OwnerID: ownerID,
RepoID: repoID,
Name: strings.ToUpper(name),
Data: encrypted,
Description: description,
}
return secret, db.Insert(ctx, secret)
}
@@ -114,16 +128,23 @@ func (opts FindSecretsOptions) ToConds() builder.Cond {
}
// UpdateSecret changes org or user reop secret.
func UpdateSecret(ctx context.Context, secretID int64, data string) error {
func UpdateSecret(ctx context.Context, secretID int64, data, description string) error {
if len(data) > SecretDataMaxLength {
return util.NewInvalidArgumentErrorf("data too long")
}
description = util.TruncateRunes(description, SecretDescriptionMaxLength)
encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
if err != nil {
return err
}
s := &Secret{
Data: encrypted,
Data: encrypted,
Description: description,
}
affected, err := db.GetEngine(ctx).ID(secretID).Cols("data").Update(s)
affected, err := db.GetEngine(ctx).ID(secretID).Cols("data", "description").Update(s)
if affected != 1 {
return ErrSecretNotFound{}
}