Merge branch 'main' into pacman-packages

This commit is contained in:
Danila Fominykh 2023-07-25 21:53:07 +03:00 committed by GitHub
commit 523e8269f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 598 additions and 146 deletions

View File

@ -22,12 +22,11 @@ import (
"xorm.io/xorm"
)
// CmdDoctor represents the available doctor sub-command.
var CmdDoctor = &cli.Command{
Name: "doctor",
var cmdDoctorCheck = &cli.Command{
Name: "check",
Usage: "Diagnose and optionally fix problems",
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
Action: runDoctor,
Action: runDoctorCheck,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "list",
@ -51,7 +50,7 @@ var CmdDoctor = &cli.Command{
},
&cli.StringFlag{
Name: "log-file",
Usage: `Name of the log file (default: "doctor.log"). Set to "-" to output to stdout, set to "" to disable`,
Usage: `Name of the log file (no verbose log output by default). Set to "-" to output to stdout`,
},
&cli.BoolFlag{
Name: "color",
@ -59,8 +58,18 @@ var CmdDoctor = &cli.Command{
Usage: "Use color for outputted information",
},
},
}
// CmdDoctor represents the available doctor sub-command.
var CmdDoctor = &cli.Command{
Name: "doctor",
Usage: "Diagnose and optionally fix problems",
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
Subcommands: []*cli.Command{
cmdDoctorCheck,
cmdRecreateTable,
cmdDoctorConvert,
},
}
@ -133,16 +142,9 @@ func setupDoctorDefaultLogger(ctx *cli.Context, colorize bool) {
setupConsoleLogger(log.FATAL, log.CanColorStderr, os.Stderr)
logFile := ctx.String("log-file")
if !ctx.IsSet("log-file") {
logFile = "doctor.log"
}
if len(logFile) == 0 {
// if no doctor log-file is set, do not show any log from default logger
return
}
if logFile == "-" {
if logFile == "" {
return // if no doctor log-file is set, do not show any log from default logger
} else if logFile == "-" {
setupConsoleLogger(log.TRACE, colorize, os.Stdout)
} else {
logFile, _ = filepath.Abs(logFile)
@ -156,7 +158,7 @@ func setupDoctorDefaultLogger(ctx *cli.Context, colorize bool) {
}
}
func runDoctor(ctx *cli.Context) error {
func runDoctorCheck(ctx *cli.Context) error {
stdCtx, cancel := installSignals()
defer cancel()

View File

@ -13,15 +13,15 @@ import (
"github.com/urfave/cli/v2"
)
// CmdConvert represents the available convert sub-command.
var CmdConvert = &cli.Command{
// cmdDoctorConvert represents the available convert sub-command.
var cmdDoctorConvert = &cli.Command{
Name: "convert",
Usage: "Convert the database",
Description: "A command to convert an existing MySQL database from utf8 to utf8mb4 or MSSQL database from varchar to nvarchar",
Action: runConvert,
Action: runDoctorConvert,
}
func runConvert(ctx *cli.Context) error {
func runDoctorConvert(ctx *cli.Context) error {
stdCtx, cancel := installSignals()
defer cancel()

View File

@ -11,6 +11,7 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"github.com/urfave/cli/v2"
)
@ -23,9 +24,13 @@ func cmdHelp() *cli.Command {
Usage: "Shows a list of commands or help for one command",
ArgsUsage: "[command]",
Action: func(c *cli.Context) (err error) {
args := c.Args()
if args.Present() {
err = cli.ShowCommandHelp(c, args.First())
lineage := c.Lineage() // The order is from child to parent: help, doctor, Gitea, {Command:nil}
targetCmdIdx := 0
if c.Command.Name == "help" {
targetCmdIdx = 1
}
if lineage[targetCmdIdx+1].Command != nil {
err = cli.ShowCommandHelp(lineage[targetCmdIdx+1], lineage[targetCmdIdx].Command.Name)
} else {
err = cli.ShowAppHelp(c)
}
@ -94,9 +99,8 @@ func prepareSubcommandWithConfig(command *cli.Command, globalFlags []cli.Flag) {
func prepareWorkPathAndCustomConf(action cli.ActionFunc) func(ctx *cli.Context) error {
return func(ctx *cli.Context) error {
var args setting.ArgWorkPathAndCustomConf
ctxLineage := ctx.Lineage()
for i := len(ctxLineage) - 1; i >= 0; i-- {
curCtx := ctxLineage[i]
// from children to parent, check the global flags
for _, curCtx := range ctx.Lineage() {
if curCtx.IsSet("work-path") && args.WorkPath == "" {
args.WorkPath = curCtx.String("work-path")
}
@ -159,7 +163,6 @@ func NewMainApp() *cli.App {
CmdAdmin,
CmdMigrate,
CmdKeys,
CmdConvert,
CmdDoctor,
CmdManager,
CmdEmbedded,
@ -170,6 +173,10 @@ func NewMainApp() *cli.App {
cmdHelp(), // the "help" sub-command was used to show the more information for "work path" and "custom config"
}
cmdConvert := util.ToPointer(*cmdDoctorConvert)
cmdConvert.Hidden = true // still support the legacy "./gitea doctor" by the hidden sub-command, remove it in next release
subCmdWithConfig = append(subCmdWithConfig, cmdConvert)
// these sub-commands do not need the config file, and they do not depend on any path or environment variable.
subCmdStandalone := []*cli.Command{
CmdCert,

View File

@ -388,35 +388,18 @@ NB: Gitea must be running for this command to succeed.
Migrates the database. This command can be used to run other commands before starting the server for the first time.
This command is idempotent.
### convert
### doctor check
Converts an existing MySQL database from utf8 to utf8mb4.
Diagnose and potentially fix problems with the current Gitea instance.
Several checks are run by default, but additional ones can be run:
### doctor
- `gitea doctor check --list` - will list all the available checks
- `gitea doctor check --all` - will run all available checks
- `gitea doctor check --default` - will run the default checks
- `gitea doctor check --run [check(s),]...` - will run the named checks
Diagnose the problems of current Gitea instance according the given configuration.
Currently there are a check list below:
- Check if OpenSSH authorized_keys file id correct
When your Gitea instance support OpenSSH, your Gitea instance binary path will be written to `authorized_keys`
when there is any public key added or changed on your Gitea instance.
Sometimes if you moved or renamed your Gitea binary when upgrade and you haven't run `Update the '.ssh/authorized_keys' file with Gitea SSH keys. (Not needed for the built-in SSH server.)` on your Admin Panel. Then all pull/push via SSH will not be work.
This check will help you to check if it works well.
For contributors, if you want to add more checks, you can write a new function like `func(ctx *cli.Context) ([]string, error)` and
append it to `doctor.go`.
```go
var checklist = []check{
{
title: "Check if OpenSSH authorized_keys file id correct",
f: runDoctorLocationMoved,
},
// more checks please append here
}
```
This function will receive a command line context and return a list of details about the problems or error.
Some problems can be automatically fixed by passing the `--fix` option.
Extra logging can be set with `--log-file=...`.
#### doctor recreate-table
@ -448,6 +431,10 @@ gitea doctor recreate-table
It is highly recommended to back-up your database before running these commands.
### doctor convert
Converts a MySQL database from utf8 to utf8mb4 or a MSSQL database from varchar to nvarchar.
### manager
Manage running server operations:

View File

@ -361,32 +361,18 @@ AuthorizedKeysCommand /path/to/gitea keys -e git -u %u -t %t -k %k
迁移数据库。该命令可用于在首次启动服务器之前运行其他命令。此命令是幂等的。
### convert
### doctor check
将现有的 MySQL 数据库从 utf8 转换为 utf8mb4。
对 Gitea 实例进行诊断,可以修复一些可修复的问题。
默认只运行部分检查,额外的检查可以参考:
### doctor
- `gitea doctor check --list` - 列出所有可用的检查
- `gitea doctor check --all` - 运行所有可用的检查
- `gitea doctor check --default` - 运行默认的检查
- `gitea doctor check --run [check(s),]...` - 运行指定的名字的检查
根据给定的配置诊断当前 Gitea 实例的问题。目前有以下检查清单:
- 检查 OpenSSH 的 authorized_keys 文件是否正确
当您的 Gitea 实例支持 OpenSSH 时,当您的 Gitea 实例添加或更改任何公钥时Gitea 实例的二进制路径将被写入 `authorized_keys` 文件。
有时,如果您在升级时移动或重命名了 Gitea 二进制文件,并且您没有在管理面板上运行“使用 Gitea 的 SSH 密钥更新「.ssh/authorized_keys」文件”操作。那么通过 SSH 的所有拉取/推送操作将无法正常工作。
此检查将帮助您检查它是否正常工作。
对于贡献者,如果您想添加更多的检查项,您可以编写一个新的函数,如 `func(ctx *cli.Context) ([]string, error)`,并将其追加到 `doctor.go` 文件中。
```go
var checklist = []check{
{
title: "Check if OpenSSH authorized_keys file id correct",
f: runDoctorLocationMoved,
},
// more checks please append here
}
```
此函数将接收一个命令行上下文,并返回有关问题或错误的详细信息列表。
有些问题可以通过设置 `--fix` 选项进行自动修复。
额外的日志可以通过 `--log-file=...` 进行设置。
#### doctor recreate-table
@ -416,6 +402,10 @@ gitea doctor recreate-table
强烈建议在运行这些命令之前备份您的数据库。
### doctor convert
将现有的 MySQL 数据库从 utf8 转换为 utf8mb4或者把 MSSQL 数据库从 varchar 转换为 nvarchar。
### manager
管理运行中的服务器操作:

View File

@ -17,6 +17,262 @@ menu:
# 认证
## 轻量级目录访问协议Lightweight Directory Access ProtocolLDAP
通过BindDN的LDAP和简单认证方式LDAP共享以下字段:
- 认证名称 **(必选)**
- 分配给新授权方法的名称。
- 主机名 **(必选)**
- LDAP 服务的主机地址.
- 例如:`mydomain.com`
- 端口号 **(必选)**
- LDAP 服务的端口号.
- 例如: LDAP `389`/ LDAPs `636`
- 安全协议 (可选)
- 连接LDAP服务器时是否使用TLS协议。
- 管理员过滤规则 (可选)
- 一个LDAP过滤器用于指定哪些用户应该被赋予管理员特权。如果用户帐户符合过滤器条件则该用户将被授予管理员权限。
- 示例:`(objectClass=adminAccount)`
- 适用于Microsoft Active DirectoryAD的示例:`memberOf=CN=admin-group,OU=example,DC=example,DC=org`
- 用户名属性(可选)
- 用户LDAP记录中包含用户名称的属性。在第一次成功登录后将使用指定的属性值作为新的Gitea账户用户名。若留空则使用登录表单上提供的用户名。
- 当提供的登录名与多个属性匹配时这一选项非常有用但是只有一个特定属性应该用于Gitea账户名称请参阅"用户过滤器"。
- 示例:uid
- 适用于Microsoft Active DirectoryAD的示例:`sAMAccountName`
- 名字属性(可选)
- 用户LDAP记录中包含用户名字的属性。将用于填充他们的账户信息。
- 示例:givenName
- 姓氏属性(可选)
- 用户LDAP记录中包含用户姓氏的属性。将用于填充他们的账户信息。
- 示例:`sn`
- 电子邮件属性 **(必选)**
- 用户LDAP记录中包含用户电子邮件地址的属性。将用于填充他们的账户信息。
- 示例:`mail`
### LDAP(via BindDN)
需要额外设置以下字段:
- 绑定DN (可选)
- 搜索用户时绑定到LDAP服务器的DN。这可以留空以执行匿名搜索。
- 示例: `cn=Search,dc=mydomain,dc=com`
- 绑定密码 (可选)
- 上述指定的Bind DN绑定区别名的密码如果有的话。注意该密码在服务器上使用SECRET_KEY进行加密存储。仍然建议确保Bind DN具有尽可能少的权限。
- 用户搜索基准 **(必选)**
- 这是用于搜索用户帐户的LDAP基础路径.
- 示例: `ou=Users,dc=mydomain,dc=com`
- 用户过滤规则 **(必选)**
- LDAP 过滤器声明如何查找试图进行身份验证的用户记录
`%[1]s`匹配参数将替换为登录表单中给出的登录名
- 示例: `(&(objectClass=posixAccount)(|(uid=%[1]s)(mail=%[1]s)))`
- 示例 for Microsoft Active Directory (AD): `(&(objectCategory=Person)(memberOf=CN=user-group,OU=example,DC=example,DC=org)(sAMAccountName=%s)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))`
- 如需多次替换,应使用 `%[1]s`,例如在将提供的登录名与多个属性(如用户标识符、电子邮件甚至电话号码)进行匹配时。
- 示例: `(&(objectClass=Person)(|(uid=%[1]s)(mail=%[1]s)(mobile=%[1]s)))`
- 启用用户同步
- 这个选项启用了一个周期性任务用于将Gitea用户与LDAP服务器进行同步。默认的同步周期是每24小时
但您可以在app.ini文件中进行更改。
有关此部分的详细说明,请参阅[sample
app.ini](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini)
的_cron.sync_external_users_ 部分的注释。前面提到的_User Search Base_和_User Filter_
设置将限制哪些用户可以使用Gitea以及哪些用户将被同步。
在初始运行任务时将根据给定的设置创建所有与LDAP匹配的用户因此在使用大型企业LDAP目录时需要小心。
### LDAP(simple auth)
需要额外设置以下字段:
- 用户DN **(必选)**
- 用作用户 DN 的模板。匹配参数 `%s` 将替换为登录表单中的登录名。
- 示例: `cn=%s,ou=Users,dc=mydomain,dc=com`
- 示例: `uid=%s,ou=Users,dc=mydomain,dc=com`
- 用户搜索基准 (可选)
- 用户搜索基准声明哪些用户帐户将被搜索.
- 示例: `ou=Users,dc=mydomain,dc=com`
- 用户过滤规则 **(必选)**
- LDAP 过滤器声明何时允许用户登录
`%[1]s`匹配参数将替换为登录表单中给出的登录名。
- 示例: `(&(objectClass=posixAccount)(|(cn=%[1]s)(mail=%[1]s)))`
- 示例: `(&(objectClass=posixAccount)(|(uid=%[1]s)(mail=%[1]s)))`
### 使用LDAP验证分组成员
使用以下字段:
- 群组搜索基础DN(可选)
- 组使用的 LDAP DN。
- 示例: `ou=group,dc=mydomain,dc=com`
- 组名过滤器 (可选)
- LDAP 过滤器,声明如何在上述 DN 中查找有效组。
- 示例: `(|(cn=gitea_users)(cn=admins))`
- 组中的用户属性 (可选)
- 组中列出了哪个用户的 LDAP 属性。
- 示例: `uid`
- 用户组属性 (可选)
- 哪个组的 LDAP 属性包含一个高于用户属性名称的数组。
- 示例: `memberUid`
## 可插拔式认证模块(Pluggable Authentication Module,PAM)
这个过程启用了PAMPluggable Authentication Modules认证。用户仍然可以通过用户管理手动添加到系统中。
PAM提供了一种机制通过对用户进行PAM认证来自动将其添加到当前数据库中。为了与普通的Linux密码一起使用
运行Gitea的用户还必须具有对`/etc/shadow`的读取权限,以便在使用公钥登录时检查账户的有效性。
**注意**:如果用户已将SSH公钥添加到Gitea中使用这些密钥可能会绕过登录检查系统。因此
如果您希望禁用使用PAM进行身份验证的用户应该在Gitea中手动禁用该账户使用内置的用户管理功能。
1. 配置和安装准备.
- 建议您创建一个管理用户.
- 建议取消自动注册.
1. 一旦数据库已初始化完成,使用新创建的管理员账户登录.
1. 导航至用户设置(右上角的图标),然后选择
`Site Administration` -> `Authentication Sources`, 并选择
`Add Authentication Source`.
1. 填写字段如下:
- 认证类型:`PAM`。
- 名称:任何有效的值都可以,如果您愿意,可以使用"System Authentication"。
- PAM服务名称:从/etc/pam.d/目录下选择适用于所需认证的正确文件[^1]。
- PAM电子邮件域:用户认证时要附加的电子邮件后缀。例如如果登录系统期望一个名为gituse的用户
并且将此字段设置为mail.com那么Gitea在验证一个GIT实例的用户时将期望user emai字段为gituser@mail.com[^2]。
**Note**: PAM 支持通过[build-time flags](https://docs.gitea.io/en-us/install-from-source/#build)添加,
而官方提供的二进制文件通常不会默认启用此功能。PAM需要确保系统上有必要的libpam动态库并且编译器可以访问必要的PAM开发头文件。
[^1]: 例如在Debian "Bullseye"上使用标准Linux登录可以使用`common-session-noninteractive`。这个值对于其他版本的Debian
包括Ubuntu和Mint可能也是有效的请查阅您所使用发行版的文档以确认。
[^2]: **PAM的必选项** 请注意:在上面的示例中,用户将作为`gituser`而不是`gituser@mail.com`登录到Gitea的Web界面。
## 简单邮件传输协议(Simple Mail Transfer Protocol,SMTP)
此选项允许 Gitea 以 Gitea 用户身份登录 SMTP 主机。请设置以下字段:
- 身份验证名称 **(必选)**
- 分配给新授权方法的名称
- SMTP 验证类型 **(必选)**
- 用于连接 SMTP 主机的验证类型plain 或 login
- 主机名 **(必选)**
- SMTP 服务的主机地址
- 例如:`smtp.mydomain.com`
- 端口号 **(必选)**
- SMTP 服务的端口号
- 例如: `587`
- 允许的域名
- 如果使用公共 SMTP 主机或有多个域的 SMTP 主机,限制哪些域可以登录
限制哪些域可以登录。
- 示例: `gitea.io,mydomain.com,mydomain2.com`
- 强制使用 SMTPS
- 默认情况下将使用SMTPS连接到端口465.如果您希望将smtp用于其他端口自行设置
- 否则,如果服务器提供' STARTTLS '扩展名,则将使用此扩展名
- 跳过 TLS 验证
- 禁用 TLS 验证身份.
- 该认证源处于激活状态
- 启用或禁用此身份验证源
## FreeIPA
- 要使用 FreeIPA 凭据登录 Gitea需要为 Gitea 创建一个绑定帐户。
创建一个绑定帐户:
- 在FreeIPA服务器上创建一个gitea.ldif文件并将`dc=example,dc=com`替换为您的`dn`,然后提供一个适当安全的密码。
```sh
dn: uid=gitea,cn=sysaccounts,cn=etc,dc=example,dc=com
changetype: add
objectclass: account
objectclass: simplesecurityobject
uid: gitea
userPassword: secure password
passwordExpirationTime: 20380119031407Z
nsIdleTimeout: 0
```
- 导入LDIF文件如果需要请将localhost更改为IPA服务器。系统会提示您输入Directory Manager的密码。:
```sh
ldapmodify -h localhost -p 389 -x -D \
"cn=Directory Manager" -W -f gitea.ldif
```
- 为`gitea_users`添加IPA组:
```sh
ipa group-add --desc="Gitea Users" gitea_users
```
- **提示**:对于IPA凭证错误运行' kinit admin '并提供域管理帐户密码.
- 以管理员身份登录Gitea点击Admin Panel下的`Authentication`。然后单击`Add New Source`并填写详细信息,更改所有适当的地方。
## SPNEGO with SSPI (Kerberos/NTLM, for Windows only)
Gitea支持通过Windows内置的安全支持提供程序接口Security Support Provider InterfaceSSPI实现SPNEGO单点登录认证由RFC4559定义的方案用于服务器的Web部分。SSPI仅在Windows环境中工作即当服务器和客户端都在Windows操作系统上运行时。
在激活SSPI单点登录认证SSO之前您需要准备您的环境:
- 在Active Directory中创建一个单独的用户账户gitea.exe 进程将在该账户下运行例如在domain.local域下创建一个名为user的账户:
- 为运行gitea.exe的主机创建一个服务主体名称Service Principal NameSPN其类别为HTTP:
- 以特权域用户例如域管理员的身份启动“命令提示符”或“PowerShell”。
- 运行下面的命令将host.domain.local替换为Web应用程序将运行的服务器的完全限定域名FQDN将domain\user替换为在前一步中创建的账户名称:
```sh
setspn -A HTTP/host.domain.local domain\user
```
在遵循上述步骤之前,请确保您按照以下流程进行操作:
1. 用之前创建的用户登录(如果已经登录,请先注销)。
2. 确保在`custom/conf/app.ini`文件的`[server]`部分中,`ROOT_URL`设置为Web应用程序将运行的服务器的完全限定域名FQDN与之前创建服务主体名称时使用的一致例如`host.domain.local`)。
3. 启动Web服务器运行 `gitea.exe web`)。
4. 在 `Site Administration -> Authentication Sources` 中添加一个 `SPNEGO with SSPI` 认证源以启用SSPI认证。
5. 在域中的客户端计算机上,使用任何域用户登录(与运行`gitea.exe`的服务器不同)。
6. 如果您使用Chrome或Edge浏览器请将Web应用程序的URL添加到“本地站点”`Internet选项 -> 安全 -> 本地站点 -> 站点`)。
7. 启动Chrome或Edge浏览器导航到Gitea的FQDN URL例如`http://host.domain.local:3000`)。
8. 在控制面板中点击“Sign In”按钮然后选择SSPI将会自动使用当前登录到计算机的用户进行登录。
9. 如果无法正常工作,请确保:
- 您不是在运行`gitea.exe`的同一台服务器上运行Web浏览器。应该在与服务器不同的域加入计算机客户端上运行Web浏览器。如果客户端和服务器都在同一台计算机上运行则NTLM将优先于Kerberos。
- 主机上只有一个`HTTP/...`的SPN。
- SPN中只包含主机名不包含端口号。
- 将Web应用程序的URL添加到"本地站点"。
- 服务器和客户端的时钟差异不超过5分钟取决于组策略
- 在Internet Explorer中启用了"集成Windows身份验证"(在"高级设置"下)。
遵循这些步骤您应该能够成功启用和使用SSPI单点登录认证SSO
## 反向代理认证
Gitea 支持通过读取反向代理传递的 HTTP 头中的登录名或者 email 地址来支持反向代理来认证。默认是不启用的,你可以用以下配置启用。
@ -34,4 +290,4 @@ ENABLE_REVERSE_PROXY_AUTHENTICATION = true
你也可以通过修改 `REVERSE_PROXY_TRUSTED_PROXIES` 来设置反向代理的IP地址范围加强安全性默认值是 `127.0.0.0/8,::1/128`。 通过 `REVERSE_PROXY_LIMIT` 可以设置最多信任几级反向代理。
注意反向代理认证不支持认证 APIAPI 仍旧需要用 access token 来进行认证。
注意:反向代理认证不支持认证 APIAPI 仍旧需要用 access token 来进行认证。

View File

@ -92,3 +92,16 @@ To set up a mirror from Gitea to Bitbucket, you need to follow these steps:
4. Select **Add Push Mirror** to save the configuration.
The repository pushes shortly thereafter. To force a push, select the **Synchronize Now** button.
### Mirror an existing ssh repository
Currently gitea supports no ssh push mirrors. You can work around this by adding a `post-receive` hook to your gitea repository that pushes manually.
1. Make sure the user running gitea has access to the git repo you are trying to mirror to from shell.
2. On the Webinterface at the repository settings > git hooks add a post-receive hook for the mirror. I.e.
```
#!/usr/bin/env bash
git push --mirror --quiet git@github.com:username/repository.git &>/dev/null &
echo "GitHub mirror initiated .."
```

View File

@ -34,7 +34,7 @@ type ActionRun struct {
Index int64 `xorm:"index unique(repo_index)"` // a unique number for each run of a repository
TriggerUserID int64 `xorm:"index"`
TriggerUser *user_model.User `xorm:"-"`
Ref string
Ref string `xorm:"index"` // the commit/tag/… that caused the run
CommitSHA string
IsForkPullRequest bool // If this is triggered by a PR from a forked repository or an untrusted user, we need to check if it is approved and limit permissions when running the workflow.
NeedApproval bool // may need approval if it's a fork pull request
@ -164,6 +164,73 @@ func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) err
return err
}
// CancelRunningJobs cancels all running and waiting jobs associated with a specific workflow.
func CancelRunningJobs(ctx context.Context, repoID int64, ref, workflowID string) error {
// Find all runs in the specified repository, reference, and workflow with statuses 'Running' or 'Waiting'.
runs, total, err := FindRuns(ctx, FindRunOptions{
RepoID: repoID,
Ref: ref,
WorkflowID: workflowID,
Status: []Status{StatusRunning, StatusWaiting},
})
if err != nil {
return err
}
// If there are no runs found, there's no need to proceed with cancellation, so return nil.
if total == 0 {
return nil
}
// Iterate over each found run and cancel its associated jobs.
for _, run := range runs {
// Find all jobs associated with the current run.
jobs, _, err := FindRunJobs(ctx, FindRunJobOptions{
RunID: run.ID,
})
if err != nil {
return err
}
// Iterate over each job and attempt to cancel it.
for _, job := range jobs {
// Skip jobs that are already in a terminal state (completed, cancelled, etc.).
status := job.Status
if status.IsDone() {
continue
}
// If the job has no associated task (probably an error), set its status to 'Cancelled' and stop it.
if job.TaskID == 0 {
job.Status = StatusCancelled
job.Stopped = timeutil.TimeStampNow()
// Update the job's status and stopped time in the database.
n, err := UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}, "status", "stopped")
if err != nil {
return err
}
// If the update affected 0 rows, it means the job has changed in the meantime, so we need to try again.
if n == 0 {
return fmt.Errorf("job has changed, try again")
}
// Continue with the next job.
continue
}
// If the job has an associated task, try to stop the task, effectively cancelling the job.
if err := StopTask(ctx, job.TaskID, StatusCancelled); err != nil {
return err
}
}
}
// Return nil to indicate successful cancellation of all running and waiting jobs.
return nil
}
// InsertRun inserts a run
func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWorkflow) error {
ctx, commiter, err := db.TxContext(ctx)

View File

@ -150,7 +150,7 @@ func aggregateJobStatus(jobs []*ActionRunJob) Status {
if !job.Status.IsDone() {
allDone = false
}
if job.Status != StatusWaiting {
if job.Status != StatusWaiting && !job.Status.IsDone() {
allWaiting = false
}
if job.Status == StatusFailure || job.Status == StatusCancelled {

View File

@ -66,12 +66,13 @@ func (runs RunList) LoadRepos() error {
type FindRunOptions struct {
db.ListOptions
RepoID int64
OwnerID int64
WorkflowFileName string
TriggerUserID int64
Approved bool // not util.OptionalBool, it works only when it's true
Status Status
RepoID int64
OwnerID int64
WorkflowID string
Ref string // the commit/tag/… that caused this workflow
TriggerUserID int64
Approved bool // not util.OptionalBool, it works only when it's true
Status []Status
}
func (opts FindRunOptions) toConds() builder.Cond {
@ -82,8 +83,8 @@ func (opts FindRunOptions) toConds() builder.Cond {
if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
}
if opts.WorkflowFileName != "" {
cond = cond.And(builder.Eq{"workflow_id": opts.WorkflowFileName})
if opts.WorkflowID != "" {
cond = cond.And(builder.Eq{"workflow_id": opts.WorkflowID})
}
if opts.TriggerUserID > 0 {
cond = cond.And(builder.Eq{"trigger_user_id": opts.TriggerUserID})
@ -91,8 +92,11 @@ func (opts FindRunOptions) toConds() builder.Cond {
if opts.Approved {
cond = cond.And(builder.Gt{"approved_by": 0})
}
if opts.Status > StatusUnknown {
cond = cond.And(builder.Eq{"status": opts.Status})
if len(opts.Status) > 0 {
cond = cond.And(builder.In("status", opts.Status))
}
if opts.Ref != "" {
cond = cond.And(builder.Eq{"ref": opts.Ref})
}
return cond
}

View File

@ -194,7 +194,7 @@ func (status *CommitStatus) APIURL(ctx context.Context) string {
// CalcCommitStatus returns commit status state via some status, the commit statues should order by id desc
func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus {
var lastStatus *CommitStatus
var state api.CommitStatusState
state := api.CommitStatusSuccess
for _, status := range statuses {
if status.State.NoBetterThan(state) {
state = status.State

View File

@ -517,6 +517,8 @@ var migrations = []Migration{
NewMigration("Reduce commit status", v1_21.ReduceCommitStatus),
// v267 -> v268
NewMigration("Add action_tasks_version table", v1_21.CreateActionTasksVersionTable),
// v268 -> v269
NewMigration("Update Action Ref", v1_21.UpdateActionsRefIndex),
}
// GetCurrentDBVersion returns the current db version

View File

@ -0,0 +1,16 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_21 //nolint
import (
"xorm.io/xorm"
)
// UpdateActionsRefIndex updates the index of actions ref field
func UpdateActionsRefIndex(x *xorm.Engine) error {
type ActionRun struct {
Ref string `xorm:"index"` // the commit/tag/… causing the run
}
return x.Sync(new(ActionRun))
}

View File

@ -53,12 +53,12 @@ func loadLFSFrom(rootCfg ConfigProvider) error {
return nil
}
LFS.JWTSecretBase64 = loadSecret(rootCfg.Section("lfs"), "LFS_JWT_SECRET_URI", "LFS_JWT_SECRET")
LFS.JWTSecretBase64 = loadSecret(rootCfg.Section("server"), "LFS_JWT_SECRET_URI", "LFS_JWT_SECRET")
LFS.JWTSecretBytes = make([]byte, 32)
n, err := base64.RawURLEncoding.Decode(LFS.JWTSecretBytes, []byte(LFS.JWTSecretBase64))
if err != nil || n != 32 {
if (err != nil || n != 32) && InstallLock {
LFS.JWTSecretBase64, err = generate.NewJwtSecretBase64()
if err != nil {
return fmt.Errorf("error generating JWT Secret for custom config: %v", err)

View File

@ -8,6 +8,7 @@ type Organization struct {
ID int64 `json:"id"`
Name string `json:"name"`
FullName string `json:"full_name"`
Email string `json:"email"`
AvatarURL string `json:"avatar_url"`
Description string `json:"description"`
Website string `json:"website"`
@ -32,6 +33,7 @@ type CreateOrgOption struct {
// required: true
UserName string `json:"username" binding:"Required;Username;MaxSize(40)"`
FullName string `json:"full_name" binding:"MaxSize(100)"`
Email string `json:"email" binding:"MaxSize(255)"`
Description string `json:"description" binding:"MaxSize(255)"`
Website string `json:"website" binding:"ValidUrl;MaxSize(255)"`
Location string `json:"location" binding:"MaxSize(50)"`
@ -46,6 +48,7 @@ type CreateOrgOption struct {
// EditOrgOption options for editing an organization
type EditOrgOption struct {
FullName string `json:"full_name" binding:"MaxSize(100)"`
Email string `json:"email" binding:"MaxSize(255)"`
Description string `json:"description" binding:"MaxSize(255)"`
Website string `json:"website" binding:"ValidUrl;MaxSize(255)"`
Location string `json:"location" binding:"MaxSize(50)"`

View File

@ -639,7 +639,7 @@ update_language_not_found = Language "%s" is not available.
update_language_success = Language has been updated.
update_profile_success = Your profile has been updated.
change_username = Your username has been changed.
change_username_prompt = Note: username changes also change your account URL.
change_username_prompt = Note: Changing your username also changes your account URL.
change_username_redirect_prompt = The old username will redirect until someone claims it.
continue = Continue
cancel = Cancel
@ -2532,6 +2532,7 @@ form.create_org_not_allowed = You are not allowed to create an organization.
settings = Settings
settings.options = Organization
settings.full_name = Full Name
settings.email = Contact Email
settings.website = Website
settings.location = Location
settings.permission = Permissions

View File

@ -640,6 +640,7 @@ language=Dil
ui=Tema
hidden_comment_types=Gizli yorum türleri
hidden_comment_types_description=Burada işaretlenen yorum türleri konu sayfalarında görüntülenmeyecektir. Örneğin "Etiket" seçildiğinde tüm "<user>, <label> ekledi/çıkardı" yorumları kalkacaktır.
hidden_comment_types.ref_tooltip=Bu konuya başka konu/işlem tarafından değinilen yorumlar…
hidden_comment_types.issue_ref_tooltip=Kullanıcının konuyla ilişkili dalı/etiketi değiştirdiği yorumlar
comment_type_group_reference=Referans
comment_type_group_label=Etiket
@ -806,8 +807,11 @@ access_token_deletion_confirm_action=Sil
access_token_deletion_desc=Bir erişim anahtarını silmek, onu kullanan uygulamaların hesabınıza erişimini kaldırır. Bu geri alınamaz. Devam edilsin mi?
delete_token_success=Jeton silindi. Onu kullanan uygulamalar artık hesabınıza erişemez.
repo_and_org_access=Depo ve Organizasyon Erişimi
permissions_public_only=Yalnızca herkese açık
permissions_access_all=Tümü (herkese açık, özel ve sınırlı)
select_permissions=İzinleri seçin
scoped_token_desc=Seçili token kapsamları, yetkilendirmeyi ilgili <a %s>API</a> yollarıyla sınırlandıracaktır. Daha fazla bilgi için <a %s>belgeleri</a> okuyun.
at_least_one_permission=Bir token oluşturmak için en azından bir izin seçmelisiniz
permissions_list=İzinler:
manage_oauth2_applications=OAuth2 Uygulamalarını Yönet
@ -822,6 +826,7 @@ create_oauth2_application_success=Başarıyla yeni bir OAuth2 uygulaması oluşt
update_oauth2_application_success=OAuth2 uygulamasını başarıyla güncellediniz.
oauth2_application_name=Uygulama Adı
oauth2_confidential_client=Güvenli İstemci. Web uygulamaları gibi sırları güvende tutan uygulamalar için bunu seçin. Masaüstü ve mobil uygulamaları da içeren doğal uygulamalar için seçmeyin.
oauth2_redirect_uris=Yönlendirme URI'leri. Lütfen her bir URI'yi yeni bir satıra yazın.
save_application=Kaydet
oauth2_client_id=İstemci Kimliği
oauth2_client_secret=İstemci Gizliliği
@ -967,6 +972,7 @@ mirror_password_blank_placeholder=(Ayarı kaldır)
mirror_password_help=Saklanan bir parolayı silmek için kullanıcı adını değiştirin.
watchers=İzleyenler
stargazers=Yıldızlayanlar
stars_remove_warning=Bu depodan tüm yıldızları kaldıracaktır.
forks=Çatallamalar
reactions_more=ve %d daha fazla
unit_disabled=Site yöneticisi bu depo bölümünü devre dışı bıraktı.
@ -1010,6 +1016,7 @@ template.one_item=En az bir şablon öğesi seçmelisiniz
template.invalid=Bir şablon deposu seçmelisiniz
archive.title=Bu depo arşivlendi. Dosyaları görüntüleyebilir ve klonlayabilirsiniz ama işlem gönderemez ve konu/değişiklik isteği açamazsınız.
archive.title_date=Bu depo %s tarihinde arşivlendi. Dosyaları görüntüleyebilir ve klonlayabilirsiniz ama işleme gönderemez veya konu/değişiklik isteği açamazsınız.
archive.issue.nocomment=Bu depo arşivlendi. Konular bölümünde yorum yapamazsınız.
archive.pull.nocomment=Bu depo arşivlendi. Değişiklik istekleri bölümünde yorum yapamazsınız.
@ -1051,6 +1058,7 @@ migrated_from_fake=%[1]s Konumundan Göç Edildi
migrate.migrate=%s Konumundan Göç Et
migrate.migrating=<b>%s</b> konumundan taşınıyor ...
migrate.migrating_failed=<b>%s</b> konumundan taşıma başarısız oldu.
migrate.migrating_failed.error=Göç yapılamadı: %s
migrate.migrating_failed_no_addr=Göç başarısız oldu.
migrate.github.description=Github.com veya diğer Github sunucularından veri aktar.
migrate.git.description=Herhangi bir Git hizmetinden sadece bir depoyu aktar.
@ -1119,6 +1127,7 @@ release=Sürüm
releases=Sürüm
tag=Etiket
released_this=bu sürümü yayınladı
tagged_this=şunu etiketledi
file.title=%s dalındaki/etiketindeki %s
file_raw=Ham
file_history=Geçmiş
@ -1427,6 +1436,8 @@ issues.context.edit=Düzenle
issues.context.delete=Sil
issues.no_content=Henüz bir içerik yok.
issues.close=Konuyu Kapat
issues.comment_pull_merged_at=%[1]s işlemesi, %[2]s dalına birleştirildi %[3]s
issues.comment_manually_pull_merged_at=%[1]s işlemesi, %[2]s dalına elle birleştirildi %[3]s
issues.close_comment_issue=Yorum Yap ve Kapat
issues.reopen_issue=Yeniden aç
issues.reopen_comment_issue=Yorum Yap ve Yeniden Aç
@ -1477,6 +1488,10 @@ issues.attachment.open_tab=`Yeni bir sekmede "%s" görmek için tıkla`
issues.attachment.download=`"%s" indirmek için tıkla`
issues.subscribe=Abone Ol
issues.unsubscribe=Abonelikten Çık
issues.unpin_issue=Konuyu Sabitlemeden Kaldır
issues.max_pinned=Daha fazla konuyu sabitleyemezsiniz
issues.pin_comment=%s sabitlendi
issues.unpin_comment=%s sabitlenmesi kaldırıldı
issues.lock=Konuşmayı kilitle
issues.unlock=Konuşmanın kilidini aç
issues.lock.unknown_reason=Sebep belirtmeden konuyu kilitleyemezsiniz.
@ -1556,6 +1571,7 @@ issues.dependency.issue_closing_blockedby=Bu konunun kapatılması aşağıdaki
issues.dependency.issue_close_blocks=Bu konu aşağıdaki konuların kapatılmasını engelliyor
issues.dependency.pr_close_blocks=Bu değişiklik isteği aşağıdaki sorunların kapatılmasını engelliyor
issues.dependency.issue_close_blocked=Kapatmadan önce bu konuyu engelleyen tüm konuları kapatmanız gerekir.
issues.dependency.issue_batch_close_blocked=Seçtiğiniz konular topluca kapatılamıyor, çünkü #%d konusunun açık bağımlılıkları var
issues.dependency.pr_close_blocked=Birleştirme işleminden önce, bu değişiklik isteğini engelleyen tüm konuları kapatmanız gerekir.
issues.dependency.blocks_short=Engeller
issues.dependency.blocked_by_short=Bağımlılıklar
@ -1901,6 +1917,16 @@ settings.hooks=Web İstemcileri
settings.githooks=Git İstemcileri
settings.basic_settings=Temel Ayarlar
settings.mirror_settings=Yansı Ayarları
settings.mirror_settings.docs=Deponuzu işlemeleri, etiketleri ve dalları başka bir depoyla otomatik olarak eşleyecek şekilde kurun.
settings.mirror_settings.docs.disabled_pull_mirror.instructions=Projenizi işlemeleri, etiketleri ve dalları başka bir depoya otomatik olarak gönderecek şekilde kurun. Çekme yansıları site yöneticiniz tarafından devre dışı bırakılmıştır.
settings.mirror_settings.docs.disabled_push_mirror.instructions=Projenizi işlemeleri, etiketleri ve dalları başka bir depodan otomatik olarak çekecek şekilde kurun.
settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=Şu an bu sadece "Yeni Göç" menüsüyle yapılabilir. Daha fazla bilgi için, lütfen şuraya danışın:
settings.mirror_settings.docs.disabled_push_mirror.info=Gönderme yansıları site yöneticiniz tarafından devre dışı bırakılmıştır.
settings.mirror_settings.docs.no_new_mirrors=Deponuz değişiklikleri başka bir depoyla yansılıyor. Şu an başka bir yansı oluşturamayacağınızı unutmayın.
settings.mirror_settings.docs.can_still_use=Her ne kadar mevcut yansıları değiştiremiyor veya yeni yansı oluşturamıyor olsanız da, hala mevcut yansıyı kullanabilirsiniz.
settings.mirror_settings.docs.pull_mirror_instructions=Çekme yansıyı kurmak için, lütfen şuraya danışın:
settings.mirror_settings.docs.doc_link_title=Depoların yansısını nasıl oluştururum?
settings.mirror_settings.docs.pulling_remote_title=Uzak bir depodan çekmek
settings.mirror_settings.mirrored_repository=Yansıtılmış depo
settings.mirror_settings.direction=Yön
settings.mirror_settings.direction.pull=Çek
@ -1913,6 +1939,8 @@ settings.sync_mirror=Şimdi Eşitle
settings.mirror_sync_in_progress=Yansı senkronizasyonu devam ediyor. Bir dakika sonra tekrar kontrol edin.
settings.site=Web Sitesi
settings.update_settings=Ayarları Güncelle
settings.update_mirror_settings=Yansı Ayarları Güncelle
settings.branches.switch_default_branch=Varsayılan Dalı Değiştir
settings.branches.update_default_branch=Varsayılan Dalı Değiştir
settings.branches.add_new_rule=Yeni Kural Ekle
settings.advanced_settings=Gelişmiş Ayarlar
@ -2011,6 +2039,7 @@ settings.delete_notices_2=- Bu işlem, kod, sorunlar, yorumlar, wiki verileri ve
settings.delete_notices_fork_1=- Silme işleminden sonra bu deponun çatalları bağımsız hale gelecektir.
settings.deletion_success=Depo silindi.
settings.update_settings_success=Depo ayarları güncellendi.
settings.update_settings_no_unit=Depo en azından bir çeşit etkileşime izin vermelidir.
settings.confirm_delete=Depoyu Sil
settings.add_collaborator=Katkıcı Ekle
settings.add_collaborator_success=Katkıcı eklendi.
@ -2108,6 +2137,10 @@ settings.event_pull_request_review=Değişiklik İsteği İncelendi
settings.event_pull_request_review_desc=Değişiklik isteği onaylandı, reddedildi veya yorumu incelendi.
settings.event_pull_request_sync=Değişiklik İsteği Senkronize Edildi
settings.event_pull_request_sync_desc=Değişiklik isteği senkronize edildi.
settings.event_pull_request_review_request=Değişiklik İsteği İncelemesi İstendi
settings.event_pull_request_review_request_desc=Değişiklik isteği incelemesi istendi veya inceleme isteği kaldırıldı.
settings.event_pull_request_approvals=Değişiklik İsteği Onayları
settings.event_pull_request_merge=Değişiklik İsteği Birleştirme
settings.event_package=Paket
settings.event_package_desc=Bir depoda paket oluşturuldu veya silindi.
settings.branch_filter=Dal filtresi
@ -2170,6 +2203,8 @@ settings.protect_disable_push=İtmeyi Devre Dışı Bırak
settings.protect_disable_push_desc=Bu dala itme yapılmasına izin verilmeyecek.
settings.protect_enable_push=İtmeyi Etkinleştir
settings.protect_enable_push_desc=Yazma erişimi olan herkesin bu dala itmesine izin verilir (ancak zorla itmeyin).
settings.protect_enable_merge=Birleştirmeyi Etkinleştir
settings.protect_enable_merge_desc=Yazma erişimi olan herhangi bir kimse, değişiklik isteklerini bu dala birleştirebilecektir.
settings.protect_whitelist_committers=Beyaz Liste Kısıtlı Gönderme
settings.protect_whitelist_committers_desc=Sadece beyaz listeye alınmış kullanıcıların veya takımların bu dala göndermesine izin verilir (ancak zorla gönderim yapmayın).
settings.protect_whitelist_deploy_keys=Beyaz liste göndermek için yazma erişimi olan anahtarları dağıtır.
@ -2182,8 +2217,13 @@ settings.protect_merge_whitelist_committers_desc=Yalnızca beyaz listedeki kulla
settings.protect_merge_whitelist_users=Birleştirme için beyaz listedeki kullanıcılar:
settings.protect_merge_whitelist_teams=Birleştirme için beyaz listedeki takımlar:
settings.protect_check_status_contexts=Durum Denetimini Etkinleştir
settings.protect_status_check_patterns=Durum denetleme desenleri:
settings.protect_status_check_patterns_desc=Bu kurala uyan dala diğer dallar birleştirilmeden önce başarılı olması gereken durum denetlemelerini belirten desenleri girin. Her bir satır bir desen tanımlıyor. Desenler boş olamaz.
settings.protect_check_status_contexts_desc=Birleştirmeden önce durum denetimlerinin geçmesini zorunlu kılın. Dalların bu kurala uyan bir dalda birleştirilebilmesi için hangi durum denetimlerinin geçmesi gerektiğini seçin. Etkinleştirildiğinde, işlemeler önce başka bir dala gönderilmeli, ardından durum denetimleri geçtikten sonra bu kuralla eşleşen bir dala birleştirilmeli veya doğrudan gönderilmelidir. Hiçbir bağlam seçilmezse, bağlamdan bağımsız olarak son işleme başarılı olmalıdır.
settings.protect_check_status_contexts_list=Bu depo için geçen haftadaki durum denetimleri
settings.protect_status_check_matched=Eşleşen
settings.protect_invalid_status_check_pattern=Hatalı durum denetleme deseni: "%s".
settings.protect_no_valid_status_check_patterns=Geçerli durum denetleme deseni yok.
settings.protect_required_approvals=Gerekli onaylar:
settings.protect_required_approvals_desc=Değişiklik isteğini yalnızca yeterince olumlu yorumla birleştirmeye izin ver.
settings.protect_approvals_whitelist_enabled=Onayları beyaz listeye giren kullanıcılar veya takımlar için kısıtla
@ -2195,6 +2235,7 @@ settings.dismiss_stale_approvals_desc=Değişiklik isteğinin içeriğini deği
settings.require_signed_commits=İmzalı İşleme Gerekli
settings.require_signed_commits_desc=Reddetme, onlar imzasızsa veya doğrulanamazsa bu dala gönderir.
settings.protect_branch_name_pattern=Korunmuş Dal Adı Deseni
settings.protect_patterns=Desenler
settings.protect_protected_file_patterns=Korumalı dosya kalıpları (noktalı virgülle ayrılmış ';'):
settings.protect_protected_file_patterns_desc=Kullanıcının bu dalda dosya ekleme, düzenleme veya silme hakları olsa bile doğrudan değiştirilmesine izin verilmeyen korumalı dosyalar. Birden çok desen noktalı virgül (';') kullanılarak ayrılabilir. Desen sözdizimi için <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> belgelerine bakın. Örnekler: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.protect_unprotected_file_patterns=Korunmasız dosya desenleri (noktalı virgülle ayrılmış ';'):
@ -2409,11 +2450,13 @@ branch.protected_deletion_failed=`"%s" dalı korunuyor. Silinemez.`
branch.default_deletion_failed=`"%s" dalı varsayılan daldır. Silinemez.`
branch.restore=`"%s" Dalını Geri Yükle`
branch.download=`"%s" Dalını İndir`
branch.rename=`"%s" Dalının Adını Değiştir`
branch.included_desc=Bu dal varsayılan dalın bir parçasıdır
branch.included=Dahil
branch.create_new_branch=Şu daldan dal oluştur:
branch.confirm_create_branch=Dal oluştur
branch.warning_rename_default_branch=Varsayılan dalın adını değiştiriyorsunuz.
branch.rename_branch_to=`"%s" adını şuna değiştir:`
branch.confirm_rename_branch=Dalı yeniden adlandır
branch.create_branch_operation=Dal oluştur
branch.new_branch=Yeni dal oluştur

View File

@ -255,6 +255,7 @@ func Create(ctx *context.APIContext) {
org := &organization.Organization{
Name: form.UserName,
FullName: form.FullName,
Email: form.Email,
Description: form.Description,
Website: form.Website,
Location: form.Location,
@ -299,7 +300,15 @@ func Get(ctx *context.APIContext) {
ctx.NotFound("HasOrgOrUserVisible", nil)
return
}
ctx.JSON(http.StatusOK, convert.ToOrganization(ctx, ctx.Org.Organization))
org := convert.ToOrganization(ctx, ctx.Org.Organization)
// Don't show Mail, when User is not logged in
if ctx.Doer == nil {
org.Email = ""
}
ctx.JSON(http.StatusOK, org)
}
// Edit change an organization's information
@ -328,6 +337,7 @@ func Edit(ctx *context.APIContext) {
form := web.GetForm(ctx).(*api.EditOrgOption)
org := ctx.Org.Organization
org.FullName = form.FullName
org.Email = form.Email
org.Description = form.Description
org.Website = form.Website
org.Location = form.Location

View File

@ -100,6 +100,7 @@ func SettingsPost(ctx *context.Context) {
}
org.FullName = form.FullName
org.Email = form.Email
org.Description = form.Description
org.Website = form.Website
org.Location = form.Location

View File

@ -150,10 +150,14 @@ func List(ctx *context.Context) {
Page: page,
PageSize: convert.ToCorrectPageSize(ctx.FormInt("limit")),
},
RepoID: ctx.Repo.Repository.ID,
WorkflowFileName: workflow,
TriggerUserID: actorID,
Status: actions_model.Status(status),
RepoID: ctx.Repo.Repository.ID,
WorkflowID: workflow,
TriggerUserID: actorID,
}
// if status is not StatusUnknown, it means user has selected a status filter
if actions_model.Status(status) != actions_model.StatusUnknown {
opts.Status = []actions_model.Status{actions_model.Status(status)}
}
runs, total, err := actions_model.FindRuns(ctx, opts)

View File

@ -230,16 +230,31 @@ func notify(ctx context.Context, input *notifyInput) error {
log.Error("jobparser.Parse: %v", err)
continue
}
// cancel running jobs if the event is push
if run.Event == webhook_module.HookEventPush {
// cancel running jobs of the same workflow
if err := actions_model.CancelRunningJobs(
ctx,
run.RepoID,
run.Ref,
run.WorkflowID,
); err != nil {
log.Error("CancelRunningJobs: %v", err)
}
}
if err := actions_model.InsertRun(ctx, run, jobs); err != nil {
log.Error("InsertRun: %v", err)
continue
}
if jobs, _, err := actions_model.FindRunJobs(ctx, actions_model.FindRunJobOptions{RunID: run.ID}); err != nil {
log.Error("FindRunJobs: %v", err)
} else {
CreateCommitStatus(ctx, jobs...)
}
alljobs, _, err := actions_model.FindRunJobs(ctx, actions_model.FindRunJobOptions{RunID: run.ID})
if err != nil {
log.Error("FindRunJobs: %v", err)
continue
}
CreateCommitStatus(ctx, alljobs...)
}
return nil
}

View File

@ -289,6 +289,7 @@ func ToOrganization(ctx context.Context, org *organization.Organization) *api.Or
Name: org.Name,
UserName: org.Name,
FullName: org.FullName,
Email: org.Email,
Description: org.Description,
Website: org.Website,
Location: org.Location,

View File

@ -38,6 +38,7 @@ func (f *CreateOrgForm) Validate(req *http.Request, errs binding.Errors) binding
type UpdateOrgSettingForm struct {
Name string `binding:"Required;Username;MaxSize(40)" locale:"org.org_name_holder"`
FullName string `binding:"MaxSize(100)"`
Email string `binding:"MaxSize(255)"`
Description string `binding:"MaxSize(255)"`
Website string `binding:"ValidUrl;MaxSize(255)"`
Location string `binding:"MaxSize(50)"`

View File

@ -15,8 +15,11 @@
</div>
{{if $.RenderedDescription}}<div class="render-content markup">{{$.RenderedDescription|Str2html}}</div>{{end}}
<div class="text grey meta">
{{if .Org.Location}}<div class="item">{{svg "octicon-location"}} <span>{{.Org.Location}}</span></div>{{end}}
{{if .Org.Website}}<div class="item">{{svg "octicon-link"}} <a target="_blank" rel="noopener noreferrer me" href="{{.Org.Website}}">{{.Org.Website}}</a></div>{{end}}
{{if .Org.Location}}<div class="flex-text-block">{{svg "octicon-location"}} <span>{{.Org.Location}}</span></div>{{end}}
{{if .Org.Website}}<div class="flex-text-block">{{svg "octicon-link"}} <a target="_blank" rel="noopener noreferrer me" href="{{.Org.Website}}">{{.Org.Website}}</a></div>{{end}}
{{if $.IsSigned}}
{{if .Org.Email}}<div class="flex-text-block">{{svg "octicon-mail"}} <a class="muted" href="mailto:{{.Org.Email}}">{{.Org.Email}}</a></div>{{end}}
{{end}}
</div>
</div>
<div class="right menu">

View File

@ -18,6 +18,10 @@
<label for="full_name">{{.locale.Tr "org.org_full_name_holder"}}</label>
<input id="full_name" name="full_name" value="{{.Org.FullName}}" maxlength="100">
</div>
<div class="field {{if .Err_Email}}error{{end}}">
<label for="email">{{.locale.Tr "org.settings.email"}}</label>
<input id="email" name="email" type="email" value="{{.Org.Email}}" maxlength="255">
</div>
<div class="field {{if .Err_Description}}error{{end}}">
<label for="description">{{$.locale.Tr "org.org_desc"}}</label>
<textarea id="description" name="description" rows="2" maxlength="255">{{.Org.Description}}</textarea>

View File

@ -31,27 +31,27 @@
<span class="message gt-dib gt-ellipsis gt-mr-3">
<span>{{RenderCommitMessage $.Context $commit.Subject $.RepoLink $.Repository.ComposeMetas}}</span>
</span>
<span class="tags gt-df gt-ac gt-mr-2">
<span class="commit-refs gt-df gt-ac gt-mr-2">
{{range $commit.Refs}}
{{$refGroup := .RefGroup}}
{{if eq $refGroup "pull"}}
{{if or (not $.HidePRRefs) (SliceUtils.Contains $.SelectedBranches .Name)}}
<!-- it's intended to use issues not pulls, if it's a pull you will get redirected -->
<a class="ui labelled icon button basic tiny gt-mr-2" href="{{$.RepoLink}}/{{if $.Repository.UnitEnabled $.Context $.UnitTypePullRequests}}pulls{{else}}issues{{end}}/{{.ShortName|PathEscape}}">
{{svg "octicon-git-pull-request" 16 "gt-mr-2"}}#{{.ShortName}}
<a class="ui labelled basic tiny button" href="{{$.RepoLink}}/{{if $.Repository.UnitEnabled $.Context $.UnitTypePullRequests}}pulls{{else}}issues{{end}}/{{.ShortName|PathEscape}}">
{{svg "octicon-git-pull-request"}} #{{.ShortName}}
</a>
{{end}}
{{else if eq $refGroup "tags"}}
<a class="ui labelled icon button basic tiny gt-mr-2" href="{{$.RepoLink}}/src/tag/{{.ShortName|PathEscape}}">
{{svg "octicon-tag" 16 "gt-mr-2"}}{{.ShortName}}
<a class="ui labelled basic tiny button" href="{{$.RepoLink}}/src/tag/{{.ShortName|PathEscape}}">
{{svg "octicon-tag"}} {{.ShortName}}
</a>
{{else if eq $refGroup "remotes"}}
<a class="ui labelled icon button basic tiny gt-mr-2" href="{{$.RepoLink}}/src/commit/{{$commit.Rev|PathEscape}}">
{{svg "octicon-cross-reference" 16 "gt-mr-2"}}{{.ShortName}}
<a class="ui labelled basic tiny button" href="{{$.RepoLink}}/src/commit/{{$commit.Rev|PathEscape}}">
{{svg "octicon-cross-reference"}} {{.ShortName}}
</a>
{{else if eq $refGroup "heads"}}
<a class="ui labelled icon button basic tiny gt-mr-2" href="{{$.RepoLink}}/src/branch/{{.ShortName|PathEscape}}">
{{svg "octicon-git-branch" 16 "gt-mr-2"}}{{.ShortName}}
<a class="ui labelled basic tiny button" href="{{$.RepoLink}}/src/branch/{{.ShortName|PathEscape}}">
{{svg "octicon-git-branch"}} {{.ShortName}}
</a>
{{else}}
<!-- Unknown ref type .Name -->

View File

@ -13,7 +13,7 @@
{{- else if .IsBlockedByOutdatedBranch}}red
{{- else if .IsBlockedByChangedProtectedFiles}}red
{{- else if and .EnableStatusCheck (or .RequiredStatusCheckState.IsFailure .RequiredStatusCheckState.IsError)}}red
{{- else if and .EnableStatusCheck (or (not $.LatestCommitStatus) .RequiredStatusCheckState.IsPending .RequiredStatusCheckState.IsWarning)}}yellow
{{- else if and .EnableStatusCheck (or (not $.LatestCommitStatus) .RequiredStatusCheckState.IsPending)}}yellow
{{- else if and .AllowMerge .RequireSigned (not .WillSign)}}red
{{- else if .Issue.PullRequest.IsChecking}}yellow
{{- else if .Issue.PullRequest.IsEmpty}}grey

View File

@ -12,9 +12,9 @@
{{end}}
</h2>
{{template "base/alert" .}}
<form class="ui form stackable grid" action="{{.Link}}" method="post">
<form class="ui form" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<div class="ui seven wide column target">
<div class="ui seven wide target">
<div class="inline field {{if .Err_TagName}}error{{end}}">
{{if .PageIsEditRelease}}
<b>{{.tag_name}}</b><span class="at">@</span><strong>{{.tag_target}}</strong>
@ -44,7 +44,7 @@
{{end}}
</div>
</div>
<div class="eleven wide column gt-pt-0">
<div class="eleven wide gt-pt-0">
<div class="field {{if .Err_Title}}error{{end}}">
<input name="title" aria-label="{{.locale.Tr "repo.release.title"}}" placeholder="{{.locale.Tr "repo.release.title"}}" value="{{.title}}" autofocus maxlength="255">
</div>
@ -83,9 +83,9 @@
</div>
{{end}}
</div>
<div class="ui container">
<div class="divider"></div>
<div class="ui text right">
<div class="divider"></div>
<div class="ui">
<div>
{{if not .PageIsEditRelease}}
<div class="tag-message field">
<div class="ui checkbox">
@ -103,30 +103,27 @@
</div>
</div>
<span class="help">{{.locale.Tr "repo.release.prerelease_helper"}}</span>
<div class="field">
<div class="divider gt-mt-0"></div>
<div class="gt-df gt-je">
{{if .PageIsEditRelease}}
<a class="ui button" href="{{.RepoLink}}/releases">
<a class="ui small button" href="{{.RepoLink}}/releases">
{{.locale.Tr "repo.release.cancel"}}
</a>
<a class="ui red button delete-button" data-url="{{$.RepoLink}}/releases/delete" data-id="{{.ID}}">
<a class="ui small red button delete-button" data-url="{{$.RepoLink}}/releases/delete" data-id="{{.ID}}">
{{$.locale.Tr "repo.release.delete_release"}}
</a>
{{if .IsDraft}}
<button class="ui button" type="submit" name="draft" value="{{.locale.Tr "repo.release.save_draft"}}">{{.locale.Tr "repo.release.save_draft"}}</button>
<button class="ui primary button">
<button class="ui small button" type="submit" name="draft" value="{{.locale.Tr "repo.release.save_draft"}}">{{.locale.Tr "repo.release.save_draft"}}</button>
<button class="ui small primary button">
{{.locale.Tr "repo.release.publish"}}
</button>
{{else}}
<button class="ui primary button">
<button class="ui small primary button">
{{.locale.Tr "repo.release.edit_release"}}
</button>
{{end}}
{{else}}
{{if not .tag_name}}
<button class="ui button" type="submit" name="tag_only" value="{{.locale.Tr "repo.release.add_tag"}}">{{.locale.Tr "repo.release.add_tag"}}</button>
{{end}}
<button class="ui button" type="submit" name="draft" value="{{.locale.Tr "repo.release.save_draft"}}">{{.locale.Tr "repo.release.save_draft"}}</button>
<button class="ui primary button">
<button class="ui small primary button">
{{.locale.Tr "repo.release.publish"}}
</button>
{{end}}

View File

@ -6,8 +6,8 @@
<div class="ui header">
{{.locale.Tr "repo.wiki.new_page"}}
{{if .PageIsWikiEdit}}
<div class="ui right">
<a class="ui green small button" href="{{.RepoLink}}/wiki?action=_new">{{.locale.Tr "repo.wiki.new_page_button"}}</a>
<div class="ui right gt-mb-3">
<a class="ui green tiny button" href="{{.RepoLink}}/wiki?action=_new">{{.locale.Tr "repo.wiki.new_page_button"}}</a>
</div>
{{end}}
</div>
@ -37,6 +37,7 @@
<div class="field gt-mt-4">
<input name="message" aria-label="{{.locale.Tr "repo.wiki.default_commit_message"}}" placeholder="{{.locale.Tr "repo.wiki.default_commit_message"}}">
</div>
<div class="divider"></div>
<div class="text right">
<button class="ui green button">
{{.locale.Tr "repo.wiki.save_page"}}

View File

@ -17125,6 +17125,10 @@
"type": "string",
"x-go-name": "Description"
},
"email": {
"type": "string",
"x-go-name": "Email"
},
"full_name": {
"type": "string",
"x-go-name": "FullName"
@ -18043,6 +18047,10 @@
"type": "string",
"x-go-name": "Description"
},
"email": {
"type": "string",
"x-go-name": "Email"
},
"full_name": {
"type": "string",
"x-go-name": "FullName"
@ -20100,6 +20108,10 @@
"type": "string",
"x-go-name": "Description"
},
"email": {
"type": "string",
"x-go-name": "Email"
},
"full_name": {
"type": "string",
"x-go-name": "FullName"

View File

@ -11,8 +11,8 @@
</div>
<div class="ui bottom attached active tab segment">
{{if eq .Status 1}}
<div class="ui stackable grid">
<div class="six wide column">
<div class="gt-df gt-sb">
<div class="gt-df">
<div class="small-menu-items ui compact tiny menu">
<a class="{{if eq .State "all"}}active {{end}}item" href="{{$.Link}}?sort={{$.SortType}}&state=all&issueType={{$.IssueType}}&labels={{$.Labels}}">
{{.locale.Tr "all"}}
@ -27,8 +27,8 @@
</a>
</div>
</div>
<div class="seven wide right aligned right floated column">
<div class="ui right aligned secondary filter stackable menu labels">
<div class="gt-df gt-sb">
<div class="ui right aligned secondary filter menu labels">
<!-- Type -->
<div class="ui dropdown type jump item">
<span class="text">

View File

@ -36,6 +36,7 @@ func TestUserOrgs(t *testing.T) {
Name: user17.Name,
UserName: user17.Name,
FullName: user17.FullName,
Email: user17.Email,
AvatarURL: user17.AvatarLink(db.DefaultContext),
Description: "",
Website: "",
@ -47,6 +48,7 @@ func TestUserOrgs(t *testing.T) {
Name: user3.Name,
UserName: user3.Name,
FullName: user3.FullName,
Email: user3.Email,
AvatarURL: user3.AvatarLink(db.DefaultContext),
Description: "",
Website: "",
@ -106,6 +108,7 @@ func TestMyOrgs(t *testing.T) {
Name: user17.Name,
UserName: user17.Name,
FullName: user17.FullName,
Email: user17.Email,
AvatarURL: user17.AvatarLink(db.DefaultContext),
Description: "",
Website: "",
@ -117,6 +120,7 @@ func TestMyOrgs(t *testing.T) {
Name: user3.Name,
UserName: user3.Name,
FullName: user3.FullName,
Email: user3.Email,
AvatarURL: user3.AvatarLink(db.DefaultContext),
Description: "",
Website: "",

View File

@ -109,8 +109,13 @@
background-color: var(--color-secondary-alpha-30);
}
#git-graph-container #rev-list .tags a.button {
#git-graph-container #rev-list .commit-refs .button {
padding: 2px 4px;
margin-right: 0.25em;
display: inline-block;
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
}
#git-graph-container #rev-list .sha.label {

View File

@ -118,13 +118,11 @@
margin-bottom: 10px;
}
.organization.profile #org-info .meta .item {
display: inline-block;
margin-right: 10px;
}
.organization.profile #org-info .meta .item .icon {
margin-right: 5px;
.organization.profile #org-info .meta {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
.organization.profile .ui.top.header .ui.right {

View File

@ -132,3 +132,7 @@
.repository.new.release .field .attachment_edit {
width: 450px !important;
}
.repository.new.release .markup {
min-height: 240px;
}

View File

@ -9,6 +9,7 @@
.repository.wiki .markup {
overflow: visible;
min-height: 340px;
}
.repository.wiki .wiki-content-parts .markup {