0
0
mirror of https://github.com/go-gitea/gitea.git synced 2025-07-18 10:52:56 +02:00

Merge branch 'main' into lunny/move_wikipath

This commit is contained in:
Lunny Xiao 2025-03-19 11:34:38 -07:00
commit 38a445575e
87 changed files with 487 additions and 243 deletions

View File

@ -1,6 +1,6 @@
{
"name": "Gitea DevContainer",
"image": "mcr.microsoft.com/devcontainers/go:1.23-bookworm",
"image": "mcr.microsoft.com/devcontainers/go:1.24-bookworm",
"features": {
// installs nodejs into container
"ghcr.io/devcontainers/features/node:1": {

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

@ -215,12 +215,24 @@ func init() {
db.RegisterModel(new(Repository))
}
func (repo *Repository) GetName() string {
return repo.Name
func RelativePath(ownerName, repoName string) string {
return strings.ToLower(ownerName) + "/" + strings.ToLower(repoName) + ".git"
}
func (repo *Repository) GetOwnerName() string {
return repo.OwnerName
// RelativePath should be an unix style path like username/reponame.git
func (repo *Repository) RelativePath() string {
return RelativePath(repo.OwnerName, repo.Name)
}
type StorageRepo string
// RelativePath should be an unix style path like username/reponame.git
func (sr StorageRepo) RelativePath() string {
return string(sr)
}
func (repo *Repository) WikiStorageRepo() StorageRepo {
return StorageRepo(strings.ToLower(repo.OwnerName) + "/" + strings.ToLower(repo.Name) + ".wiki.git")
}
// SanitizedOriginalURL returns a sanitized OriginalURL

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{}
}

View File

@ -46,6 +46,7 @@ type Command struct {
args []string
globalArgsLength int
brokenArgs []string
cmd *exec.Cmd // for debug purpose only
}
func logArgSanitize(arg string) string {
@ -314,6 +315,7 @@ func (c *Command) run(ctx context.Context, skip int, opts *RunOpts) error {
startTime := time.Now()
cmd := exec.CommandContext(ctx, c.prog, c.args...)
c.cmd = cmd // for debug purpose only
if opts.Env == nil {
cmd.Env = os.Environ()
} else {

View File

@ -9,6 +9,8 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"time"
"code.gitea.io/gitea/modules/log"
)
@ -102,7 +104,7 @@ type CheckAttributeReader struct {
stdinReader io.ReadCloser
stdinWriter *os.File
stdOut attributeWriter
stdOut *nulSeparatedAttributeWriter
cmd *Command
env []string
ctx context.Context
@ -152,7 +154,6 @@ func (c *CheckAttributeReader) Init(ctx context.Context) error {
return nil
}
// Run run cmd
func (c *CheckAttributeReader) Run() error {
defer func() {
_ = c.stdinReader.Close()
@ -176,7 +177,7 @@ func (c *CheckAttributeReader) Run() error {
func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err error) {
defer func() {
if err != nil && err != c.ctx.Err() {
log.Error("Unexpected error when checking path %s in %s. Error: %v", path, c.Repo.Path, err)
log.Error("Unexpected error when checking path %s in %s, error: %v", path, filepath.Base(c.Repo.Path), err)
}
}()
@ -191,9 +192,31 @@ func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err
return nil, err
}
reportTimeout := func() error {
stdOutClosed := false
select {
case <-c.stdOut.closed:
stdOutClosed = true
default:
}
debugMsg := fmt.Sprintf("check path %q in repo %q", path, filepath.Base(c.Repo.Path))
debugMsg += fmt.Sprintf(", stdOut: tmp=%q, pos=%d, closed=%v", string(c.stdOut.tmp), c.stdOut.pos, stdOutClosed)
if c.cmd.cmd != nil {
debugMsg += fmt.Sprintf(", process state: %q", c.cmd.cmd.ProcessState.String())
}
_ = c.Close()
return fmt.Errorf("CheckPath timeout: %s", debugMsg)
}
rs = make(map[string]string)
for range c.Attributes {
select {
case <-time.After(5 * time.Second):
// There is a strange "hang" problem in gitdiff.GetDiff -> CheckPath
// So add a timeout here to mitigate the problem, and output more logs for debug purpose
// In real world, if CheckPath runs long than seconds, it blocks the end user's operation,
// and at the moment the CheckPath result is not so important, so we can just ignore it.
return nil, reportTimeout()
case attr, ok := <-c.stdOut.ReadAttribute():
if !ok {
return nil, c.ctx.Err()
@ -206,18 +229,12 @@ func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err
return rs, nil
}
// Close close pip after use
func (c *CheckAttributeReader) Close() error {
c.cancel()
err := c.stdinWriter.Close()
return err
}
type attributeWriter interface {
io.WriteCloser
ReadAttribute() <-chan attributeTriple
}
type attributeTriple struct {
Filename string
Attribute string
@ -281,7 +298,7 @@ func (wr *nulSeparatedAttributeWriter) Close() error {
return nil
}
// Create a check attribute reader for the current repository and provided commit ID
// CheckAttributeReader creates a check attribute reader for the current repository and provided commit ID
func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeReader, context.CancelFunc) {
indexFilename, worktree, deleteTemporaryFile, err := repo.ReadTreeToTemporaryIndex(commitID)
if err != nil {
@ -303,21 +320,21 @@ func (repo *Repository) CheckAttributeReader(commitID string) (*CheckAttributeRe
}
ctx, cancel := context.WithCancel(repo.Ctx)
if err := checker.Init(ctx); err != nil {
log.Error("Unable to open checker for %s. Error: %v", commitID, err)
log.Error("Unable to open attribute checker for commit %s, error: %v", commitID, err)
} else {
go func() {
err := checker.Run()
if err != nil && err != ctx.Err() {
log.Error("Unable to open checker for %s. Error: %v", commitID, err)
if err != nil && !IsErrCanceledOrKilled(err) {
log.Error("Attribute checker for commit %s exits with error: %v", commitID, err)
}
cancel()
}()
}
deferable := func() {
deferrable := func() {
_ = checker.Close()
cancel()
deleteTemporaryFile()
}
return checker, deferable
return checker, deferrable
}

View File

@ -4,10 +4,16 @@
package git
import (
"context"
mathRand "math/rand/v2"
"path/filepath"
"slices"
"sync"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
@ -95,3 +101,57 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
Value: "unspecified",
}, attr)
}
func TestAttributeReader(t *testing.T) {
t.Skip() // for debug purpose only, do not run in CI
ctx := t.Context()
timeout := 1 * time.Second
repoPath := filepath.Join(testReposDir, "language_stats_repo")
commitRef := "HEAD"
oneRound := func(t *testing.T, roundIdx int) {
ctx, cancel := context.WithTimeout(ctx, timeout)
_ = cancel
gitRepo, err := OpenRepository(ctx, repoPath)
require.NoError(t, err)
defer gitRepo.Close()
commit, err := gitRepo.GetCommit(commitRef)
require.NoError(t, err)
files, err := gitRepo.LsFiles()
require.NoError(t, err)
randomFiles := slices.Clone(files)
randomFiles = append(randomFiles, "any-file-1", "any-file-2")
t.Logf("Round %v with %d files", roundIdx, len(randomFiles))
attrReader, deferrable := gitRepo.CheckAttributeReader(commit.ID.String())
defer deferrable()
wg := sync.WaitGroup{}
wg.Add(1)
go func() {
for {
file := randomFiles[mathRand.IntN(len(randomFiles))]
_, err := attrReader.CheckPath(file)
if err != nil {
for i := 0; i < 10; i++ {
_, _ = attrReader.CheckPath(file)
}
break
}
}
wg.Done()
}()
wg.Wait()
}
for i := 0; i < 100; i++ {
oneRound(t, i)
}
}

View File

@ -44,24 +44,12 @@ func GetDefaultBranch(ctx context.Context, repo Repository) (string, error) {
return git.GetDefaultBranch(ctx, repoPath(repo))
}
func GetWikiDefaultBranch(ctx context.Context, repo Repository) (string, error) {
return git.GetDefaultBranch(ctx, wikiPath(repo))
}
// IsReferenceExist returns true if given reference exists in the repository.
func IsReferenceExist(ctx context.Context, repo Repository, name string) bool {
return git.IsReferenceExist(ctx, repoPath(repo), name)
}
func IsWikiReferenceExist(ctx context.Context, repo Repository, name string) bool {
return git.IsReferenceExist(ctx, wikiPath(repo), name)
}
// IsBranchExist returns true if given branch exists in the repository.
func IsBranchExist(ctx context.Context, repo Repository, name string) bool {
return IsReferenceExist(ctx, repo, git.BranchPrefix+name)
}
func IsWikiBranchExist(ctx context.Context, repo Repository, name string) bool {
return IsWikiReferenceExist(ctx, repo, git.BranchPrefix+name)
}

View File

@ -8,7 +8,6 @@ import (
"fmt"
"io"
"path/filepath"
"strings"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/reqctx"
@ -16,17 +15,15 @@ import (
"code.gitea.io/gitea/modules/util"
)
// Repository represents a git repository which stored in a disk
type Repository interface {
GetName() string
GetOwnerName() string
}
func absPath(owner, name string) string {
return filepath.Join(setting.RepoRootPath, strings.ToLower(owner), strings.ToLower(name)+".git")
RelativePath() string // We don't assume how the directory structure of the repository is, so we only need the relative path
}
// RelativePath should be an unix style path like username/reponame.git
// This method should change it according to the current OS.
func repoPath(repo Repository) string {
return absPath(repo.GetOwnerName(), repo.GetName())
return filepath.Join(setting.RepoRootPath, filepath.FromSlash(repo.RelativePath()))
}
// OpenRepository opens the repository at the given relative path with the provided context.
@ -78,9 +75,8 @@ func DeleteRepository(ctx context.Context, repo Repository) error {
}
// RenameRepository renames a repository's name on disk
func RenameRepository(ctx context.Context, repo Repository, newName string) error {
newRepoPath := absPath(repo.GetOwnerName(), newName)
if err := util.Rename(repoPath(repo), newRepoPath); err != nil {
func RenameRepository(ctx context.Context, repo, newRepo Repository) error {
if err := util.Rename(repoPath(repo), repoPath(newRepo)); err != nil {
return fmt.Errorf("rename repository directory: %w", err)
}
return nil

View File

@ -106,16 +106,11 @@ done
return hookNames, hookTpls, giteaHookTpls
}
// CreateDelegateHooksForRepo creates all the hooks scripts for the repo
func CreateDelegateHooksForRepo(_ context.Context, repo Repository) (err error) {
// CreateDelegateHooks creates all the hooks scripts for the repo
func CreateDelegateHooks(_ context.Context, repo Repository) (err error) {
return createDelegateHooks(filepath.Join(repoPath(repo), "hooks"))
}
// CreateDelegateHooksForWiki creates all the hooks scripts for the wiki repo
func CreateDelegateHooksForWiki(_ context.Context, repo Repository) (err error) {
return createDelegateHooks(filepath.Join(wikiPath(repo), "hooks"))
}
func createDelegateHooks(hookDir string) (err error) {
hookNames, hookTpls, giteaHookTpls := getHookTemplates()
@ -178,16 +173,11 @@ func ensureExecutable(filename string) error {
return os.Chmod(filename, mode)
}
// CheckDelegateHooksForRepo checks the hooks scripts for the repo
func CheckDelegateHooksForRepo(_ context.Context, repo Repository) ([]string, error) {
// CheckDelegateHooks checks the hooks scripts for the repo
func CheckDelegateHooks(_ context.Context, repo Repository) ([]string, error) {
return checkDelegateHooks(filepath.Join(repoPath(repo), "hooks"))
}
// CheckDelegateHooksForWiki checks the hooks scripts for the repo
func CheckDelegateHooksForWiki(_ context.Context, repo Repository) ([]string, error) {
return checkDelegateHooks(filepath.Join(wikiPath(repo), "hooks"))
}
func checkDelegateHooks(hookDir string) ([]string, error) {
hookNames, hookTpls, giteaHookTpls := getHookTemplates()

View File

@ -138,7 +138,7 @@ func CheckInitRepository(ctx context.Context, repo *repo_model.Repository) (err
// Init git bare new repository.
if err = git.InitRepository(ctx, repo.RepoPath(), true, repo.ObjectFormatName); err != nil {
return fmt.Errorf("git.InitRepository: %w", err)
} else if err = gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
} else if err = gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
return fmt.Errorf("createDelegateHooks: %w", err)
}
return nil

View File

@ -10,6 +10,8 @@ import "time"
type Secret struct {
// the secret's name
Name string `json:"name"`
// the secret's description
Description string `json:"description"`
// swagger:strfmt date-time
Created time.Time `json:"created_at"`
}
@ -21,4 +23,9 @@ type CreateOrUpdateSecretOption struct {
//
// required: true
Data string `json:"data" binding:"Required"`
// Description of the secret to update
//
// required: false
Description string `json:"description"`
}

View File

@ -10,6 +10,11 @@ type CreateVariableOption struct {
//
// required: true
Value string `json:"value" binding:"Required"`
// Description of the variable to create
//
// required: false
Description string `json:"description"`
}
// UpdateVariableOption the option when updating variable
@ -21,6 +26,11 @@ type UpdateVariableOption struct {
//
// required: true
Value string `json:"value" binding:"Required"`
// Description of the variable to update
//
// required: false
Description string `json:"description"`
}
// ActionVariable return value of the query API
@ -34,4 +44,6 @@ type ActionVariable struct {
Name string `json:"name"`
// the value of the variable
Data string `json:"data"`
// the description of the variable
Description string `json:"description"`
}

View File

@ -3679,6 +3679,7 @@ secrets=Tajné klíče
description=Tejné klíče budou předány určitým akcím a nelze je přečíst jinak.
none=Zatím zde nejsou žádné tajné klíče.
creation=Přidat tajný klíč
creation.description=Popis
creation.name_placeholder=nerozlišovat velká a malá písmena, pouze alfanumerické znaky nebo podtržítka, nemohou začínat na GITEA_ nebo GITHUB_
creation.value_placeholder=Vložte jakýkoliv obsah. Mezery na začátku a konci budou vynechány.
creation.success=Tajný klíč „%s“ byl přidán.

View File

@ -3670,6 +3670,7 @@ secrets=Secrets
description=Secrets werden an bestimmte Aktionen weitergegeben und können nicht anderweitig ausgelesen werden.
none=Noch keine Secrets vorhanden.
creation=Secret hinzufügen
creation.description=Beschreibung
creation.name_placeholder=Groß-/Kleinschreibung wird ignoriert, nur alphanumerische Zeichen oder Unterstriche, darf nicht mit GITEA_ oder GITHUB_ beginnen
creation.value_placeholder=Beliebigen Inhalt eingeben. Leerzeichen am Anfang und Ende werden weggelassen.
creation.success=Das Secret "%s" wurde hinzugefügt.

View File

@ -3338,6 +3338,7 @@ secrets=Μυστικά
description=Τα μυστικά θα περάσουν σε ορισμένες δράσεις και δεν μπορούν να αναγνωστούν αλλού.
none=Δεν υπάρχουν ακόμα μυστικά.
creation=Προσθήκη Μυστικού
creation.description=Περιγραφή
creation.name_placeholder=αλφαριθμητικοί χαρακτήρες ή κάτω παύλες μόνο, δεν μπορούν να ξεκινούν με GITEA_ ή GITHUB_
creation.value_placeholder=Εισάγετε οποιοδήποτε περιεχόμενο. Τα κενά στην αρχή παραλείπονται.
creation.success=Το μυστικό "%s" προστέθηκε.

View File

@ -3712,8 +3712,10 @@ secrets = Secrets
description = Secrets will be passed to certain actions and cannot be read otherwise.
none = There are no secrets yet.
creation = Add Secret
creation.description = Description
creation.name_placeholder = case-insensitive, alphanumeric characters or underscores only, cannot start with GITEA_ or GITHUB_
creation.value_placeholder = Input any content. Whitespace at the start and end will be omitted.
creation.description_placeholder = Enter short description (optional).
creation.success = The secret "%s" has been added.
creation.failed = Failed to add secret.
deletion = Remove secret

View File

@ -3318,6 +3318,7 @@ secrets=Secretos
description=Los secretos pasarán a ciertas acciones y no se podrán leer de otro modo.
none=Todavía no hay secretos.
creation=Añadir secreto
creation.description=Descripción
creation.name_placeholder=sin distinción de mayúsculas, solo carácteres alfanuméricos o guiones bajos, no puede empezar por GITEA_ o GITHUB_
creation.value_placeholder=Introduce cualquier contenido. Se omitirá el espacio en blanco en el inicio y el final.
creation.success=El secreto "%s" ha sido añadido.

View File

@ -2513,6 +2513,7 @@ conan.details.repository=مخزن
owner.settings.cleanuprules.enabled=فعال شده
[secrets]
creation.description=شرح
[actions]

View File

@ -1694,6 +1694,7 @@ conan.details.repository=Repo
owner.settings.cleanuprules.enabled=Käytössä
[secrets]
creation.description=Kuvaus
[actions]

View File

@ -3705,6 +3705,7 @@ secrets=Secrets
description=Les secrets seront transmis à certaines actions et ne pourront pas être lus autrement.
none=Il n'y a pas encore de secrets.
creation=Ajouter un secret
creation.description=Description
creation.name_placeholder=Caractères alphanumériques ou tirets bas uniquement, insensibles à la casse, ne peut commencer par GITEA_ ou GITHUB_.
creation.value_placeholder=Entrez nimporte quoi. Les blancs cernant seront taillés.
creation.success=Le secret "%s" a été ajouté.

View File

@ -3705,6 +3705,7 @@ secrets=Rúin
description=Cuirfear rúin ar aghaidh chuig gníomhartha áirithe agus ní féidir iad a léamh ar mhalairt.
none=Níl aon rúin ann fós.
creation=Cuir Rúnda leis
creation.description=Cur síos
creation.name_placeholder=carachtair alfanumair nó íoslaghda amháin nach féidir a thosú le GITEA_ nó GITHUB_
creation.value_placeholder=Ionchur ábhar ar bith. Fágfar spás bán ag tús agus ag deireadh ar lár.
creation.success=Tá an rún "%s" curtha leis.

View File

@ -1598,6 +1598,7 @@ conan.details.repository=Tároló
owner.settings.cleanuprules.enabled=Engedélyezett
[secrets]
creation.description=Leírás
[actions]

View File

@ -1398,6 +1398,7 @@ conan.details.repository=Repositori
owner.settings.cleanuprules.enabled=Aktif
[secrets]
creation.description=Deskripsi
[actions]

View File

@ -1326,6 +1326,7 @@ npm.details.tag=Merki
pypi.requires=Þarfnast Python
[secrets]
creation.description=Lýsing
[actions]

View File

@ -2790,6 +2790,7 @@ settings.delete.error=Impossibile eliminare il pacchetto.
owner.settings.cleanuprules.enabled=Attivo
[secrets]
creation.description=Descrizione
[actions]

View File

@ -3699,6 +3699,7 @@ secrets=シークレット
description=シークレットは特定のActionsに渡されます。 それ以外で読み出されることはありません。
none=シークレットはまだありません。
creation=シークレットを追加
creation.description=説明
creation.name_placeholder=大文字小文字の区別なし、英数字とアンダースコアのみ、GITEA_ や GITHUB_ で始まるものは不可
creation.value_placeholder=内容を入力してください。前後の空白は除去されます。
creation.success=シークレット "%s" を追加しました。

View File

@ -1547,6 +1547,7 @@ conan.details.repository=저장소
owner.settings.cleanuprules.enabled=활성화됨
[secrets]
creation.description=설명
[actions]

View File

@ -3341,6 +3341,7 @@ secrets=Noslēpumi
description=Noslēpumi tiks padoti atsevišķām darbībām un citādi nevar tikt nolasīti.
none=Pagaidām nav neviena noslēpuma.
creation=Pievienot noslēpumu
creation.description=Apraksts
creation.name_placeholder=reģistr-nejūtīgs, tikai burti, cipari un apakšsvītras, nevar sākties ar GITEA_ vai GITHUB_
creation.value_placeholder=Ievadiet jebkādu saturu. Atstarpes sākumā un beigā tiks noņemtas.
creation.success=Noslēpums "%s" tika pievienots.

View File

@ -2523,6 +2523,7 @@ settings.link.button=Repository link bijwerken
owner.settings.cleanuprules.enabled=Ingeschakeld
[secrets]
creation.description=Omschrijving
[actions]

View File

@ -2412,6 +2412,7 @@ conan.details.repository=Repozytorium
owner.settings.cleanuprules.enabled=Włączone
[secrets]
creation.description=Opis
[actions]

View File

@ -2194,7 +2194,7 @@ settings.protect_check_status_contexts_list=Verificações de status encontradas
settings.protect_required_approvals=Aprovações necessárias:
settings.dismiss_stale_approvals=Descartar aprovações obsoletas
settings.dismiss_stale_approvals_desc=Quando novos commits que mudam o conteúdo do pull request são enviados para o branch, as antigas aprovações serão descartadas.
settings.require_signed_commits=Exibir commits assinados
settings.require_signed_commits=Exigir commits assinados
settings.require_signed_commits_desc=Rejeitar pushes para este branch se não estiverem assinados ou não forem validáveis.
settings.protect_branch_name_pattern=Padrão de Nome de Branch Protegida
settings.protect_patterns=Padrões
@ -3278,6 +3278,7 @@ secrets=Segredos
description=Os segredos serão passados a certas ações e não poderão ser lidos de outra forma.
none=Não há segredos ainda.
creation=Adicionar Segredo
creation.description=Descrição
creation.name_placeholder=apenas caracteres alfanuméricos ou underline (_), não pode começar com GITEA_ ou GITHUB_
creation.value_placeholder=Insira qualquer conteúdo. Espaços em branco no início e no fim serão omitidos.
creation.success=O segredo "%s" foi adicionado.

View File

@ -113,6 +113,7 @@ copy_type_unsupported=Este tipo de ficheiro não pode ser copiado
write=Escrever
preview=Pré-visualizar
loading=Carregando…
files=Ficheiros
error=Erro
error404=A página que pretende aceder <strong>não existe</strong> ou <strong>não tem autorização</strong> para a ver.
@ -3710,8 +3711,10 @@ secrets=Segredos
description=Os segredos serão transmitidos a certas operações e não poderão ser lidos de outra forma.
none=Ainda não há segredos.
creation=Adicionar segredo
creation.description=Descrição
creation.name_placeholder=Só sublinhados ou alfanuméricos sem distinguir maiúsculas, sem começar com GITEA_ nem GITHUB_
creation.value_placeholder=Insira um conteúdo qualquer. Espaços em branco no início ou no fim serão omitidos.
creation.description_placeholder=Escreva uma descrição curta (opcional).
creation.success=O segredo "%s" foi adicionado.
creation.failed=Falhou ao adicionar o segredo.
deletion=Remover segredo

View File

@ -3275,6 +3275,7 @@ secrets=Секреты
description=Секреты будут передаваться определенным действиям и не могут быть прочитаны иначе.
none=Секретов пока нет.
creation=Добавить секрет
creation.description=Описание
creation.name_placeholder=регистр не важен, только алфавитно-цифровые символы и подчёркивания, не может начинаться с GITEA_ или GITHUB_
creation.value_placeholder=Введите любое содержимое. Пробельные символы в начале и конце будут опущены.
creation.success=Секрет «%s» добавлен.

View File

@ -2454,6 +2454,7 @@ conan.details.repository=කෝෂ්ඨය
owner.settings.cleanuprules.enabled=සබල කර ඇත
[secrets]
creation.description=සවිස්තරය
[actions]

View File

@ -1989,6 +1989,7 @@ conan.details.repository=Utvecklingskatalog
owner.settings.cleanuprules.enabled=Aktiv
[secrets]
creation.description=Beskrivning
[actions]

View File

@ -3534,6 +3534,7 @@ secrets=Gizlilikler
description=Gizlilikler belirli işlemlere aktarılacaktır, bunun dışında okunamaz.
none=Henüz gizlilik yok.
creation=Gizlilik Ekle
creation.description=ıklama
creation.name_placeholder=küçük-büyük harfe duyarlı değil, alfanümerik karakterler veya sadece alt tire, GITEA_ veya GITHUB_ ile başlayamaz
creation.value_placeholder=Herhangi bir içerik girin. Baştaki ve sondaki boşluklar ihmal edilecektir.
creation.success=Gizlilik "%s" eklendi.

View File

@ -2524,6 +2524,7 @@ conan.details.repository=Репозиторій
owner.settings.cleanuprules.enabled=Увімкнено
[secrets]
creation.description=Опис
[actions]

View File

@ -96,8 +96,8 @@ edit=编辑
view=查看
test=测试
enabled=启用
disabled=禁用
enabled=启用
disabled=禁用
locked=已锁定
copy=复制
@ -148,7 +148,7 @@ name=名称
value=
readme=自述文档
filter=过滤
filter=筛选
filter.clear=清除筛选器
filter.is_archived=已归档
filter.not_archived=非存档
@ -159,7 +159,7 @@ filter.not_mirror=非镜像
filter.is_template=模板
filter.not_template=非模板
filter.public=公开
filter.private=私有
filter.private=私有
no_results_found=未找到结果
internal_error_skipped=发生内部错误,但已被跳过: %s
@ -245,6 +245,7 @@ license_desc=所有的代码都开源在 <a target="_blank" rel="noopener norefe
[install]
install=安装页面
installing_desc=正在安装,请稍候...
title=初始配置
docker_helper=如果您正在使用 Docker 容器运行 Gitea请务必先仔细阅读 <a target="_blank" rel="noopener noreferrer" href="%s">官方文档</a> 后再对本页面进行填写。
require_db_desc=Gitea 需要使用 MySQL、PostgreSQL、MSSQL、SQLite3 或 TiDB (MySQL协议) 等数据库
@ -2870,7 +2871,7 @@ authentication=认证源
emails=用户邮件
config=应用配置
config_summary=摘要
config_settings=组织设置
config_settings=设置
notices=系统提示
monitor=监控面板
first_page=首页
@ -3349,6 +3350,7 @@ monitor.previous=上次执行时间
monitor.execute_times=执行次数
monitor.process=运行中进程
monitor.stacktrace=调用栈踪迹
monitor.performance_logs=性能日志
monitor.processes_count=%d 个进程
monitor.download_diagnosis_report=下载诊断报告
monitor.desc=进程描述
@ -3529,12 +3531,12 @@ alpine.registry.info=从下面的列表中选择 $branch 和 $repository。
alpine.install=要安装包,请运行以下命令:
alpine.repository=仓库信息
alpine.repository.branches=分支
alpine.repository.repositories=仓库管理
alpine.repository.repositories=仓库
alpine.repository.architectures=架构
arch.registry=添加具有相关仓库和架构的服务器到 <code>/etc/pacman.conf</code> 中:
arch.install=使用 pacman 同步软件包:
arch.repository=仓库信息
arch.repository.repositories=仓库管理
arch.repository.repositories=仓库
arch.repository.architectures=架构
cargo.registry=在 Cargo 配置文件中设置此注册中心(例如:<code>~/.cargo/config.toml</code>)
cargo.install=要使用 Cargo 安装软件包,请运行以下命令:
@ -3552,6 +3554,7 @@ conda.install=要使用 Conda 安装软件包,请运行以下命令:
container.details.type=镜像类型
container.details.platform=平台
container.pull=从命令行拉取镜像:
container.images=镜像
container.multi_arch=OS / Arch
container.layers=镜像层
container.labels=标签
@ -3655,6 +3658,7 @@ secrets=密钥
description=Secrets 将被传给特定的 Actions其它情况将不能读取
none=还没有密钥。
creation=添加密钥
creation.description=组织描述
creation.name_placeholder=不区分大小写字母数字或下划线不能以GITEA_ 或 GITHUB_ 开头。
creation.value_placeholder=输入任何内容,开头和结尾的空白都会被省略
creation.success=您的密钥 '%s' 添加成功。

View File

@ -963,6 +963,7 @@ conan.details.repository=儲存庫
owner.settings.cleanuprules.enabled=已啟用
[secrets]
creation.description=組織描述
[actions]

View File

@ -3646,6 +3646,7 @@ secrets=Secret
description=Secret 會被傳給特定的 Action其他情況無法讀取。
none=還沒有 Secret。
creation=加入 Secret
creation.description=描述
creation.name_placeholder=不區分大小寫,只能包含英文字母、數字、底線 ('_'),不能以 GITEA_ 或 GITHUB_ 開頭。
creation.value_placeholder=輸入任何內容,頭尾的空白都會被忽略。
creation.success=已新增 Secret「%s」。

View File

@ -61,8 +61,9 @@ func (Action) ListActionsSecrets(ctx *context.APIContext) {
apiSecrets := make([]*api.Secret, len(secrets))
for k, v := range secrets {
apiSecrets[k] = &api.Secret{
Name: v.Name,
Created: v.CreatedUnix.AsTime(),
Name: v.Name,
Description: v.Description,
Created: v.CreatedUnix.AsTime(),
}
}
@ -106,7 +107,7 @@ func (Action) CreateOrUpdateSecret(ctx *context.APIContext) {
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Org.Organization.ID, 0, ctx.PathParam("secretname"), opt.Data)
_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Org.Organization.ID, 0, ctx.PathParam("secretname"), opt.Data, opt.Description)
if err != nil {
if errors.Is(err, util.ErrInvalidArgument) {
ctx.APIError(http.StatusBadRequest, err)
@ -230,10 +231,11 @@ func (Action) ListVariables(ctx *context.APIContext) {
variables := make([]*api.ActionVariable, len(vars))
for i, v := range vars {
variables[i] = &api.ActionVariable{
OwnerID: v.OwnerID,
RepoID: v.RepoID,
Name: v.Name,
Data: v.Data,
OwnerID: v.OwnerID,
RepoID: v.RepoID,
Name: v.Name,
Data: v.Data,
Description: v.Description,
}
}
@ -281,10 +283,11 @@ func (Action) GetVariable(ctx *context.APIContext) {
}
variable := &api.ActionVariable{
OwnerID: v.OwnerID,
RepoID: v.RepoID,
Name: v.Name,
Data: v.Data,
OwnerID: v.OwnerID,
RepoID: v.RepoID,
Name: v.Name,
Data: v.Data,
Description: v.Description,
}
ctx.JSON(http.StatusOK, variable)
@ -386,7 +389,7 @@ func (Action) CreateVariable(ctx *context.APIContext) {
return
}
if _, err := actions_service.CreateVariable(ctx, ownerID, 0, variableName, opt.Value); err != nil {
if _, err := actions_service.CreateVariable(ctx, ownerID, 0, variableName, opt.Value, opt.Description); err != nil {
if errors.Is(err, util.ErrInvalidArgument) {
ctx.APIError(http.StatusBadRequest, err)
} else {
@ -453,6 +456,7 @@ func (Action) UpdateVariable(ctx *context.APIContext) {
v.Name = opt.Name
v.Data = opt.Value
v.Description = opt.Description
if _, err := actions_service.UpdateVariableNameData(ctx, v); err != nil {
if errors.Is(err, util.ErrInvalidArgument) {

View File

@ -84,8 +84,9 @@ func (Action) ListActionsSecrets(ctx *context.APIContext) {
apiSecrets := make([]*api.Secret, len(secrets))
for k, v := range secrets {
apiSecrets[k] = &api.Secret{
Name: v.Name,
Created: v.CreatedUnix.AsTime(),
Name: v.Name,
Description: v.Description,
Created: v.CreatedUnix.AsTime(),
}
}
@ -136,7 +137,7 @@ func (Action) CreateOrUpdateSecret(ctx *context.APIContext) {
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
_, created, err := secret_service.CreateOrUpdateSecret(ctx, 0, repo.ID, ctx.PathParam("secretname"), opt.Data)
_, created, err := secret_service.CreateOrUpdateSecret(ctx, 0, repo.ID, ctx.PathParam("secretname"), opt.Data, opt.Description)
if err != nil {
if errors.Is(err, util.ErrInvalidArgument) {
ctx.APIError(http.StatusBadRequest, err)
@ -249,10 +250,11 @@ func (Action) GetVariable(ctx *context.APIContext) {
}
variable := &api.ActionVariable{
OwnerID: v.OwnerID,
RepoID: v.RepoID,
Name: v.Name,
Data: v.Data,
OwnerID: v.OwnerID,
RepoID: v.RepoID,
Name: v.Name,
Data: v.Data,
Description: v.Description,
}
ctx.JSON(http.StatusOK, variable)
@ -362,7 +364,7 @@ func (Action) CreateVariable(ctx *context.APIContext) {
return
}
if _, err := actions_service.CreateVariable(ctx, 0, repoID, variableName, opt.Value); err != nil {
if _, err := actions_service.CreateVariable(ctx, 0, repoID, variableName, opt.Value, opt.Description); err != nil {
if errors.Is(err, util.ErrInvalidArgument) {
ctx.APIError(http.StatusBadRequest, err)
} else {
@ -432,6 +434,7 @@ func (Action) UpdateVariable(ctx *context.APIContext) {
v.Name = opt.Name
v.Data = opt.Value
v.Description = opt.Description
if _, err := actions_service.UpdateVariableNameData(ctx, v); err != nil {
if errors.Is(err, util.ErrInvalidArgument) {
@ -491,9 +494,11 @@ func (Action) ListVariables(ctx *context.APIContext) {
variables := make([]*api.ActionVariable, len(vars))
for i, v := range vars {
variables[i] = &api.ActionVariable{
OwnerID: v.OwnerID,
RepoID: v.RepoID,
Name: v.Name,
OwnerID: v.OwnerID,
RepoID: v.RepoID,
Name: v.Name,
Data: v.Data,
Description: v.Description,
}
}

View File

@ -476,7 +476,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error)
// findWikiRepoCommit opens the wiki repo and returns the latest commit, writing to context on error.
// The caller is responsible for closing the returned repo again
func findWikiRepoCommit(ctx *context.APIContext) (*git.Repository, *git.Commit) {
wikiRepo, err := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
wikiRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
if err != nil {
if git.IsErrNotExist(err) || err.Error() == "no such file or directory" {
ctx.APIErrorNotFound(err)

View File

@ -49,7 +49,7 @@ func CreateOrUpdateSecret(ctx *context.APIContext) {
opt := web.GetForm(ctx).(*api.CreateOrUpdateSecretOption)
_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Doer.ID, 0, ctx.PathParam("secretname"), opt.Data)
_, created, err := secret_service.CreateOrUpdateSecret(ctx, ctx.Doer.ID, 0, ctx.PathParam("secretname"), opt.Data, opt.Description)
if err != nil {
if errors.Is(err, util.ErrInvalidArgument) {
ctx.APIError(http.StatusBadRequest, err)
@ -153,7 +153,7 @@ func CreateVariable(ctx *context.APIContext) {
return
}
if _, err := actions_service.CreateVariable(ctx, ownerID, 0, variableName, opt.Value); err != nil {
if _, err := actions_service.CreateVariable(ctx, ownerID, 0, variableName, opt.Value, opt.Description); err != nil {
if errors.Is(err, util.ErrInvalidArgument) {
ctx.APIError(http.StatusBadRequest, err)
} else {
@ -215,6 +215,7 @@ func UpdateVariable(ctx *context.APIContext) {
v.Name = opt.Name
v.Data = opt.Value
v.Description = opt.Description
if _, err := actions_service.UpdateVariableNameData(ctx, v); err != nil {
if errors.Is(err, util.ErrInvalidArgument) {
@ -300,10 +301,11 @@ func GetVariable(ctx *context.APIContext) {
}
variable := &api.ActionVariable{
OwnerID: v.OwnerID,
RepoID: v.RepoID,
Name: v.Name,
Data: v.Data,
OwnerID: v.OwnerID,
RepoID: v.RepoID,
Name: v.Name,
Data: v.Data,
Description: v.Description,
}
ctx.JSON(http.StatusOK, variable)
@ -345,10 +347,11 @@ func ListVariables(ctx *context.APIContext) {
variables := make([]*api.ActionVariable, len(vars))
for i, v := range vars {
variables[i] = &api.ActionVariable{
OwnerID: v.OwnerID,
RepoID: v.RepoID,
Name: v.Name,
Data: v.Data,
OwnerID: v.OwnerID,
RepoID: v.RepoID,
Name: v.Name,
Data: v.Data,
Description: v.Description,
}
}

View File

@ -284,7 +284,7 @@ func Diff(ctx *context.Context) {
)
if ctx.Data["PageIsWiki"] != nil {
gitRepo, err = gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
gitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
if err != nil {
ctx.ServerError("Repo.GitRepo.GetCommit", err)
return
@ -417,7 +417,7 @@ func Diff(ctx *context.Context) {
func RawDiff(ctx *context.Context) {
var gitRepo *git.Repository
if ctx.Data["PageIsWiki"] != nil {
wikiRepo, err := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
wikiRepo, err := gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
if err != nil {
ctx.ServerError("OpenRepository", err)
return

View File

@ -885,7 +885,7 @@ func ExcerptBlob(ctx *context.Context) {
gitRepo := ctx.Repo.GitRepo
if ctx.Data["PageIsWiki"] == true {
var err error
gitRepo, err = gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
gitRepo, err = gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
if err != nil {
ctx.ServerError("OpenRepository", err)
return

View File

@ -96,7 +96,7 @@ func findEntryForFile(commit *git.Commit, target string) (*git.TreeEntry, error)
}
func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, error) {
wikiGitRepo, errGitRepo := gitrepo.OpenWikiRepository(ctx, ctx.Repo.Repository)
wikiGitRepo, errGitRepo := gitrepo.OpenRepository(ctx, ctx.Repo.Repository.WikiStorageRepo())
if errGitRepo != nil {
ctx.ServerError("OpenRepository", errGitRepo)
return nil, nil, errGitRepo
@ -105,7 +105,7 @@ func findWikiRepoCommit(ctx *context.Context) (*git.Repository, *git.Commit, err
commit, errCommit := wikiGitRepo.GetBranchCommit(ctx.Repo.Repository.DefaultWikiBranch)
if git.IsErrNotExist(errCommit) {
// if the default branch recorded in database is out of sync, then re-sync it
gitRepoDefaultBranch, errBranch := gitrepo.GetWikiDefaultBranch(ctx, ctx.Repo.Repository)
gitRepoDefaultBranch, errBranch := gitrepo.GetDefaultBranch(ctx, ctx.Repo.Repository.WikiStorageRepo())
if errBranch != nil {
return wikiGitRepo, nil, errBranch
}

View File

@ -29,7 +29,7 @@ const (
)
func wikiEntry(t *testing.T, repo *repo_model.Repository, wikiName wiki_service.WebPath) *git.TreeEntry {
wikiRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
wikiRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo())
assert.NoError(t, err)
defer wikiRepo.Close()
commit, err := wikiRepo.GetBranchCommit("master")

View File

@ -106,7 +106,8 @@ func Variables(ctx *context.Context) {
return
}
ctx.Data["Variables"] = variables
ctx.Data["DataMaxLength"] = actions_model.VariableDataMaxLength
ctx.Data["DescriptionMaxLength"] = actions_model.VariableDescriptionMaxLength
ctx.HTML(http.StatusOK, vCtx.VariablesTemplate)
}
@ -124,7 +125,7 @@ func VariableCreate(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.EditVariableForm)
v, err := actions_service.CreateVariable(ctx, vCtx.OwnerID, vCtx.RepoID, form.Name, form.Data)
v, err := actions_service.CreateVariable(ctx, vCtx.OwnerID, vCtx.RepoID, form.Name, form.Data, form.Description)
if err != nil {
log.Error("CreateVariable: %v", err)
ctx.JSONError(ctx.Tr("actions.variables.creation.failed"))
@ -157,6 +158,7 @@ func VariableUpdate(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.EditVariableForm)
variable.Name = form.Name
variable.Data = form.Data
variable.Description = form.Description
if ok, err := actions_service.UpdateVariableNameData(ctx, variable); err != nil || !ok {
log.Error("UpdateVariable: %v", err)

View File

@ -22,12 +22,14 @@ func SetSecretsContext(ctx *context.Context, ownerID, repoID int64) {
}
ctx.Data["Secrets"] = secrets
ctx.Data["DataMaxLength"] = secret_model.SecretDataMaxLength
ctx.Data["DescriptionMaxLength"] = secret_model.SecretDescriptionMaxLength
}
func PerformSecretsPost(ctx *context.Context, ownerID, repoID int64, redirectURL string) {
form := web.GetForm(ctx).(*forms.AddSecretForm)
s, _, err := secret_service.CreateOrUpdateSecret(ctx, ownerID, repoID, form.Name, util.ReserveLineBreakForTextarea(form.Data))
s, _, err := secret_service.CreateOrUpdateSecret(ctx, ownerID, repoID, form.Name, util.ReserveLineBreakForTextarea(form.Data), form.Description)
if err != nil {
log.Error("CreateOrUpdateSecret failed: %v", err)
ctx.JSONError(ctx.Tr("secrets.creation.failed"))

View File

@ -13,7 +13,7 @@ import (
secret_service "code.gitea.io/gitea/services/secrets"
)
func CreateVariable(ctx context.Context, ownerID, repoID int64, name, data string) (*actions_model.ActionVariable, error) {
func CreateVariable(ctx context.Context, ownerID, repoID int64, name, data, description string) (*actions_model.ActionVariable, error) {
if err := secret_service.ValidateName(name); err != nil {
return nil, err
}
@ -22,7 +22,7 @@ func CreateVariable(ctx context.Context, ownerID, repoID int64, name, data strin
return nil, err
}
v, err := actions_model.InsertVariable(ctx, ownerID, repoID, name, util.ReserveLineBreakForTextarea(data))
v, err := actions_model.InsertVariable(ctx, ownerID, repoID, name, util.ReserveLineBreakForTextarea(data), description)
if err != nil {
return nil, err
}
@ -41,7 +41,7 @@ func UpdateVariableNameData(ctx context.Context, variable *actions_model.ActionV
variable.Data = util.ReserveLineBreakForTextarea(variable.Data)
return actions_model.UpdateVariableCols(ctx, variable, "name", "data")
return actions_model.UpdateVariableCols(ctx, variable, "name", "data", "description")
}
func DeleteVariableByID(ctx context.Context, variableID int64) error {

View File

@ -204,7 +204,7 @@ Loop:
return false, "", nil, &ErrWontSign{twofa}
}
case parentSigned:
gitRepo, err := gitrepo.OpenWikiRepository(ctx, repo)
gitRepo, err := gitrepo.OpenRepository(ctx, repo.WikiStorageRepo())
if err != nil {
return false, "", nil, err
}

View File

@ -49,14 +49,14 @@ func checkScriptType(ctx context.Context, logger log.Logger, autofix bool) error
func checkHooks(ctx context.Context, logger log.Logger, autofix bool) error {
if err := iterateRepositories(ctx, func(repo *repo_model.Repository) error {
results, err := gitrepo.CheckDelegateHooksForRepo(ctx, repo)
results, err := gitrepo.CheckDelegateHooks(ctx, repo)
if err != nil {
logger.Critical("Unable to check delegate hooks for repo %-v. ERROR: %v", repo, err)
return fmt.Errorf("Unable to check delegate hooks for repo %-v. ERROR: %w", repo, err)
}
if len(results) > 0 && autofix {
logger.Warn("Regenerated hooks for %s", repo.FullName())
if err := gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
logger.Critical("Unable to recreate delegate hooks for %-v. ERROR: %v", repo, err)
return fmt.Errorf("Unable to recreate delegate hooks for %-v. ERROR: %w", repo, err)
}

View File

@ -323,8 +323,9 @@ func (f *AddKeyForm) Validate(req *http.Request, errs binding.Errors) binding.Er
// AddSecretForm for adding secrets
type AddSecretForm struct {
Name string `binding:"Required;MaxSize(255)"`
Data string `binding:"Required;MaxSize(65535)"`
Name string `binding:"Required;MaxSize(255)"`
Data string `binding:"Required;MaxSize(65535)"`
Description string `binding:"MaxSize(65535)"`
}
// Validate validates the fields
@ -334,8 +335,9 @@ func (f *AddSecretForm) Validate(req *http.Request, errs binding.Errors) binding
}
type EditVariableForm struct {
Name string `binding:"Required;MaxSize(255)"`
Data string `binding:"Required;MaxSize(65535)"`
Name string `binding:"Required;MaxSize(255)"`
Data string `binding:"Required;MaxSize(65535)"`
Description string `binding:"MaxSize(65535)"`
}
func (f *EditVariableForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {

View File

@ -1253,6 +1253,8 @@ func GetDiffForRender(ctx context.Context, gitRepo *git.Repository, opts *DiffOp
if language.Has() {
diffFile.Language = language.Value()
}
} else {
checker = nil // CheckPath fails, it's not impossible to "check" anymore
}
}

View File

@ -151,7 +151,7 @@ func runPushSync(ctx context.Context, m *repo_model.PushMirror) error {
var gitRepo *git.Repository
if isWiki {
gitRepo, err = gitrepo.OpenWikiRepository(ctx, repo)
gitRepo, err = gitrepo.OpenRepository(ctx, repo.WikiStorageRepo())
} else {
gitRepo, err = gitrepo.OpenRepository(ctx, repo)
}

View File

@ -115,7 +115,7 @@ func adoptRepository(ctx context.Context, repo *repo_model.Repository, defaultBr
return fmt.Errorf("adoptRepository: path does not already exist: %s", repo.FullName())
}
if err := gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
return fmt.Errorf("createDelegateHooks: %w", err)
}

View File

@ -170,7 +170,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork
return fmt.Errorf("git update-server-info: %w", err)
}
if err = gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
if err = gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
return fmt.Errorf("createDelegateHooks: %w", err)
}

View File

@ -31,16 +31,16 @@ func SyncRepositoryHooks(ctx context.Context) error {
default:
}
if err := gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
return fmt.Errorf("SyncRepositoryHook: %w", err)
if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
return fmt.Errorf("CreateDelegateHooks: %w", err)
}
exist, err := gitrepo.IsWikiRepositoryExist(ctx, repo)
exist, err := gitrepo.IsRepositoryExist(ctx, repo.WikiStorageRepo())
if err != nil {
return fmt.Errorf("SyncRepositoryHook: %w", err)
return fmt.Errorf("IsRepositoryExist: %w", err)
}
if exist {
if err := gitrepo.CreateDelegateHooksForWiki(ctx, repo); err != nil {
return fmt.Errorf("SyncRepositoryHook: %w", err)
if err := gitrepo.CreateDelegateHooks(ctx, repo.WikiStorageRepo()); err != nil {
return fmt.Errorf("CreateDelegateHooks: %w", err)
}
}
return nil

View File

@ -265,16 +265,16 @@ func cleanUpMigrateGitConfig(ctx context.Context, repoPath string) error {
// CleanUpMigrateInfo finishes migrating repository and/or wiki with things that don't need to be done for mirrors.
func CleanUpMigrateInfo(ctx context.Context, repo *repo_model.Repository) (*repo_model.Repository, error) {
if err := gitrepo.CreateDelegateHooksForRepo(ctx, repo); err != nil {
if err := gitrepo.CreateDelegateHooks(ctx, repo); err != nil {
return repo, fmt.Errorf("createDelegateHooks: %w", err)
}
hasWiki, err := gitrepo.IsWikiRepositoryExist(ctx, repo)
hasWiki, err := gitrepo.IsRepositoryExist(ctx, repo.WikiStorageRepo())
if err != nil {
return repo, fmt.Errorf("IsWikiRepositoryExist: %w", err)
}
if hasWiki {
if err := gitrepo.CreateDelegateHooksForWiki(ctx, repo); err != nil {
if err := gitrepo.CreateDelegateHooks(ctx, repo.WikiStorageRepo()); err != nil {
return repo, fmt.Errorf("createDelegateHooks.(wiki): %w", err)
}
}

View File

@ -331,12 +331,13 @@ func changeRepositoryName(ctx context.Context, repo *repo_model.Repository, newR
return fmt.Errorf("IsRepositoryExist: %w", err)
} else if has {
return repo_model.ErrRepoAlreadyExist{
Uname: repo.Owner.Name,
Uname: repo.OwnerName,
Name: newRepoName,
}
}
if err = gitrepo.RenameRepository(ctx, repo, newRepoName); err != nil {
if err = gitrepo.RenameRepository(ctx, repo,
repo_model.StorageRepo(repo_model.RelativePath(repo.OwnerName, newRepoName))); err != nil {
return fmt.Errorf("rename repository directory: %w", err)
}

View File

@ -10,7 +10,7 @@ import (
secret_model "code.gitea.io/gitea/models/secret"
)
func CreateOrUpdateSecret(ctx context.Context, ownerID, repoID int64, name, data string) (*secret_model.Secret, bool, error) {
func CreateOrUpdateSecret(ctx context.Context, ownerID, repoID int64, name, data, description string) (*secret_model.Secret, bool, error) {
if err := ValidateName(name); err != nil {
return nil, false, err
}
@ -25,14 +25,14 @@ func CreateOrUpdateSecret(ctx context.Context, ownerID, repoID int64, name, data
}
if len(s) == 0 {
s, err := secret_model.InsertEncryptedSecret(ctx, ownerID, repoID, name, data)
s, err := secret_model.InsertEncryptedSecret(ctx, ownerID, repoID, name, data, description)
if err != nil {
return nil, false, err
}
return s, true, nil
}
if err := secret_model.UpdateSecret(ctx, s[0].ID, data); err != nil {
if err := secret_model.UpdateSecret(ctx, s[0].ID, data, description); err != nil {
return nil, false, err
}

View File

@ -43,7 +43,7 @@ func InitWiki(ctx context.Context, repo *repo_model.Repository) error {
if err := git.InitRepository(ctx, repo.WikiPath(), true, repo.ObjectFormatName); err != nil {
return fmt.Errorf("InitRepository: %w", err)
} else if err = gitrepo.CreateDelegateHooksForWiki(ctx, repo); err != nil {
} else if err = gitrepo.CreateDelegateHooks(ctx, repo.WikiStorageRepo()); err != nil {
return fmt.Errorf("createDelegateHooks: %w", err)
} else if _, _, err = git.NewCommand("symbolic-ref", "HEAD").AddDynamicArguments(git.BranchPrefix+repo.DefaultWikiBranch).RunStdString(ctx, &git.RunOpts{Dir: repo.WikiPath()}); err != nil {
return fmt.Errorf("unable to set default wiki branch to %q: %w", repo.DefaultWikiBranch, err)
@ -102,7 +102,7 @@ func updateWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model
return fmt.Errorf("InitWiki: %w", err)
}
hasDefaultBranch := gitrepo.IsWikiBranchExist(ctx, repo, repo.DefaultWikiBranch)
hasDefaultBranch := gitrepo.IsBranchExist(ctx, repo.WikiStorageRepo(), repo.DefaultWikiBranch)
basePath, err := repo_module.CreateTemporaryPath("update-wiki")
if err != nil {
@ -392,7 +392,7 @@ func ChangeDefaultWikiBranch(ctx context.Context, repo *repo_model.Repository, n
return nil
}
oldDefBranch, err := gitrepo.GetWikiDefaultBranch(ctx, repo)
oldDefBranch, err := gitrepo.GetDefaultBranch(ctx, repo.WikiStorageRepo())
if err != nil {
return fmt.Errorf("unable to get default branch: %w", err)
}
@ -400,7 +400,7 @@ func ChangeDefaultWikiBranch(ctx context.Context, repo *repo_model.Repository, n
return nil
}
gitRepo, err := gitrepo.OpenWikiRepository(ctx, repo)
gitRepo, err := gitrepo.OpenRepository(ctx, repo.WikiStorageRepo())
if errors.Is(err, util.ErrNotExist) {
return nil // no git repo on storage, no need to do anything else
} else if err != nil {

View File

@ -168,7 +168,7 @@ func TestRepository_AddWikiPage(t *testing.T) {
webPath := UserTitleToWebPath("", userTitle)
assert.NoError(t, AddWikiPage(git.DefaultContext, doer, repo, webPath, wikiContent, commitMsg))
// Now need to show that the page has been added:
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo())
require.NoError(t, err)
defer gitRepo.Close()
@ -215,7 +215,7 @@ func TestRepository_EditWikiPage(t *testing.T) {
assert.NoError(t, EditWikiPage(git.DefaultContext, doer, repo, "Home", webPath, newWikiContent, commitMsg))
// Now need to show that the page has been added:
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo())
assert.NoError(t, err)
masterTree, err := gitRepo.GetTree(repo.DefaultWikiBranch)
assert.NoError(t, err)
@ -239,7 +239,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
assert.NoError(t, DeleteWikiPage(git.DefaultContext, doer, repo, "Home"))
// Now need to show that the page has been added:
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo())
require.NoError(t, err)
defer gitRepo.Close()
@ -253,7 +253,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
func TestPrepareWikiFileName(t *testing.T) {
unittest.PrepareTestEnv(t)
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
gitRepo, err := gitrepo.OpenWikiRepository(git.DefaultContext, repo)
gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo.WikiStorageRepo())
require.NoError(t, err)
defer gitRepo.Close()

View File

@ -82,7 +82,7 @@
<tbody>
{{range $key, $value := .PackageDescriptor.Metadata.Labels}}
<tr>
<td class="top aligned">{{$key}}</td>
<td class="tw-align-top">{{$key}}</td>
<td class="tw-break-anywhere">{{$value}}</td>
</tr>
{{end}}

View File

@ -63,13 +63,11 @@
{{if and (not .PageIsOrgSettingsLabels) (.OrgLabels)}}
<li class="item">
<div class="ui grid middle aligned">
<div class="ten wide column">
{{ctx.Locale.Tr "repo.org_labels_desc"}}
{{if .IsOrganizationOwner}}
<a href="{{.OrganizationLink}}/settings/labels">({{ctx.Locale.Tr "repo.org_labels_desc_manage"}})</a>:
{{end}}
</div>
<div>{{/* parent is flex, so use block here to keep sentence spaces */}}
{{ctx.Locale.Tr "repo.org_labels_desc"}}
{{if .IsOrganizationOwner}}
<a href="{{.OrganizationLink}}/settings/labels">({{ctx.Locale.Tr "repo.org_labels_desc_manage"}})</a>:
{{end}}
</div>
</li>

View File

@ -1,8 +1,6 @@
<div class="divider"></div>
<div class="ui equal width compact grid">
{{$issueReferenceLink := printf "%s#%d" .Issue.Repo.FullName .Issue.Index}}
<div class="row tw-items-center" data-tooltip-content="{{$issueReferenceLink}}">
<span class="text column truncate">{{ctx.Locale.Tr "repo.issues.reference_link" $issueReferenceLink}}</span>
<button class="ui two wide button column tw-p-2" data-clipboard-text="{{$issueReferenceLink}}">{{svg "octicon-copy" 14}}</button>
</div>
{{$issueReferenceLink := printf "%s#%d" .Issue.Repo.FullName .Issue.Index}}
<div class="flex-text-block" data-tooltip-content="{{$issueReferenceLink}}">
<span class="tw-flex-1 gt-ellipsis">{{ctx.Locale.Tr "repo.issues.reference_link" $issueReferenceLink}}</span>
<button class="ui compact tiny icon button" data-clipboard-text="{{$issueReferenceLink}}">{{svg "octicon-copy" 14}}</button>
</div>

View File

@ -1,5 +1,5 @@
<div class="flex-text-block tw-mb-2">
<button class="ui compact tiny icon button"
<div class="flex-text-block repo-button-row">
<button class="ui compact basic icon button"
data-global-click="onRepoViewFileTreeToggle" data-toggle-action="hide"
data-tooltip-content="{{ctx.Locale.Tr "repo.diff.hide_file_tree"}}">
{{svg "octicon-sidebar-expand"}}

View File

@ -14,19 +14,21 @@
{{$entry := $item.Entry}}
{{$commit := $item.Commit}}
{{$submoduleFile := $item.SubmoduleFile}}
<div class="repo-file-cell name {{if not $commit}}notready{{end}}">
<div class="repo-file-cell name muted-links {{if not $commit}}notready{{end}}">
{{ctx.RenderUtils.RenderFileIcon $entry}}
{{if $entry.IsSubModule}}
{{$submoduleLink := $submoduleFile.SubmoduleWebLink ctx}}
{{if $submoduleLink}}
<a class="muted" href="{{$submoduleLink.RepoWebLink}}">{{$entry.Name}}</a> <span class="at">@</span> <a href="{{$submoduleLink.CommitWebLink}}">{{ShortSha $submoduleFile.RefID}}</a>
<a class="entry-name" href="{{$submoduleLink.RepoWebLink}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
@ <a class="text primary" href="{{$submoduleLink.CommitWebLink}}">{{ShortSha $submoduleFile.RefID}}</a>
{{else}}
{{$entry.Name}} <span class="at">@</span> {{ShortSha $submoduleFile.RefID}}
<span class="entry-name" title="{{$entry.Name}}">{{$entry.Name}}</span>
@ {{ShortSha $submoduleFile.RefID}}
{{end}}
{{else}}
{{if $entry.IsDir}}
{{$subJumpablePathName := $entry.GetSubJumpablePathName}}
<a class="muted" href="{{$.TreeLink}}/{{PathEscapeSegments $subJumpablePathName}}" title="{{$subJumpablePathName}}">
<a class="entry-name" href="{{$.TreeLink}}/{{PathEscapeSegments $subJumpablePathName}}" title="{{$subJumpablePathName}}">
{{$subJumpablePathFields := StringUtils.Split $subJumpablePathName "/"}}
{{$subJumpablePathFieldLast := (Eval (len $subJumpablePathFields) "-" 1)}}
{{if eq $subJumpablePathFieldLast 0}}
@ -37,7 +39,7 @@
{{end}}
</a>
{{else}}
<a class="muted" href="{{$.TreeLink}}/{{PathEscapeSegments $entry.Name}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
<a class="entry-name" href="{{$.TreeLink}}/{{PathEscapeSegments $entry.Name}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
{{end}}
{{end}}
</div>

View File

@ -22,6 +22,9 @@
<div class="flex-item-title">
{{.Name}}
</div>
<div class="flex-item-body">
{{if .Description}}{{.Description}}{{else}}-{{end}}
</div>
<div class="flex-item-body">
******
</div>
@ -72,9 +75,20 @@
<textarea required
id="secret-data"
name="data"
maxlength="{{.DataMaxLength}}"
placeholder="{{ctx.Locale.Tr "secrets.creation.value_placeholder"}}"
></textarea>
</div>
<div class="field">
<label for="secret-description">{{ctx.Locale.Tr "secrets.creation.description"}}</label>
<textarea
id="secret-description"
name="description"
rows="2"
maxlength="{{.DescriptionMaxLength}}"
placeholder="{{ctx.Locale.Tr "secrets.creation.description_placeholder"}}"
></textarea>
</div>
</div>
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
</form>

View File

@ -7,6 +7,7 @@
data-modal-header="{{ctx.Locale.Tr "actions.variables.creation"}}"
data-modal-dialog-variable-name=""
data-modal-dialog-variable-data=""
data-modal-dialog-variable-description=""
>
{{ctx.Locale.Tr "actions.variables.creation"}}
</button>
@ -24,6 +25,9 @@
<div class="flex-item-title">
{{.Name}}
</div>
<div class="flex-item-body">
{{if .Description}}{{.Description}}{{else}}-{{end}}
</div>
<div class="flex-item-body">
{{.Data}}
</div>
@ -39,6 +43,7 @@
data-modal-header="{{ctx.Locale.Tr "actions.variables.edit"}}"
data-modal-dialog-variable-name="{{.Name}}"
data-modal-dialog-variable-data="{{.Data}}"
data-modal-dialog-variable-description="{{.Description}}"
>
{{svg "octicon-pencil"}}
</button>
@ -82,9 +87,20 @@
<textarea required
name="data"
id="dialog-variable-data"
maxlength="{{.DataMaxLength}}"
placeholder="{{ctx.Locale.Tr "secrets.creation.value_placeholder"}}"
></textarea>
</div>
<div class="field">
<label for="dialog-variable-description">{{ctx.Locale.Tr "secrets.creation.description"}}</label>
<textarea
name="description"
id="dialog-variable-description"
rows="2"
maxlength="{{.DescriptionMaxLength}}"
placeholder="{{ctx.Locale.Tr "secrets.creation.description_placeholder"}}"
></textarea>
</div>
</div>
{{template "base/modal_actions_confirm" (dict "ModalButtonTypes" "confirm")}}
</form>

View File

@ -19325,6 +19325,11 @@
"type": "string",
"x-go-name": "Data"
},
"description": {
"description": "the description of the variable",
"type": "string",
"x-go-name": "Description"
},
"name": {
"description": "the name of the variable",
"type": "string",
@ -20988,6 +20993,11 @@
"description": "Data of the secret to update",
"type": "string",
"x-go-name": "Data"
},
"description": {
"description": "Description of the secret to update",
"type": "string",
"x-go-name": "Description"
}
},
"x-go-package": "code.gitea.io/gitea/modules/structs"
@ -21498,6 +21508,11 @@
"value"
],
"properties": {
"description": {
"description": "Description of the variable to create",
"type": "string",
"x-go-name": "Description"
},
"value": {
"description": "Value of the variable to create",
"type": "string",
@ -25459,6 +25474,11 @@
"format": "date-time",
"x-go-name": "Created"
},
"description": {
"description": "the secret's description",
"type": "string",
"x-go-name": "Description"
},
"name": {
"description": "the secret's name",
"type": "string",
@ -26034,6 +26054,11 @@
"value"
],
"properties": {
"description": {
"description": "Description of the variable to update",
"type": "string",
"x-go-name": "Description"
},
"name": {
"description": "New name for the variable. If the field is empty, the variable name won't be updated.",
"type": "string",

View File

@ -10,12 +10,12 @@
<div class="inline field tw-text-center required">
<div id="captcha" data-captcha-type="g-recaptcha" class="g-recaptcha-style" data-sitekey="{{.RecaptchaSitekey}}"></div>
</div>
<script src='{{URLJoin .RecaptchaURL "api.js"}}'></script>
<script defer src='{{URLJoin .RecaptchaURL "api.js"}}'></script>
{{else if eq .CaptchaType "hcaptcha"}}
<div class="inline field tw-text-center required">
<div id="captcha" data-captcha-type="h-captcha" class="h-captcha-style" data-sitekey="{{.HcaptchaSitekey}}"></div>
</div>
<script src='https://hcaptcha.com/1/api.js'></script>
<script defer src='https://hcaptcha.com/1/api.js'></script>
{{else if eq .CaptchaType "mcaptcha"}}
<div class="inline field tw-text-center">
<div class="m-captcha-style" id="mcaptcha__widget-container"></div>
@ -25,5 +25,5 @@
<div class="inline field tw-text-center">
<div id="captcha" data-captcha-type="cf-turnstile" data-sitekey="{{.CfTurnstileSitekey}}"></div>
</div>
<script src='https://challenges.cloudflare.com/turnstile/v0/api.js'></script>
<script defer src='https://challenges.cloudflare.com/turnstile/v0/api.js'></script>
{{end}}{{end}}

View File

@ -81,7 +81,7 @@
{{end}}
{{else}}
{{if .Repos}}
<div class="ui middle aligned divided list">
<div class="ui list">
{{range .Repos}}
<div class="item">
<div class="content flex-text-block">

View File

@ -27,21 +27,21 @@ func TestActionsVariables(t *testing.T) {
require.NoError(t, db.DeleteAllRecords("action_variable"))
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
_, _ = actions_model.InsertVariable(ctx, user2.ID, 0, "VAR", "user2-var")
_, _ = actions_model.InsertVariable(ctx, user2.ID, 0, "VAR", "user2-var", "user2-var-description")
user2Var := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{OwnerID: user2.ID, Name: "VAR"})
userWebURL := "/user/settings/actions/variables"
org3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3, Type: user_model.UserTypeOrganization})
_, _ = actions_model.InsertVariable(ctx, org3.ID, 0, "VAR", "org3-var")
_, _ = actions_model.InsertVariable(ctx, org3.ID, 0, "VAR", "org3-var", "org3-var-description")
org3Var := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{OwnerID: org3.ID, Name: "VAR"})
orgWebURL := "/org/org3/settings/actions/variables"
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
_, _ = actions_model.InsertVariable(ctx, 0, repo1.ID, "VAR", "repo1-var")
_, _ = actions_model.InsertVariable(ctx, 0, repo1.ID, "VAR", "repo1-var", "repo1-var-description")
repo1Var := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{RepoID: repo1.ID, Name: "VAR"})
repoWebURL := "/user2/repo1/settings/actions/variables"
_, _ = actions_model.InsertVariable(ctx, 0, 0, "VAR", "global-var")
_, _ = actions_model.InsertVariable(ctx, 0, 0, "VAR", "global-var", "global-var-description")
globalVar := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionVariable{Name: "VAR", Data: "global-var"})
adminWebURL := "/-/admin/actions/variables"

View File

@ -73,6 +73,33 @@ func TestAPIRepoSecrets(t *testing.T) {
}
})
t.Run("CreateWithDescription", func(t *testing.T) {
cases := []struct {
Name string
Description string
ExpectedStatus int
}{
{
Name: "no_description",
Description: "",
ExpectedStatus: http.StatusCreated,
},
{
Name: "description",
Description: "some description",
ExpectedStatus: http.StatusCreated,
},
}
for _, c := range cases {
req := NewRequestWithJSON(t, "PUT", fmt.Sprintf("/api/v1/repos/%s/actions/secrets/%s", repo.FullName(), c.Name), api.CreateOrUpdateSecretOption{
Data: "data",
Description: c.Description,
}).AddTokenAuth(token)
MakeRequest(t, req, c.ExpectedStatus)
}
})
t.Run("Update", func(t *testing.T) {
name := "update_secret"
url := fmt.Sprintf("/api/v1/repos/%s/actions/secrets/%s", repo.FullName(), name)

View File

@ -285,7 +285,6 @@
.markup table {
display: block;
width: 100%;
width: max-content;
max-width: 100%;
overflow: auto;
}

View File

@ -393,28 +393,6 @@
margin-right: 2.5rem;
}
.ui[class*="middle aligned"].grid > .column:not(.row),
.ui[class*="middle aligned"].grid > .row > .column,
.ui.grid > [class*="middle aligned"].row > .column,
.ui.grid > [class*="middle aligned"].column:not(.row),
.ui.grid > .row > [class*="middle aligned"].column {
flex-direction: column;
vertical-align: middle;
align-self: center !important;
}
.ui[class*="equal width"].grid > .column:not(.row),
.ui[class*="equal width"].grid > .row > .column,
.ui.grid > [class*="equal width"].row > .column {
display: inline-block;
flex-grow: 1;
}
.ui[class*="equal width"].grid > .wide.column,
.ui[class*="equal width"].grid > .row > .wide.column,
.ui.grid > [class*="equal width"].row > .wide.column {
flex-grow: 0;
}
@media only screen and (max-width: 767.98px) {
.ui[class*="mobile reversed"].grid,
.ui[class*="mobile reversed"].grid > .row,

View File

@ -152,16 +152,6 @@
}
}
.ui.table[class*="top aligned"],
.ui.table [class*="top aligned"] {
vertical-align: top;
}
.ui.table[class*="middle aligned"],
.ui.table [class*="middle aligned"] {
vertical-align: middle;
}
.ui.table th.collapsing,
.ui.table td.collapsing {
width: 1px;

View File

@ -14,10 +14,6 @@
}
}
#repo-files-table .repo-file-cell.name .svg {
margin-right: 2px;
}
#repo-files-table .svg.octicon-file-directory-fill,
#repo-files-table .svg.octicon-file-submodule {
color: var(--color-primary);
@ -70,11 +66,25 @@
}
#repo-files-table .repo-file-cell.name {
display: flex;
align-items: center;
gap: 0.5em;
overflow: hidden;
}
#repo-files-table .repo-file-cell.name > a,
#repo-files-table .repo-file-cell.name > span {
flex-shrink: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#repo-files-table .repo-file-cell.name .entry-name {
flex-shrink: 1;
min-width: 3em;
}
@media (max-width: 767.98px) {
#repo-files-table .repo-file-cell.name {
max-width: 35vw;

View File

@ -55,7 +55,7 @@
}
.repo-view-container .repo-view-file-tree-container {
flex: 0 1 15%;
flex: 0 0 15%;
min-width: 0;
max-height: 100vh;
}

View File

@ -1499,16 +1499,6 @@
width: 100%;
}
/*--------------------
Equal Width
---------------------*/
.ui[class*="equal width"].form .fields > .field,
.ui.form [class*="equal width"].fields > .field {
width: 100%;
flex: 1 1 auto;
}
/*--------------------
Inline Fields
---------------------*/

View File

@ -116,12 +116,7 @@
align-self: start;
max-width: 100%;
}
.ui.modal > [class*="top aligned"] {
align-self: start;
}
.ui.modal > [class*="middle aligned"] {
align-self: center;
}
.ui.modal > [class*="stretched"] {
align-self: stretch;
}
@ -258,7 +253,7 @@
padding: 1rem 0 !important;
box-shadow: none;
}
/* Let Buttons Stack */
.ui.modal > .actions {
padding: 1rem 1rem 0rem !important;

View File

@ -20,7 +20,7 @@ test('toAbsoluteLocaleDate', () => {
// test different timezone
const oldTZ = process.env.TZ;
process.env.TZ = 'America/New_York';
expect(new Date('2024-03-15').toLocaleString()).toEqual('3/14/2024, 8:00:00 PM');
expect(toAbsoluteLocaleDate('2024-03-15')).toEqual('3/15/2024, 12:00:00 AM');
expect(new Date('2024-03-15').toLocaleString('en-US')).toEqual('3/14/2024, 8:00:00 PM');
expect(toAbsoluteLocaleDate('2024-03-15', 'en-US')).toEqual('3/15/2024, 12:00:00 AM');
process.env.TZ = oldTZ;
});