1
1
mirror of https://github.com/go-gitea/gitea synced 2024-11-05 09:44:26 +00:00

Merge remote-tracking branch 'origin/main' into api-repo-actions

This commit is contained in:
chesterip 2023-08-30 11:31:23 -04:00
commit 80a2c8ee38
317 changed files with 3111 additions and 2686 deletions

View File

@ -5,7 +5,7 @@
2. Please ask questions or configuration/deploy problems on our Discord
server (https://discord.gg/gitea) or forum (https://discourse.gitea.io).
3. Please take a moment to check that your issue doesn't already exist.
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.io/en-us/faq)
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.com/help/faq)
5. Please give all relevant information below for bug reports, because
incomplete details will be handled as an invalid report.
-->
@ -26,7 +26,7 @@
- [ ] No
- Log gist:
<!-- It really is important to provide pertinent logs -->
<!-- Please read https://docs.gitea.io/en-us/logging-configuration/#debugging-problems -->
<!-- Please read https://docs.gitea.com/administration/logging-config#collecting-logs-for-help -->
<!-- In addition, if your problem relates to git commands set `RUN_MODE=dev` at the top of app.ini -->
## Description

View File

@ -1,6 +1,6 @@
name: Bug Report
description: Found something you weren't expecting? Report it here!
labels: kind/bug
labels: ["kind/bug"]
body:
- type: markdown
attributes:
@ -14,12 +14,9 @@ body:
server (https://discord.gg/gitea) or forum (https://discourse.gitea.io).
3. Make sure you are using the latest release and
take a moment to check that your issue hasn't been reported before.
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.io/en-us/faq)
5. Please give all relevant information below for bug reports, because
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.com/help/faq)
5. It's really important to provide pertinent details and logs (https://docs.gitea.com/help/support),
incomplete details will be handled as an invalid report.
6. In particular it's really important to provide pertinent logs. You must give us DEBUG level logs.
Please read https://docs.gitea.io/en-us/logging-configuration/#debugging-problems
In addition, if your problem relates to git commands set `RUN_MODE=dev` at the top of app.ini
- type: textarea
id: description
attributes:
@ -50,7 +47,7 @@ body:
attributes:
value: |
It's really important to provide pertinent logs
Please read https://docs.gitea.io/en-us/logging-configuration/#debugging-problems
Please read https://docs.gitea.com/administration/logging-config#collecting-logs-for-help
In addition, if your problem relates to git commands set `RUN_MODE=dev` at the top of app.ini
- type: input
id: logs
@ -89,6 +86,6 @@ body:
description: What database system are you running?
options:
- PostgreSQL
- MySQL
- MySQL/MariaDB
- MSSQL
- SQLite

View File

@ -8,9 +8,9 @@ contact_links:
about: Please ask questions and discuss configuration or deployment problems here.
- name: Discourse Forum
url: https://discourse.gitea.io
about: Questions and configuration or deployment problems can also be discussed on our forum.
about: Questions and configuration or deployment problems can also be discussed on our forum.
- name: Frequently Asked Questions
url: https://docs.gitea.io/en-us/faq
url: https://docs.gitea.com/help/faq
about: Please check if your question isn't mentioned here.
- name: Crowdin Translations
url: https://crowdin.com/project/gitea

View File

@ -13,12 +13,12 @@ body:
2. Please ask questions or configuration/deploy problems on our Discord
server (https://discord.gg/gitea) or forum (https://discourse.gitea.io).
3. Please take a moment to check that your issue doesn't already exist.
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.io/en-us/faq)
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.com/help/faq)
5. Please give all relevant information below for bug reports, because
incomplete details will be handled as an invalid report.
6. In particular it's really important to provide pertinent logs. If you are certain that this is a javascript
error, show us the javascript console. If the error appears to relate to Gitea the server you must also give us
DEBUG level logs. (See https://docs.gitea.io/en-us/logging-configuration/#debugging-problems)
DEBUG level logs. (See https://docs.gitea.com/administration/logging-config#collecting-logs-for-help)
- type: textarea
id: description
attributes:

View File

@ -43,6 +43,8 @@ jobs:
- "go.mod"
- "go.sum"
- "Makefile"
- ".golangci.yml"
- ".editorconfig"
frontend:
- "**/*.js"
@ -51,16 +53,21 @@ jobs:
- "package.json"
- "package-lock.json"
- "Makefile"
- ".eslintrc.yaml"
- ".stylelintrc.yaml"
- ".npmrc"
docs:
- "**/*.md"
- "docs/**"
- ".markdownlint.yaml"
actions:
- ".github/workflows/*"
templates:
- "templates/**/*.tmpl"
- "pyproject.toml"
- "poetry.lock"
docker:
@ -72,3 +79,6 @@ jobs:
swagger:
- "templates/swagger/v1_json.tmpl"
- "Makefile"
- "package.json"
- "package-lock.json"
- ".spectral.yml"

View File

@ -29,7 +29,7 @@ linters:
fast: false
run:
go: "1.20"
go: "1.21"
timeout: 10m
skip-dirs:
- node_modules
@ -75,7 +75,7 @@ linters-settings:
- name: modifies-value-receiver
gofumpt:
extra-rules: true
lang-version: "1.20"
lang-version: "1.21"
depguard:
rules:
main:

View File

@ -60,7 +60,7 @@
## Introduction
This document explains how to contribute changes to the Gitea project. \
It assumes you have followed the [installation instructions](https://docs.gitea.io/en-us/). \
It assumes you have followed the [installation instructions](https://docs.gitea.com/category/installation). \
Sensitive security-related issues should be reported to [security@gitea.io](mailto:security@gitea.io).
For configuring IDEs for Gitea development, see the [contributed IDE configurations](contrib/ide/).

View File

@ -79,14 +79,14 @@ or if SQLite support is required:
The `build` target is split into two sub-targets:
- `make backend` which requires [Go Stable](https://go.dev/dl/), required version is defined in [go.mod](/go.mod).
- `make frontend` which requires [Node.js LTS](https://nodejs.org/en/download/) or greater and Internet connectivity to download npm dependencies.
- `make backend` which requires [Go Stable](https://go.dev/dl/), the required version is defined in [go.mod](/go.mod).
- `make frontend` which requires [Node.js LTS](https://nodejs.org/en/download/) or greater.
When building from the official source tarballs which include pre-built frontend files, the `frontend` target will not be triggered, making it possible to build without Node.js and Internet connectivity.
Internet connectivity is required to download the go and npm modules. When building from the official source tarballs which include pre-built frontend files, the `frontend` target will not be triggered, making it possible to build without Node.js.
Parallelism (`make -j <num>`) is not supported.
More info: https://docs.gitea.io/en-us/install-from-source/
More info: https://docs.gitea.com/installation/install-from-source
## Using

View File

@ -68,7 +68,7 @@ Gitea 的首要目标是创建一个极易安装,运行非常快速,安装
## 文档
关于如何安装请访问我们的 [文档站](https://docs.gitea.io/zh-cn/),如果没有找到对应的文档,你也可以通过 [Discord - 英文](https://discord.gg/gitea) 和 QQ群 328432459 来和我们交流。
关于如何安装请访问我们的 [文档站](https://docs.gitea.com/zh-cn/category/installation),如果没有找到对应的文档,你也可以通过 [Discord - 英文](https://discord.gg/gitea) 和 QQ群 328432459 来和我们交流。
## 贡献流程

View File

@ -12,6 +12,7 @@ import (
"path/filepath"
"strings"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/setting"
)
@ -58,7 +59,7 @@ func main() {
// use old en-US as the base, and copy the new translations to the old locales
enUsOld := inisOld["options/locale/locale_en-US.ini"]
brokenWarned := map[string]bool{}
brokenWarned := make(container.Set[string])
for path, iniOld := range inisOld {
if iniOld == enUsOld {
continue
@ -77,7 +78,7 @@ func main() {
broken := oldStr != "" && strings.Count(oldStr, "%") != strings.Count(newStr, "%")
broken = broken || strings.Contains(oldStr, "\n") || strings.Contains(oldStr, "\n")
if broken {
brokenWarned[secOld.Name()+"."+keyEnUs.Name()] = true
brokenWarned.Add(secOld.Name() + "." + keyEnUs.Name())
fmt.Println("----")
fmt.Printf("WARNING: skip broken locale: %s , [%s] %s\n", path, secEnUS.Name(), keyEnUs.Name())
fmt.Printf("\told: %s\n", strings.ReplaceAll(oldStr, "\n", "\\n"))
@ -103,7 +104,7 @@ func main() {
broken = broken || strings.HasPrefix(str, "`\"")
broken = broken || strings.Count(str, `"`)%2 == 1
broken = broken || strings.Count(str, "`")%2 == 1
if broken && !brokenWarned[sec.Name()+"."+key.Name()] {
if broken && !brokenWarned.Contains(sec.Name()+"."+key.Name()) {
fmt.Printf("WARNING: found broken locale: %s , [%s] %s\n", path, sec.Name(), key.Name())
fmt.Printf("\tstr: %s\n", strings.ReplaceAll(str, "\n", "\\n"))
fmt.Println("----")

View File

@ -15,6 +15,8 @@ import (
"regexp"
"sort"
"strings"
"code.gitea.io/gitea/modules/container"
)
// regexp is based on go-license, excluding README and NOTICE
@ -55,20 +57,14 @@ func main() {
// yml
//
// It could be removed once we have a better regex.
excludedExt := map[string]bool{
".gitignore": true,
".go": true,
".mod": true,
".sum": true,
".toml": true,
".yml": true,
}
excludedExt := container.SetOf(".gitignore", ".go", ".mod", ".sum", ".toml", ".yml")
var paths []string
err := filepath.WalkDir(base, func(path string, entry fs.DirEntry, err error) error {
if err != nil {
return err
}
if entry.IsDir() || !licenseRe.MatchString(entry.Name()) || excludedExt[filepath.Ext(entry.Name())] {
if entry.IsDir() || !licenseRe.MatchString(entry.Name()) || excludedExt.Contains(filepath.Ext(entry.Name())) {
return nil
}
paths = append(paths, path)

View File

@ -43,7 +43,7 @@ Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
},
&cli.IntFlag{
Name: "rsa-bits",
Value: 2048,
Value: 3072,
Usage: "Size of RSA key to generate. Ignored if --ecdsa-curve is set",
},
&cli.StringFlag{

View File

@ -7,7 +7,7 @@
dashboardTimezone: 'default',
dashboardRefresh: '1m',
// please see https://docs.gitea.io/en-us/config-cheat-sheet/#metrics-metrics
// please see https://docs.gitea.com/administration/config-cheat-sheet#metrics-metrics
// Show issue by repository metrics with format gitea_issues_by_repository{repository="org/repo"} 5.
// Requires Gitea 1.16.0 with ENABLED_ISSUE_BY_REPOSITORY set to true.
showIssuesByRepository: true,

View File

@ -37,7 +37,7 @@
<h3>With your Consent</h3>
<p>We share your User Personal Information, if you consent, after letting you know what information will be shared, with whom, and why. For example, if you allow third party applications to access your Account using <a href="https://docs.gitea.io/en-us/oauth2-provider/">OAuth2 providers</a>, we share all information associated with your Account, including private repos and organizations. You may also direct us through your action on Your Gitea Instance to share your User Personal Information, such as when joining an Organization.</p>
<p>We share your User Personal Information, if you consent, after letting you know what information will be shared, with whom, and why. For example, if you allow third party applications to access your Account using <a href="https://docs.gitea.com/development/oauth2-provider">OAuth2 providers</a>, we share all information associated with your Account, including private repos and organizations. You may also direct us through your action on Your Gitea Instance to share your User Personal Information, such as when joining an Organization.</p>
<h3>With Service Providers</h3>
@ -144,7 +144,7 @@
<h3>Data Portability</h3>
<p>As a Your Gitea Instance User, you can always take your data with you. You can clone your repositories to your computer, or you can <a href="https://docs.gitea.io/en-us/migrations-interfaces/">perform migrations using the provided interfaces</a>, for example.</p>
<p>As a Your Gitea Instance User, you can always take your data with you. You can clone your repositories to your computer, or you can <a href="https://docs.gitea.com/development/migrations-interfaces">perform migrations using the provided interfaces</a>, for example.</p>
<h3>Data Retention and Deletion of Data</h3>
@ -183,7 +183,7 @@
<h2>Changes to this Privacy Policy</h2>
<p>Although most changes are likely to be minor, Your Gitea Instance may change our Privacy Statement from time to time. We will provide notification to Users of material changes to this Privacy Statement through our Website at least 30 days prior to the change taking effect by posting a notice on our home page or sending email to the primary email address specified in your account.</p>
<p>Although most changes are likely to be minor, Your Gitea Instance may change our Privacy Statement from time to time. We will provide notification to Users of material changes to this Privacy Statement through our Website at least 30 days prior to the change taking effect by posting a notice on our home page or sending email to the primary email address specified in your account.</p>
<h2>Contact</h2>

View File

@ -1339,7 +1339,7 @@ LEVEL = Info
;; Define allowed algorithms and their minimum key length (use -1 to disable a type)
;ED25519 = 256
;ECDSA = 256
;RSA = 2047 ; we allow 2047 here because an otherwise valid 2048 bit RSA key can be reported as having 2047 bit length
;RSA = 3071 ; we allow 3071 here because an otherwise valid 3072 bit RSA key can be reported as having 3071 bit length
;DSA = -1 ; set to 1024 to switch on
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -4,4 +4,4 @@ Dockerfile is found in root of repository.
Docker image can be found on [docker hub](https://hub.docker.com/r/gitea/gitea)
Documentation on using docker image can be found on [Gitea Docs site](https://docs.gitea.io/en-us/install-with-docker/)
Documentation on using docker image can be found on [Gitea Docs site](https://docs.gitea.com/installation/install-with-docker-rootless)

View File

@ -11,7 +11,7 @@ fi
if [ ! -f /data/ssh/ssh_host_rsa_key ]; then
echo "Generating /data/ssh/ssh_host_rsa_key..."
ssh-keygen -t rsa -b 2048 -f /data/ssh/ssh_host_rsa_key -N "" > /dev/null
ssh-keygen -t rsa -b 3072 -f /data/ssh/ssh_host_rsa_key -N "" > /dev/null
fi
if [ ! -f /data/ssh/ssh_host_ecdsa_key ]; then

View File

@ -313,7 +313,7 @@ directory and will overwrite any existing files.
- `--ecdsa-curve value`: ECDSA curve to use to generate a key. Optional. Valid options
are P224, P256, P384, P521.
- `--rsa-bits value`: Size of RSA key to generate. Optional. Ignored if --ecdsa-curve is
set. (default: 2048).
set. (default: 3072).
- `--start-date value`: Creation date. Optional. (format: `Jan 1 15:04:05 2011`).
- `--duration value`: Duration which the certificate is valid for. Optional. (default: 8760h0m0s)
- `--ca`: If provided, this cert generates it's own certificate authority. Optional.

View File

@ -295,7 +295,7 @@ menu:
- 选项:
- `--host value`逗号分隔的主机名和IP地址列表此证书适用于这些主机。支持使用通配符。必填。
- `--ecdsa-curve value`用于生成密钥的ECDSA曲线。可选。有效选项为P224、P256、P384、P521。
- `--rsa-bits value`要生成的RSA密钥的大小。可选。如果设置了--ecdsa-curve则忽略此选项。默认值2048)。
- `--rsa-bits value`要生成的RSA密钥的大小。可选。如果设置了--ecdsa-curve则忽略此选项。默认值3072)。
- `--start-date value`:证书的创建日期。可选。(格式:`Jan 1 15:04:05 2011`)。
- `--duration value`证书有效期。可选。默认值8760h0m0s
- `--ca`:如果提供此选项,则证书将生成自己的证书颁发机构。可选。

View File

@ -681,7 +681,7 @@ Define allowed algorithms and their minimum key length (use -1 to disable a type
- `ED25519`: **256**
- `ECDSA`: **256**
- `RSA`: **2047**: We set 2047 here because an otherwise valid 2048 RSA key can be reported as 2047 length.
- `RSA`: **3071**: We set 3071 here because an otherwise valid 3072 RSA key can be reported as 3071 length.
- `DSA`: **-1**: DSA is now disabled by default. Set to **1024** to re-enable but ensure you may need to reconfigure your SSHD provider
## Webhook (`webhook`)

View File

@ -648,7 +648,7 @@ Gitea 创建以下非唯一队列:
- `ED25519`**256**
- `ECDSA`**256**
- `RSA`**2047**我们在这里设置为2047因为一个其他方面有效的2048 RSA密钥可能被报告为2047长度。
- `RSA`**3071**我们在这里设置为2047因为一个其他方面有效的3072 RSA密钥可能被报告为3071长度。
- `DSA`**-1**默认情况下禁用DSA。设置为**1024**以重新启用但请注意可能需要重新配置您的SSHD提供者
## Webhook (`webhook`)

View File

@ -36,7 +36,7 @@ Application settings can be found in file `CustomConf` which is by default,
Again `gitea help` will allow you review this variable and you can override it using the
`--config` option on the `gitea` binary.
- [Quick Cheat Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/)
- [Quick Cheat Sheet](administration/config-cheat-sheet.md)
- [Complete List](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini)
If the `CustomPath` folder can't be found despite checking `gitea help`, check the `GITEA_CUSTOM`
@ -44,7 +44,7 @@ environment variable; this can be used to override the default path to something
`GITEA_CUSTOM` might, for example, be set by an init script. You can check whether the value
is set under the "Configuration" tab on the site administration page.
- [List of Environment Variables](https://docs.gitea.io/en-us/environment-variables/)
- [List of Environment Variables](administration/environment-variables.md)
**Note:** Gitea must perform a full restart to see configuration changes.
@ -84,7 +84,7 @@ for C++ repositories, we want to replace `options/gitignore/C++`. To do this, a
must be placed in `$GITEA_CUSTOM/options/gitignore/C++` (see about the location of the `CustomPath`
directory at the top of this document).
Every single page of Gitea can be changed. Dynamic content is generated using [go templates](https://golang.org/pkg/html/template/),
Every single page of Gitea can be changed. Dynamic content is generated using [go templates](https://pkg.go.dev/html/template),
which can be modified by placing replacements below the `$GITEA_CUSTOM/templates` directory.
To obtain any embedded file (including templates), the [`gitea embedded` tool](administration/cmd-embedded.md) can be used. Alternatively, they can be found in the [`templates`](https://github.com/go-gitea/gitea/tree/main/templates) directory of Gitea source (Note: the example link is from the `main` branch. Make sure to use templates compatible with the release you are using).
@ -108,7 +108,7 @@ just place it under your "$GITEA_CUSTOM/public/assets/" directory (for instance
To match the current style, the link should have the class name "item", and you can use `{{AppSubUrl}}` to get the base URL:
`<a class="item" href="{{AppSubUrl}}/assets/impressum.html">Impressum</a>`
For more information, see [Adding Legal Pages](https://docs.gitea.io/en-us/adding-legal-pages).
For more information, see [Adding Legal Pages](administration/adding-legal-pages.md).
You can add new tabs in the same way, putting them in `extra_tabs.tmpl`.
The exact HTML needed to match the style of other tabs is in the file
@ -371,10 +371,10 @@ A full list of supported emoji's is at [emoji list](https://gitea.com/gitea/gite
## Customizing the look of Gitea
The default built-in themes are `gitea` (light), `arc-green` (dark), and `auto` (chooses light or dark depending on operating system settings).
The default theme can be changed via `DEFAULT_THEME` in the [ui](https://docs.gitea.io/en-us/config-cheat-sheet/#ui-ui) section of `app.ini`.
The default theme can be changed via `DEFAULT_THEME` in the [ui](administration/config-cheat-sheet.md#ui-ui) section of `app.ini`.
Gitea also has support for user themes, which means every user can select which theme should be used.
The list of themes a user can choose from can be configured with the `THEMES` value in the [ui](https://docs.gitea.io/en-us/config-cheat-sheet/#ui-ui) section of `app.ini`.
The list of themes a user can choose from can be configured with the `THEMES` value in the [ui](administration/config-cheat-sheet.md#ui-ui) section of `app.ini`.
To make a custom theme available to all users:

View File

@ -23,13 +23,13 @@ Gitea 引用 `custom` 目录中的自定义配置文件来覆盖配置、模板
将会自动创建包括 `custom/` 在内的必要应用目录,应用本身的配置存放在
`custom/conf/app.ini` 当中。在发行版中可能会以 `/etc/gitea/` 的形式为 `custom` 设置一个符号链接,查看配置详情请移步:
- [快速备忘单](https://docs.gitea.io/en-us/config-cheat-sheet/)
- [快速备忘单](administration/config-cheat-sheet.md)
- [完整配置清单](https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini)
如果您在 binary 同目录下无法找到 `custom` 文件夹,请检查您的 `GITEA_CUSTOM`
环境变量配置, 因为它可能被配置到了其他地方(可能被一些启动脚本设置指定了目录)。
- [环境变量清单](https://docs.gitea.io/en-us/specific-variables/)
- [环境变量清单](administration/environment-variables.md)
**注:** 必须完全重启 Gitea 以使配置生效。
@ -87,4 +87,4 @@ Gitea 引用 `custom` 目录中的自定义配置文件来覆盖配置、模板
## 更改 Gitea 外观
Gitea 目前由两种内置主题,分别为默认 `gitea` 主题和深色主题 `arc-green`,您可以通过修改
`app.ini` [ui](https://docs.gitea.io/en-us/config-cheat-sheet/#ui-ui) 部分的 `DEFAULT_THEME` 的值来变更至一个可用的 Gitea 外观。
`app.ini` [ui](administration/config-cheat-sheet.md#ui-ui) 部分的 `DEFAULT_THEME` 的值来变更至一个可用的 Gitea 外观。

View File

@ -119,7 +119,7 @@ proxy_set_header X-Real-IP $remote_addr;
The security options in `app.ini` need to be adjusted to allow the interpretation of the headers
as well as the list of IP addresses and networks that describe trusted proxy servers
(See the [configuration cheat sheet](https://docs.gitea.io/en-us/config-cheat-sheet/#security-security) for more information).
(See the [configuration cheat sheet](administration/config-cheat-sheet.md#security-security) for more information).
```
REVERSE_PROXY_LIMIT = 1

View File

@ -91,4 +91,4 @@ REVERSE_PROXY_TRUSTED_PROXIES = 127.0.0.0/8,::1/128
`REVERSE_PROXY_LIMIT` 限制反向代理服务器的层数,设置为 `0` 表示不使用这些标头。
`REVERSE_PROXY_TRUSTED_PROXIES` 表示受信任的反向代理服务器网络地址,
经过该网络地址转发来的流量会经过解析 `X-Real-IP` 头部得到真实客户端地址。
(参考 [configuration cheat sheet](https://docs.gitea.io/en-us/config-cheat-sheet/#security-security)
(参考 [configuration cheat sheet](administration/config-cheat-sheet.md#security-security)

View File

@ -18,7 +18,7 @@ menu:
# Mail templates
To craft the e-mail subject and contents for certain operations, Gitea can be customized by using templates. The templates
for these functions are located under the [`custom` directory](https://docs.gitea.io/en-us/customizing-gitea/).
for these functions are located under the [`custom` directory](administration/customizing-gitea.md).
Gitea has an internal template that serves as default in case there's no custom alternative.
Custom templates are loaded when Gitea starts. Changes made to them are not recognized until Gitea is restarted again.
@ -165,7 +165,7 @@ If the template fails to render, it will be noticed only at the moment the mail
A default subject is used if the subject template fails, and whatever was rendered successfully
from the the _mail body_ is used, disregarding the rest.
Please check [Gitea's logs](https://docs.gitea.io/en-us/logging-configuration/) for error messages in case of trouble.
Please check [Gitea's logs](administration/logging-config.md) for error messages in case of trouble.
## Example

View File

@ -17,7 +17,7 @@ menu:
# 邮件模板
为了定制特定操作的电子邮件主题和内容,可以使用模板来自定义 Gitea。这些功能的模板位于 [`custom` 目录](https://docs.gitea.io/en-us/customizing-gitea/) 下。
为了定制特定操作的电子邮件主题和内容,可以使用模板来自定义 Gitea。这些功能的模板位于 [`custom` 目录](administration/customizing-gitea.md) 下。
如果没有自定义的替代方案Gitea 将使用内部模板作为默认模板。
自定义模板在 Gitea 启动时加载。对它们的更改在 Gitea 重新启动之前不会被识别。
@ -148,7 +148,7 @@ _主题_ 和 _邮件正文_ 由 [Golang的模板引擎](https://golang.org/pkg/t
如果模板无法呈现,则只有在发送邮件时才会注意到。
如果主题模板失败,将使用默认主题,如果从 _邮件正文_ 中成功呈现了任何内容,则将使用该内容,忽略其他内容。
如果遇到问题,请检查 [Gitea的日志](https://docs.gitea.io/en-us/logging-configuration/) 以获取错误消息。
如果遇到问题,请检查 [Gitea的日志](administration/logging-config.md) 以获取错误消息。
## 示例

View File

@ -19,7 +19,7 @@ menu:
## Setting up the repository indexer
Gitea can search through the files of the repositories by enabling this function in your [`app.ini`](https://docs.gitea.io/en-us/config-cheat-sheet/):
Gitea can search through the files of the repositories by enabling this function in your [`app.ini`](administration/config-cheat-sheet.md):
```ini
[indexer]

View File

@ -19,7 +19,7 @@ menu:
## 设置仓库索引器
通过在您的 [`app.ini`](https://docs.gitea.io/en-us/config-cheat-sheet/) 中启用此功能Gitea 可以通过仓库的文件进行搜索:
通过在您的 [`app.ini`](administration/config-cheat-sheet.md) 中启用此功能Gitea 可以通过仓库的文件进行搜索:
```ini
[indexer]

View File

@ -21,7 +21,7 @@ menu:
By default, `ENABLE_SWAGGER` is true, and
`MAX_RESPONSE_ITEMS` is set to 50. See [Config Cheat
Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/) for more
Sheet](administration/config-cheat-sheet.md) for more
information.
## Authentication
@ -76,7 +76,7 @@ interface: `Settings | Applications | Generate New Token`.
## OAuth2 Provider
Access tokens obtained from Gitea's [OAuth2 provider](https://docs.gitea.io/en-us/oauth2-provider) are accepted by these methods:
Access tokens obtained from Gitea's [OAuth2 provider](development/oauth2-provider.md) are accepted by these methods:
- `Authorization bearer ...` header in HTTP headers
- `token=...` parameter in URL query string

View File

@ -20,7 +20,7 @@ menu:
## 开启/配置 API 访问
通常情况下, `ENABLE_SWAGGER` 默认开启并且参数 `MAX_RESPONSE_ITEMS` 默认为 50。您可以从 [Config Cheat
Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/) 中获取更多配置相关信息。
Sheet](administration/config-cheat-sheet.md) 中获取更多配置相关信息。
## 通过 API 认证

View File

@ -148,7 +148,7 @@ For public clients, a redirect URI of a loopback IP address such as `http://127.
The `REDIRECT_URI` in the `access_token` request must match the `REDIRECT_URI` in the `authorize` request.
3. Use the `access_token` to make [API requests](https://docs.gitea.io/en-us/api-usage#oauth2) to access the user's resources.
3. Use the `access_token` to make [API requests](development/api-usage.md#oauth2-provider) to access the user's resources.
### Public client (PKCE)
@ -210,4 +210,4 @@ After you have generated this values, you can continue with your request.
The `REDIRECT_URI` in the `access_token` request must match the `REDIRECT_URI` in the `authorize` request.
3. Use the `access_token` to make [API requests](https://docs.gitea.io/en-us/api-usage#oauth2) to access the user's resources.
3. Use the `access_token` to make [API requests](development/api-usage.md#oauth2-provider) to access the user's resources.

View File

@ -134,4 +134,4 @@ Gitea 支持私密和公共客户端类型,[参见 RFC 6749](https://datatrack
`access_token` 请求中的 `REDIRECT_URI` 必须与 `authorize` 请求中的 `REDIRECT_URI` 相符。
3. 使用 `access_token` 来构造 [API 请求](https://docs.gitea.io/en-us/api-usage#oauth2) 以读写用户的资源。
3. 使用 `access_token` 来构造 [API 请求](development/api-usage.md#oauth2-provider) 以读写用户的资源。

View File

@ -93,4 +93,4 @@ Gitea 支援作為 OAuth2 提供者,能讓第三方程式能在使用者同意
`access_token` 請求中的 `REDIRECT_URI` 必須符合 `authorize` 請求中的 `REDIRECT_URI`
1. 發送 [API requests](https://docs.gitea.io/en-us/api-usage#oauth2) 時使用 `access_token` 以存取使用者的資源。
1. 發送 [API requests](development/api-usage.md#oauth2-provider) 時使用 `access_token` 以存取使用者的資源。

View File

@ -22,34 +22,57 @@ menu:
- [Discourse Forum](https://discourse.gitea.io/)
- [Matrix](https://matrix.to/#/#gitea-space:matrix.org)
- NOTE: Most of the Matrix channels are bridged with their counterpart in Discord and may experience some degree of flakiness with the bridge process.
- Chinese Support
- [Discourse Chinese Category](https://discourse.gitea.io/c/5-category/5)
- QQ Group 328432459
# Bug Report
If you found a bug, please [create an issue on GitHub](https://github.com/go-gitea/gitea/issues).
**NOTE:** When asking for support, it may be a good idea to have the following available so that the person helping has all the info they need:
1. Your `app.ini` (with any sensitive data scrubbed as necessary).
2. The Gitea logs, and any other appropriate log files for the situation.
- When using systemd, use `journalctl --lines 1000 --unit gitea` to collect logs.
- When using docker, use `docker logs --tail 1000 <gitea-container>` to collect logs.
- By default, the logs are outputted to console. If you need to collect logs from files,
you could copy the following config into your `app.ini` (remove all other `[log]` sections),
then you can find the `*.log` files in Gitea's log directory (default: `%(GITEA_WORK_DIR)/log`).
```ini
; To show all SQL logs, you can also set LOG_SQL=true in the [database] section
[log]
LEVEL=debug
MODE=console,file
```
3. Any error messages you are seeing.
4. When possible, try to replicate the issue on [try.gitea.io](https://try.gitea.io) and include steps so that others can reproduce the issue.
- This will greatly improve the chance that the root of the issue can be quickly discovered and resolved.
5. If you encounter slow/hanging/deadlock problems, please report the stack trace when the problem occurs.
2. Any error messages you are seeing.
3. The Gitea logs, and all other related logs for the situation.
- It's more useful to collect `trace` / `debug` level logs (see the next section).
- When using systemd, use `journalctl --lines 1000 --unit gitea` to collect logs.
- When using docker, use `docker logs --tail 1000 <gitea-container>` to collect logs.
4. Reproducible steps so that others could reproduce and understand the problem more quickly and easily.
- [try.gitea.io](https://try.gitea.io) could be used to reproduce the problem.
5. If you encounter slow/hanging/deadlock problems, please report the stacktrace when the problem occurs.
Go to the "Site Admin" -> "Monitoring" -> "Stacktrace" -> "Download diagnosis report".
## Bugs
# Advanced Bug Report Tips
If you found a bug, please create an [issue on GitHub](https://github.com/go-gitea/gitea/issues).
## More Config Options for Logs
## Chinese Support
By default, the logs are outputted to console with `info` level.
If you need to set log level and/or collect logs from files,
you could just copy the following config into your `app.ini` (remove all other `[log]` sections),
then you will find the `*.log` files in Gitea's log directory (default: `%(GITEA_WORK_DIR)/log`).
Support for the Chinese language is provided at [Our discourse](https://discourse.gitea.io/c/5-category/5) or QQ Group 328432459.
```ini
; To show all SQL logs, you can also set LOG_SQL=true in the [database] section
[log]
LEVEL=debug
MODE=console,file
```
## Collecting Stacktrace by Command Line
Gitea could use Golang's pprof handler and toolchain to collect stacktrace and other runtime information.
If the web UI stops working, you could try to collect the stacktrace by command line:
1. Set `app.ini`:
```
[server]
ENABLE_PPROF = true
```
2. Restart Gitea
3. Try to trigger the bug, when the requests get stuck for a while,
use `curl` or browser to visit: `http://127.0.0.1:6060/debug/pprof/goroutine?debug=1` to get the stacktrace.

View File

@ -28,7 +28,7 @@ menu:
3. 您看到的任何錯誤訊息
4. 儘可能地在 [try.gitea.io](https://try.gitea.io) 觸發您的問題並記下步驟,以便其他人能重現那個問題。
- 這將讓我們更有機會快速地找出問題的根源並解決它。
5. 堆棧跟踪,[請參考英文文檔](https://docs.gitea.io/en-us/seek-help/)
5. 堆棧跟踪,[請參考英文文檔](https://docs.gitea.com/help/support)
## 錯誤回報

View File

@ -254,7 +254,7 @@ documented above, please note that `db` must be used as the database hostname.
# Customization
Customization files described [here](https://docs.gitea.io/en-us/customizing-gitea/) should
Customization files described [here](administration/customizing-gitea.md) should
be placed in `/var/lib/gitea/custom` directory. If using host volumes, it's quite easy to access these
files; for named volumes, this is done through another container or by direct access at
`/var/lib/docker/volumes/gitea_gitea/_/var_lib_gitea`. The configuration file will be saved at
@ -313,7 +313,7 @@ services:
- GITEA__mailer__PASSWD="""${GITEA__mailer__PASSWD:?GITEA__mailer__PASSWD not set}"""
```
To set required TOKEN and SECRET values, consider using Gitea's built-in [generate utility functions](https://docs.gitea.io/en-us/command-line/#generate).
To set required TOKEN and SECRET values, consider using Gitea's built-in [generate utility functions](administration/command-line.md#generate).
# SSH Container Passthrough
@ -342,7 +342,7 @@ Once the wrapper is in place, you can make it the shell for the `git` user:
sudo usermod -s /usr/local/bin/gitea-shell git
```
Now that all the SSH commands are forwarded to the container, you need to set up the SSH authentication on the host. This is done by leveraging the [SSH AuthorizedKeysCommand](https://docs.gitea.io/en-us/command-line/#keys) to match the keys against those accepted by Gitea. Add the following block to `/etc/ssh/sshd_config`, on the host:
Now that all the SSH commands are forwarded to the container, you need to set up the SSH authentication on the host. This is done by leveraging the [SSH AuthorizedKeysCommand](administration/command-line.md#keys) to match the keys against those accepted by Gitea. Add the following block to `/etc/ssh/sshd_config`, on the host:
```bash
Match User git

View File

@ -281,7 +281,7 @@ services:
- GITEA__mailer__PASSWD="""${GITEA__mailer__PASSWD:?GITEA__mailer__PASSWD not set}"""
```
要设置所需的 TOKEN 和 SECRET 值,可以使用 Gitea 的内置[生成使用函数](https://docs.gitea.io/en-us/command-line/#generate).
要设置所需的 TOKEN 和 SECRET 值,可以使用 Gitea 的内置[生成使用函数](administration/command-line.md#generate).
# SSH 容器透传
@ -310,7 +310,7 @@ sudo chmod +x /usr/local/bin/gitea-shell
sudo usermod -s /usr/local/bin/gitea-shell git
```
现在,所有的 SSH 命令都会被转发到容器,您需要在主机上设置 SSH 认证。这可以通过利用 [SSH AuthorizedKeysCommand](https://docs.gitea.io/en-us/command-line/#keys) 来匹配 Gitea 接受的密钥。在主机的 `/etc/ssh/sshd_config` 文件中添加以下代码块:
现在,所有的 SSH 命令都会被转发到容器,您需要在主机上设置 SSH 认证。这可以通过利用 [SSH AuthorizedKeysCommand](administration/command-line.md#keys) 来匹配 Gitea 接受的密钥。在主机的 `/etc/ssh/sshd_config` 文件中添加以下代码块:
```bash
Match User git

View File

@ -261,7 +261,7 @@ documented above, please note that `db` must be used as the database hostname.
## Customization
Customization files described [here](https://docs.gitea.io/en-us/customizing-gitea/) should
Customization files described [here](administration/customizing-gitea.md) should
be placed in `/data/gitea` directory. If using host volumes, it's quite easy to access these
files; for named volumes, this is done through another container or by direct access at
`/var/lib/docker/volumes/gitea_gitea/_data`. The configuration file will be saved at
@ -309,7 +309,7 @@ services:
- GITEA__mailer__PASSWD="""${GITEA__mailer__PASSWD:?GITEA__mailer__PASSWD not set}"""
```
Gitea will generate new secrets/tokens for every new installation automatically and write them into the app.ini. If you want to set the secrets/tokens manually, you can use the following docker commands to use of Gitea's built-in [generate utility functions](https://docs.gitea.io/en-us/command-line/#generate). Do not lose/change your SECRET_KEY after the installation, otherwise the encrypted data can not be decrypted anymore.
Gitea will generate new secrets/tokens for every new installation automatically and write them into the app.ini. If you want to set the secrets/tokens manually, you can use the following docker commands to use of Gitea's built-in [generate utility functions](administration/command-line.md#generate). Do not lose/change your SECRET_KEY after the installation, otherwise the encrypted data can not be decrypted anymore.
The following commands will output a new `SECRET_KEY` and `INTERNAL_TOKEN` to `stdout`, which you can then place in your environment variables.
@ -553,7 +553,7 @@ In this option, the idea is that the host SSH uses an `AuthorizedKeysCommand` in
Now all attempts to login as the `git` user on the host will be forwarded to the docker - including the `SSH_ORIGINAL_COMMAND`. We now need to set-up SSH authentication on the host.
We will do this by leveraging the [SSH AuthorizedKeysCommand](https://docs.gitea.io/en-us/command-line/#keys) to match the keys against those accepted by Gitea.
We will do this by leveraging the [SSH AuthorizedKeysCommand](administration/command-line.md#keys) to match the keys against those accepted by Gitea.
Add the following block to `/etc/ssh/sshd_config`, on the host:

View File

@ -103,7 +103,7 @@ Vous devriez maintenant avoir deux conteneurs Docker pour Gitea et PostgreSQL pl
# Personnalisation
Les fichier personnalisés ([voir les instructions](https://docs.gitea.io/en-us/customizing-gitea/)) peuvent être placés dans le répertoire `/data/gitea`.
Les fichier personnalisés ([voir les instructions](administration/customizing-gitea.md)) peuvent être placés dans le répertoire `/data/gitea`.
Le fichier de configuration sera sauvegardé à l'emplacement suivant : `/data/gitea/conf/app.ini`

View File

@ -260,7 +260,7 @@ MySQL 或 PostgreSQL 容器将需要分别创建。
## 自定义
[此处](https://docs.gitea.io/zh-cn/customizing-gitea/)描述的定制文件应放在 `/data/gitea` 目录中。如果使用主机卷,则访问这些文件非常容易;对于命名卷,可以通过另一个容器或通过直接访问 `/var/lib/docker/volumes/gitea_gitea/_data` 来完成。安装后,配置文件将保存在 `/data/gitea/conf/app.ini` 中。
[此处](administration/customizing-gitea.md)描述的定制文件应放在 `/data/gitea` 目录中。如果使用主机卷,则访问这些文件非常容易;对于命名卷,可以通过另一个容器或通过直接访问 `/var/lib/docker/volumes/gitea_gitea/_data` 来完成。安装后,配置文件将保存在 `/data/gitea/conf/app.ini` 中。
## 升级
@ -293,7 +293,7 @@ services:
- GITEA__mailer__PASSWD="""${GITEA__mailer__PASSWD:?GITEA__mailer__PASSWD not set}"""
```
Gitea 将为每次新安装自动生成新的 `SECRET_KEY` 并将它们写入 `app.ini`。 如果您想手动设置 `SECRET_KEY`,您可以使用以下 docker 命令来使用 Gitea 内置的[方法](https://docs.gitea.io/en-us/command-line/#generate)生成 `SECRET_KEY`。 安装后请妥善保管您的 `SECRET_KEY`,如若丢失则无法解密已加密的数据。
Gitea 将为每次新安装自动生成新的 `SECRET_KEY` 并将它们写入 `app.ini`。 如果您想手动设置 `SECRET_KEY`,您可以使用以下 docker 命令来使用 Gitea 内置的[方法](administration/command-line.md#generate)生成 `SECRET_KEY`。 安装后请妥善保管您的 `SECRET_KEY`,如若丢失则无法解密已加密的数据。
以下命令将向 `stdout` 输出一个新的 `SECRET_KEY``INTERNAL_TOKEN`,然后您可以将其放入环境变量中。

View File

@ -112,7 +112,7 @@ You can configure your Gitea instance to fetch actions or images from your intra
In fact, your Gitea instance can serve as both the actions marketplace and the image registry.
You can mirror actions repositories from GitHub to your Gitea instance, and use them as normal.
And [Gitea Container Registry](https://docs.gitea.io/en-us/usage/packages/container/) can be used as a Docker image registry.
And [Gitea Container Registry](usage/packages/container.md) can be used as a Docker image registry.
### Connection 4, job containers to internet

View File

@ -113,7 +113,7 @@ act runner 必须能够连接到Gitea以接收任务并发送执行结果回来
实际上您的Gitea实例可以同时充当 Actions 市场和镜像注册表。
您可以将GitHub上的Actions仓库镜像到您的Gitea实例并将其用作普通Actions。
而 [Gitea 容器注册表](https://docs.gitea.io/en-us/usage/packages/container/) 可用作Docker镜像注册表。
而 [Gitea 容器注册表](usage/packages/container.md) 可用作Docker镜像注册表。
### 连接 4Job容器到互联网

View File

@ -61,7 +61,7 @@ For example:
Be careful, the `https://` or `http://` prefix is necessary!
Alternatively, if you want your runners to download actions from GitHub or your own Gitea instance by default, you can configure it by setting `[actions].DEFAULT_ACTIONS_URL`.
See [Configuration Cheat Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/#actions-actions).
See [Configuration Cheat Sheet](administration/config-cheat-sheet.md#actions-actions).
This is one of the differences from GitHub Actions, but it should allow users much more flexibility in how they run Actions.
@ -69,7 +69,7 @@ This is one of the differences from GitHub Actions, but it should allow users mu
Runners have no more permissions than simply connecting to your Gitea instance.
When any runner receives a job to run, it will temporarily gain limited permission to the repository associated with the job.
If you want to give more permissions to the runner, allowing it to access more private repositories or external systems, you can pass [secrets](https://docs.gitea.io/en-us/usage/secrets/) to it.
If you want to give more permissions to the runner, allowing it to access more private repositories or external systems, you can pass [secrets](usage/secrets.md) to it.
Refined permission control to Actions is a complicated job.
In the future, we will add more options to Gitea to make it more configurable, such as allowing more write access to repositories or read access to all repositories in the same organization.

View File

@ -61,7 +61,7 @@ DEFAULT_REPO_UNITS = ...,repo.actions
注意,`https://`或`http://`前缀是必需的!
另外如果您希望您的Runner默认从GitHub或您自己的Gitea实例下载Actions可以通过设置 `[actions].DEFAULT_ACTIONS_URL`进行配置。
参见[配置速查表](https://docs.gitea.io/en-us/config-cheat-sheet/#actions-actions)。
参见[配置速查表](administration/config-cheat-sheet.md#actions-actions)。
这是与GitHub Actions的一个区别但它应该允许用户以更灵活的方式运行Actions。
@ -69,7 +69,7 @@ DEFAULT_REPO_UNITS = ...,repo.actions
Runner仅具有连接到您的Gitea实例的权限。
当任何Runner接收到要运行的Job时它将临时获得与Job关联的仓库的有限权限。
如果您想为Runner提供更多权限允许它访问更多私有仓库或外部系统您可以向其传递[密钥](https://docs.gitea.io/en-us/usage/secrets/)。
如果您想为Runner提供更多权限允许它访问更多私有仓库或外部系统您可以向其传递[密钥](usage/secrets.md)。
对于 Actions 的细粒度权限控制是一项复杂的工作。
在未来我们将添加更多选项以使Gitea更可配置例如允许对仓库进行更多写访问或对同一组织中的所有仓库进行读访问。

View File

@ -197,7 +197,7 @@ administrative user.
field is set to `mail.com`, then Gitea will expect the `user email` field
for an authenticated GIT instance to be `gituser@mail.com`.[^2]
**Note**: PAM support is added via [build-time flags](https://docs.gitea.io/en-us/install-from-source/#build),
**Note**: PAM support is added via [build-time flags](installation/install-from-source.md#build),
and the official binaries provided do not have this enabled. PAM requires that
the necessary libpam dynamic library be available and the necessary PAM
development headers be accessible to the compiler.

View File

@ -162,7 +162,7 @@ PAM提供了一种机制通过对用户进行PAM认证来自动将其添加
- 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)添加,
**Note**: PAM 支持通过[build-time flags](installation/install-from-source.md#build)添加,
而官方提供的二进制文件通常不会默认启用此功能。PAM需要确保系统上有必要的libpam动态库并且编译器可以访问必要的PAM开发头文件。
[^1]: 例如在Debian "Bullseye"上使用标准Linux登录可以使用`common-session-noninteractive`。这个值对于其他版本的Debian

2
go.mod
View File

@ -90,6 +90,7 @@ require (
github.com/prometheus/client_golang v1.16.0
github.com/quasoft/websspi v1.1.2
github.com/redis/go-redis/v9 v9.0.5
github.com/robfig/cron/v3 v3.0.1
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/sassoftware/go-rpmutils v0.2.0
github.com/sergi/go-diff v1.3.1
@ -254,7 +255,6 @@ require (
github.com/rhysd/actionlint v1.6.25 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/robfig/cron v1.2.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect

120
models/actions/schedule.go Normal file
View File

@ -0,0 +1,120 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package actions
import (
"context"
"time"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/timeutil"
webhook_module "code.gitea.io/gitea/modules/webhook"
"github.com/robfig/cron/v3"
)
// ActionSchedule represents a schedule of a workflow file
type ActionSchedule struct {
ID int64
Title string
Specs []string
RepoID int64 `xorm:"index"`
Repo *repo_model.Repository `xorm:"-"`
OwnerID int64 `xorm:"index"`
WorkflowID string
TriggerUserID int64
TriggerUser *user_model.User `xorm:"-"`
Ref string
CommitSHA string
Event webhook_module.HookEventType
EventPayload string `xorm:"LONGTEXT"`
Content []byte
Created timeutil.TimeStamp `xorm:"created"`
Updated timeutil.TimeStamp `xorm:"updated"`
}
func init() {
db.RegisterModel(new(ActionSchedule))
}
// GetSchedulesMapByIDs returns the schedules by given id slice.
func GetSchedulesMapByIDs(ids []int64) (map[int64]*ActionSchedule, error) {
schedules := make(map[int64]*ActionSchedule, len(ids))
return schedules, db.GetEngine(db.DefaultContext).In("id", ids).Find(&schedules)
}
// GetReposMapByIDs returns the repos by given id slice.
func GetReposMapByIDs(ids []int64) (map[int64]*repo_model.Repository, error) {
repos := make(map[int64]*repo_model.Repository, len(ids))
return repos, db.GetEngine(db.DefaultContext).In("id", ids).Find(&repos)
}
var cronParser = cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
// CreateScheduleTask creates new schedule task.
func CreateScheduleTask(ctx context.Context, rows []*ActionSchedule) error {
// Return early if there are no rows to insert
if len(rows) == 0 {
return nil
}
// Begin transaction
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
defer committer.Close()
// Loop through each schedule row
for _, row := range rows {
// Create new schedule row
if err = db.Insert(ctx, row); err != nil {
return err
}
// Loop through each schedule spec and create a new spec row
now := time.Now()
for _, spec := range row.Specs {
// Parse the spec and check for errors
schedule, err := cronParser.Parse(spec)
if err != nil {
continue // skip to the next spec if there's an error
}
// Insert the new schedule spec row
if err = db.Insert(ctx, &ActionScheduleSpec{
RepoID: row.RepoID,
ScheduleID: row.ID,
Spec: spec,
Next: timeutil.TimeStamp(schedule.Next(now).Unix()),
}); err != nil {
return err
}
}
}
// Commit transaction
return committer.Commit()
}
func DeleteScheduleTaskByRepo(ctx context.Context, id int64) error {
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
defer committer.Close()
if _, err := db.GetEngine(ctx).Delete(&ActionSchedule{RepoID: id}); err != nil {
return err
}
if _, err := db.GetEngine(ctx).Delete(&ActionScheduleSpec{RepoID: id}); err != nil {
return err
}
return committer.Commit()
}

View File

@ -0,0 +1,94 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package actions
import (
"context"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/container"
"xorm.io/builder"
)
type ScheduleList []*ActionSchedule
// GetUserIDs returns a slice of user's id
func (schedules ScheduleList) GetUserIDs() []int64 {
ids := make(container.Set[int64], len(schedules))
for _, schedule := range schedules {
ids.Add(schedule.TriggerUserID)
}
return ids.Values()
}
func (schedules ScheduleList) GetRepoIDs() []int64 {
ids := make(container.Set[int64], len(schedules))
for _, schedule := range schedules {
ids.Add(schedule.RepoID)
}
return ids.Values()
}
func (schedules ScheduleList) LoadTriggerUser(ctx context.Context) error {
userIDs := schedules.GetUserIDs()
users := make(map[int64]*user_model.User, len(userIDs))
if err := db.GetEngine(ctx).In("id", userIDs).Find(&users); err != nil {
return err
}
for _, schedule := range schedules {
if schedule.TriggerUserID == user_model.ActionsUserID {
schedule.TriggerUser = user_model.NewActionsUser()
} else {
schedule.TriggerUser = users[schedule.TriggerUserID]
}
}
return nil
}
func (schedules ScheduleList) LoadRepos() error {
repoIDs := schedules.GetRepoIDs()
repos, err := repo_model.GetRepositoriesMapByIDs(repoIDs)
if err != nil {
return err
}
for _, schedule := range schedules {
schedule.Repo = repos[schedule.RepoID]
}
return nil
}
type FindScheduleOptions struct {
db.ListOptions
RepoID int64
OwnerID int64
}
func (opts FindScheduleOptions) toConds() builder.Cond {
cond := builder.NewCond()
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
if opts.OwnerID > 0 {
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
}
return cond
}
func FindSchedules(ctx context.Context, opts FindScheduleOptions) (ScheduleList, int64, error) {
e := db.GetEngine(ctx).Where(opts.toConds())
if !opts.ListAll && opts.PageSize > 0 && opts.Page >= 1 {
e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
}
var schedules ScheduleList
total, err := e.Desc("id").FindAndCount(&schedules)
return schedules, total, err
}
func CountSchedules(ctx context.Context, opts FindScheduleOptions) (int64, error) {
return db.GetEngine(ctx).Where(opts.toConds()).Count(new(ActionSchedule))
}

View File

@ -0,0 +1,50 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package actions
import (
"context"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/timeutil"
"github.com/robfig/cron/v3"
)
// ActionScheduleSpec represents a schedule spec of a workflow file
type ActionScheduleSpec struct {
ID int64
RepoID int64 `xorm:"index"`
Repo *repo_model.Repository `xorm:"-"`
ScheduleID int64 `xorm:"index"`
Schedule *ActionSchedule `xorm:"-"`
// Next time the job will run, or the zero time if Cron has not been
// started or this entry's schedule is unsatisfiable
Next timeutil.TimeStamp `xorm:"index"`
// Prev is the last time this job was run, or the zero time if never.
Prev timeutil.TimeStamp
Spec string
Created timeutil.TimeStamp `xorm:"created"`
Updated timeutil.TimeStamp `xorm:"updated"`
}
func (s *ActionScheduleSpec) Parse() (cron.Schedule, error) {
return cronParser.Parse(s.Spec)
}
func init() {
db.RegisterModel(new(ActionScheduleSpec))
}
func UpdateScheduleSpec(ctx context.Context, spec *ActionScheduleSpec, cols ...string) error {
sess := db.GetEngine(ctx).ID(spec.ID)
if len(cols) > 0 {
sess.Cols(cols...)
}
_, err := sess.Update(spec)
return err
}

View File

@ -0,0 +1,106 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package actions
import (
"context"
"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/container"
"xorm.io/builder"
)
type SpecList []*ActionScheduleSpec
func (specs SpecList) GetScheduleIDs() []int64 {
ids := make(container.Set[int64], len(specs))
for _, spec := range specs {
ids.Add(spec.ScheduleID)
}
return ids.Values()
}
func (specs SpecList) LoadSchedules() error {
scheduleIDs := specs.GetScheduleIDs()
schedules, err := GetSchedulesMapByIDs(scheduleIDs)
if err != nil {
return err
}
for _, spec := range specs {
spec.Schedule = schedules[spec.ScheduleID]
}
repoIDs := specs.GetRepoIDs()
repos, err := GetReposMapByIDs(repoIDs)
if err != nil {
return err
}
for _, spec := range specs {
spec.Repo = repos[spec.RepoID]
}
return nil
}
func (specs SpecList) GetRepoIDs() []int64 {
ids := make(container.Set[int64], len(specs))
for _, spec := range specs {
ids.Add(spec.RepoID)
}
return ids.Values()
}
func (specs SpecList) LoadRepos() error {
repoIDs := specs.GetRepoIDs()
repos, err := repo_model.GetRepositoriesMapByIDs(repoIDs)
if err != nil {
return err
}
for _, spec := range specs {
spec.Repo = repos[spec.RepoID]
}
return nil
}
type FindSpecOptions struct {
db.ListOptions
RepoID int64
Next int64
}
func (opts FindSpecOptions) toConds() builder.Cond {
cond := builder.NewCond()
if opts.RepoID > 0 {
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
}
if opts.Next > 0 {
cond = cond.And(builder.Lte{"next": opts.Next})
}
return cond
}
func FindSpecs(ctx context.Context, opts FindSpecOptions) (SpecList, int64, error) {
e := db.GetEngine(ctx).Where(opts.toConds())
if opts.PageSize > 0 && opts.Page >= 1 {
e.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
}
var specs SpecList
total, err := e.Desc("id").FindAndCount(&specs)
if err != nil {
return nil, 0, err
}
if err := specs.LoadSchedules(); err != nil {
return nil, 0, err
}
return specs, total, nil
}
func CountSpecs(ctx context.Context, opts FindSpecOptions) (int64, error) {
return db.GetEngine(ctx).Where(opts.toConds()).Count(new(ActionScheduleSpec))
}

View File

@ -276,4 +276,12 @@
email: user2-2@example.com
lower_email: user2-2@example.com
is_activated: false
is_primary: false
is_primary: false
-
id: 36
uid: 36
email: abcde@gitea.com
lower_email: abcde@gitea.com
is_activated: true
is_primary: false

View File

@ -1 +1,23 @@
[] # empty
-
id: 5
owner_id: 36
key_id: B15431642629B826
primary_key_id:
content: xsDNBGTrY3UBDAC2HLBqmMplAV15qSnC7g1c4dV406f5EHNhFr95Nup2My6b2eafTlvedv77s8PT/I7F3fy4apOZs5A7w2SsPlLMcQ3ev4uGOsxRtkq5RLy1Yb6SNueX0Da2UVKR5KTC5Q6BWaqxwS0IjKOLZ/xz0Pbe/ClV3bZSKBEY2omkVo3Z0HZ771vB2clPRvGJ/IdeKOsZ3ZytSFXfyiJBdARmeSPmydXLil8+Ibq5iLAeow5PK8hK1TCOnKHzLWNqcNq70tyjoHvcGi70iGjoVEEUgPCLLuU8WmzTJwlvA3BuDzjtaO7TLo/jdE6iqkHtMSS8x+43sAH6hcFRCWAVh/0Uq7n36uGDfNxGnX3YrmX3LR9x5IsBES1rGGWbpxio4o5GIf/Xd+JgDd9rzJCqRuZ3/sW/TxK38htWaVNZV0kMkHUCTc1ctzWpCm635hbFCHBhPYIp+/z206khkAKDbz/CNuU91Wazsh7KO07wrwDtxfDDbInJ8TfHE2TGjzjQzgChfmcAEQEAAQ==
verified: true
can_sign: true
can_encrypt_comms: true
can_encrypt_storage: true
can_certify: true
-
id: 6
owner_id: 36
key_id: EE3AF48454AFD619
primary_key_id: B15431642629B826
content: zsDNBGTrY3UBDADsHrzuOicQaPdUQm0+0UNrs92cESm/j/4yBBUk+sfLZAo6J99c4eh4nAQzzZ7al080rYKB0G+7xoRz1eHcQH6zrVcqB8KYtf/sdY47WaMiMyxM+kTSvzp7tsv7QuSQZ0neUEXRyYMz5ttBfIjWUd+3NDItuHyB+MtNWlS3zXgaUbe5VifqKaNmzN0Ye4yXTKcpypE3AOqPVz+iIFv3c6TmsqLHJaR4VoicCleAqLyF/28WsJO7M9dDW+EM3MZVnsVpycTURyHAJGfSk10waQZAaRwmarCN/q0KEJ+aEAK/SRliUneBZoMO5hY5iBeG432tofwaQqAahPv9uXIb1n2JEMKwnMlMA9UGD1AcDbywfj1m/ZGBBw95i4Ekkfn43RvV3THr7uJU/dRqqP+iic4MwpUrOxqELW/kmeHXlBcNbZZhEEvwRoW7U2/9eeuog4nRleRJ0pi/xOP9wmxkKjaIPIK3phdBtEpVk4w/UTAWNdyIIrFggukeAnZFyGJwlm8AEQEAAQ==
verified: true
can_sign: true
can_encrypt_comms: true
can_encrypt_storage: true
can_certify: true

View File

@ -1301,7 +1301,7 @@
lower_name: limited_org36
name: limited_org36
full_name: Limited Org 36
email: limited_org36@example.com
email: abcde@gitea.com
keep_email_private: false
email_notifications_preference: enabled
passwd: ZogKvWdyEx:password
@ -1320,7 +1320,7 @@
allow_create_organization: true
prohibit_login: false
avatar: avatar22
avatar_email: limited_org36@example.com
avatar_email: abcde@gitea.com
use_custom_avatar: false
num_followers: 0
num_following: 0

View File

@ -23,6 +23,7 @@ import (
"code.gitea.io/gitea/modules/references"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/util"
"xorm.io/builder"
@ -181,40 +182,32 @@ func (t CommentType) HasAttachmentSupport() bool {
return false
}
// RoleDescriptor defines comment tag type
type RoleDescriptor int
// RoleInRepo presents the user's participation in the repo
type RoleInRepo string
// RoleDescriptor defines comment "role" tags
type RoleDescriptor struct {
IsPoster bool
RoleInRepo RoleInRepo
}
// Enumerate all the role tags.
const (
RoleDescriptorNone RoleDescriptor = iota
RoleDescriptorPoster
RoleDescriptorWriter
RoleDescriptorOwner
RoleRepoOwner RoleInRepo = "owner"
RoleRepoMember RoleInRepo = "member"
RoleRepoCollaborator RoleInRepo = "collaborator"
RoleRepoFirstTimeContributor RoleInRepo = "first_time_contributor"
RoleRepoContributor RoleInRepo = "contributor"
)
// WithRole enable a specific tag on the RoleDescriptor.
func (rd RoleDescriptor) WithRole(role RoleDescriptor) RoleDescriptor {
return rd | (1 << role)
// LocaleString returns the locale string name of the role
func (r RoleInRepo) LocaleString(lang translation.Locale) string {
return lang.Tr("repo.issues.role." + string(r))
}
func stringToRoleDescriptor(role string) RoleDescriptor {
switch role {
case "Poster":
return RoleDescriptorPoster
case "Writer":
return RoleDescriptorWriter
case "Owner":
return RoleDescriptorOwner
default:
return RoleDescriptorNone
}
}
// HasRole returns if a certain role is enabled on the RoleDescriptor.
func (rd RoleDescriptor) HasRole(role string) bool {
roleDescriptor := stringToRoleDescriptor(role)
bitValue := rd & (1 << roleDescriptor)
return (bitValue > 0)
// LocaleHelper returns the locale tooltip of the role
func (r RoleInRepo) LocaleHelper(lang translation.Locale) string {
return lang.Tr("repo.issues.role." + string(r) + "_helper")
}
// Comment represents a comment in commit and issue page.

View File

@ -199,3 +199,16 @@ func (prs PullRequestList) GetIssueIDs() []int64 {
}
return issueIDs
}
// HasMergedPullRequestInRepo returns whether the user(poster) has merged pull-request in the repo
func HasMergedPullRequestInRepo(ctx context.Context, repoID, posterID int64) (bool, error) {
return db.GetEngine(ctx).
Join("INNER", "pull_request", "pull_request.issue_id = issue.id").
Where("repo_id=?", repoID).
And("poster_id=?", posterID).
And("is_pull=?", true).
And("pull_request.has_merged=?", true).
Select("issue.id").
Limit(1).
Get(new(Issue))
}

View File

@ -526,6 +526,8 @@ var migrations = []Migration{
NewMigration("Allow archiving labels", v1_21.AddArchivedUnixColumInLabelTable),
// v272 -> v273
NewMigration("Add Version to ActionRun table", v1_21.AddVersionToActionRunTable),
// v273 -> v274
NewMigration("Add Action Schedule Table", v1_21.AddActionScheduleTable),
}
// GetCurrentDBVersion returns the current db version

View File

@ -4,7 +4,6 @@
package v1_16 //nolint
import (
"crypto/elliptic"
"encoding/base32"
"fmt"
"strings"
@ -123,13 +122,17 @@ func RemigrateU2FCredentials(x *xorm.Engine) error {
if err != nil {
continue
}
pubKey, err := parsed.PubKey.ECDH()
if err != nil {
continue
}
remigrated := &webauthnCredential{
ID: reg.ID,
Name: reg.Name,
LowerName: strings.ToLower(reg.Name),
UserID: reg.UserID,
CredentialID: base32.HexEncoding.EncodeToString(parsed.KeyHandle),
PublicKey: elliptic.Marshal(elliptic.P256(), parsed.PubKey.X, parsed.PubKey.Y),
PublicKey: pubKey.Bytes(),
AttestationType: "fido-u2f",
AAGUID: []byte{},
SignCount: reg.Counter,

View File

@ -0,0 +1,45 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_21 //nolint
import (
"code.gitea.io/gitea/modules/timeutil"
"xorm.io/xorm"
)
func AddActionScheduleTable(x *xorm.Engine) error {
type ActionSchedule struct {
ID int64
Title string
Specs []string
RepoID int64 `xorm:"index"`
OwnerID int64 `xorm:"index"`
WorkflowID string
TriggerUserID int64
Ref string
CommitSHA string
Event string
EventPayload string `xorm:"LONGTEXT"`
Content []byte
Created timeutil.TimeStamp `xorm:"created"`
Updated timeutil.TimeStamp `xorm:"updated"`
}
type ActionScheduleSpec struct {
ID int64
RepoID int64 `xorm:"index"`
ScheduleID int64 `xorm:"index"`
Spec string
Next timeutil.TimeStamp `xorm:"index"`
Prev timeutil.TimeStamp
Created timeutil.TimeStamp `xorm:"created"`
Updated timeutil.TimeStamp `xorm:"updated"`
}
return x.Sync(
new(ActionSchedule),
new(ActionScheduleSpec),
)
}

View File

@ -170,6 +170,8 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
&actions_model.ActionRunJob{RepoID: repoID},
&actions_model.ActionRun{RepoID: repoID},
&actions_model.ActionRunner{RepoID: repoID},
&actions_model.ActionScheduleSpec{RepoID: repoID},
&actions_model.ActionSchedule{RepoID: repoID},
&actions_model.ActionArtifact{RepoID: repoID},
); err != nil {
return fmt.Errorf("deleteBeans: %w", err)

View File

@ -128,7 +128,7 @@ func GetPushMirrorsByRepoID(ctx context.Context, repoID int64, listOptions db.Li
func GetPushMirrorsSyncedOnCommit(ctx context.Context, repoID int64) ([]*PushMirror, error) {
mirrors := make([]*PushMirror, 0, 10)
return mirrors, db.GetEngine(ctx).
Where("repo_id=? AND sync_on_commit=?", repoID, true).
Where("repo_id = ? AND sync_on_commit = ?", repoID, true).
Find(&mirrors)
}

View File

@ -133,6 +133,11 @@ func (r *Release) HTMLURL() string {
return r.Repo.HTMLURL() + "/releases/tag/" + util.PathEscapeSegments(r.TagName)
}
// APIUploadURL the api url to upload assets to a release. release must have attributes loaded
func (r *Release) APIUploadURL() string {
return r.APIURL() + "/assets"
}
// Link the relative url for a release on the web UI. release must have attributes loaded
func (r *Release) Link() string {
return r.Repo.Link() + "/releases/tag/" + util.PathEscapeSegments(r.TagName)

View File

@ -6,12 +6,14 @@ package secret
import (
"context"
"errors"
"fmt"
"strings"
"code.gitea.io/gitea/models/db"
secret_module "code.gitea.io/gitea/modules/secret"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"xorm.io/builder"
)
@ -26,6 +28,25 @@ type Secret struct {
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"`
}
// ErrSecretNotFound represents a "secret not found" error.
type ErrSecretNotFound struct {
Name string
}
// IsErrSecretNotFound checks if an error is a ErrSecretNotFound.
func IsErrSecretNotFound(err error) bool {
_, ok := err.(ErrSecretNotFound)
return ok
}
func (err ErrSecretNotFound) Error() string {
return fmt.Sprintf("secret was not found [name: %s]", err.Name)
}
func (err ErrSecretNotFound) Unwrap() error {
return util.ErrNotExist
}
// newSecret Creates a new already encrypted secret
func newSecret(ownerID, repoID int64, name, data string) *Secret {
return &Secret{
@ -93,3 +114,77 @@ func FindSecrets(ctx context.Context, opts FindSecretsOptions) ([]*Secret, error
func CountSecrets(ctx context.Context, opts *FindSecretsOptions) (int64, error) {
return db.GetEngine(ctx).Where(opts.toConds()).Count(new(Secret))
}
// UpdateSecret changes org or user reop secret.
func UpdateSecret(ctx context.Context, orgID, repoID int64, name, data string) error {
sc := new(Secret)
name = strings.ToUpper(name)
has, err := db.GetEngine(ctx).
Where("owner_id=?", orgID).
And("repo_id=?", repoID).
And("name=?", name).
Get(sc)
if err != nil {
return err
} else if !has {
return ErrSecretNotFound{Name: name}
}
encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
if err != nil {
return err
}
sc.Data = encrypted
_, err = db.GetEngine(ctx).ID(sc.ID).Cols("data").Update(sc)
return err
}
// DeleteSecret deletes secret from an organization.
func DeleteSecret(ctx context.Context, orgID, repoID int64, name string) error {
sc := new(Secret)
has, err := db.GetEngine(ctx).
Where("owner_id=?", orgID).
And("repo_id=?", repoID).
And("name=?", strings.ToUpper(name)).
Get(sc)
if err != nil {
return err
} else if !has {
return ErrSecretNotFound{Name: name}
}
if _, err := db.GetEngine(ctx).ID(sc.ID).Delete(new(Secret)); err != nil {
return fmt.Errorf("Delete: %w", err)
}
return nil
}
// CreateOrUpdateSecret creates or updates a secret and returns true if it was created
func CreateOrUpdateSecret(ctx context.Context, orgID, repoID int64, name, data string) (bool, error) {
sc := new(Secret)
name = strings.ToUpper(name)
has, err := db.GetEngine(ctx).
Where("owner_id=?", orgID).
And("repo_id=?", repoID).
And("name=?", name).
Get(sc)
if err != nil {
return false, err
}
if !has {
_, err = InsertEncryptedSecret(ctx, orgID, repoID, name, data)
if err != nil {
return false, err
}
return true, nil
}
if err := UpdateSecret(ctx, orgID, repoID, name, data); err != nil {
return false, err
}
return false, nil
}

View File

@ -9,6 +9,7 @@ import (
"strings"
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
)
@ -318,14 +319,13 @@ var (
// FindUnitTypes give the unit key names and return valid unique units and invalid keys
func FindUnitTypes(nameKeys ...string) (res []Type, invalidKeys []string) {
m := map[Type]struct{}{}
m := make(container.Set[Type])
for _, key := range nameKeys {
t := TypeFromKey(key)
if t == TypeInvalid {
invalidKeys = append(invalidKeys, key)
} else if _, ok := m[t]; !ok {
} else if m.Add(t) {
res = append(res, t)
m[t] = struct{}{}
}
}
return res, invalidKeys

View File

@ -95,18 +95,25 @@ func GetEventsFromContent(content []byte) ([]*jobparser.Event, error) {
return events, nil
}
func DetectWorkflows(gitRepo *git.Repository, commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader) ([]*DetectedWorkflow, error) {
func DetectWorkflows(
gitRepo *git.Repository,
commit *git.Commit,
triggedEvent webhook_module.HookEventType,
payload api.Payloader,
) ([]*DetectedWorkflow, []*DetectedWorkflow, error) {
entries, err := ListWorkflows(commit)
if err != nil {
return nil, err
return nil, nil, err
}
workflows := make([]*DetectedWorkflow, 0, len(entries))
schedules := make([]*DetectedWorkflow, 0, len(entries))
for _, entry := range entries {
content, err := GetContentFromEntry(entry)
if err != nil {
return nil, err
return nil, nil, err
}
events, err := GetEventsFromContent(content)
if err != nil {
log.Warn("ignore invalid workflow %q: %v", entry.Name(), err)
@ -114,6 +121,14 @@ func DetectWorkflows(gitRepo *git.Repository, commit *git.Commit, triggedEvent w
}
for _, evt := range events {
log.Trace("detect workflow %q for event %#v matching %q", entry.Name(), evt, triggedEvent)
if evt.IsSchedule() {
dwf := &DetectedWorkflow{
EntryName: entry.Name(),
TriggerEvent: evt.Name,
Content: content,
}
schedules = append(schedules, dwf)
}
if detectMatched(gitRepo, commit, triggedEvent, payload, evt) {
dwf := &DetectedWorkflow{
EntryName: entry.Name(),
@ -125,7 +140,7 @@ func DetectWorkflows(gitRepo *git.Repository, commit *git.Commit, triggedEvent w
}
}
return workflows, nil
return workflows, schedules, nil
}
func detectMatched(gitRepo *git.Repository, commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader, evt *jobparser.Event) bool {

View File

@ -8,7 +8,7 @@ import (
"code.gitea.io/gitea/modules/util"
)
const rsaBits = 2048
const rsaBits = 3072
// GetKeyPair function returns a user's private and public keys
func GetKeyPair(user *user_model.User) (pub, priv string, err error) {

View File

@ -14,6 +14,7 @@ import (
"sort"
"time"
"code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/process"
"code.gitea.io/gitea/modules/util"
@ -130,7 +131,7 @@ func readDir(layer *Layer, name string) ([]fs.FileInfo, error) {
// * false: only directories will be returned.
// The returned files are sorted by name.
func (l *LayeredFS) ListFiles(name string, fileMode ...bool) ([]string, error) {
fileMap := map[string]bool{}
fileSet := make(container.Set[string])
for _, layer := range l.layers {
infos, err := readDir(layer, name)
if err != nil {
@ -138,14 +139,11 @@ func (l *LayeredFS) ListFiles(name string, fileMode ...bool) ([]string, error) {
}
for _, info := range infos {
if shouldInclude(info, fileMode...) {
fileMap[info.Name()] = true
fileSet.Add(info.Name())
}
}
}
files := make([]string, 0, len(fileMap))
for file := range fileMap {
files = append(files, file)
}
files := fileSet.Values()
sort.Strings(files)
return files, nil
}
@ -161,7 +159,7 @@ func (l *LayeredFS) ListAllFiles(name string, fileMode ...bool) ([]string, error
}
func listAllFiles(layers []*Layer, name string, fileMode ...bool) ([]string, error) {
fileMap := map[string]bool{}
fileSet := make(container.Set[string])
var list func(dir string) error
list = func(dir string) error {
for _, layer := range layers {
@ -172,7 +170,7 @@ func listAllFiles(layers []*Layer, name string, fileMode ...bool) ([]string, err
for _, info := range infos {
path := util.PathJoinRelX(dir, info.Name())
if shouldInclude(info, fileMode...) {
fileMap[path] = true
fileSet.Add(path)
}
if info.IsDir() {
if err = list(path); err != nil {
@ -186,10 +184,7 @@ func listAllFiles(layers []*Layer, name string, fileMode ...bool) ([]string, err
if err := list(name); err != nil {
return nil, err
}
var files []string
for file := range fileMap {
files = append(files, file)
}
files := fileSet.Values()
sort.Strings(files)
return files, nil
}

View File

@ -107,6 +107,29 @@ func GetValidateContext(req *http.Request) (ctx *ValidateContext) {
return ctx
}
func NewTemplateContextForWeb(ctx *Context) TemplateContext {
tmplCtx := NewTemplateContext(ctx)
tmplCtx["Locale"] = ctx.Base.Locale
tmplCtx["AvatarUtils"] = templates.NewAvatarUtils(ctx)
return tmplCtx
}
func NewWebContext(base *Base, render Render, session session.Store) *Context {
ctx := &Context{
Base: base,
Render: render,
Session: session,
Cache: mc.GetCache(),
Link: setting.AppSubURL + strings.TrimSuffix(base.Req.URL.EscapedPath(), "/"),
Repo: &Repository{PullRequest: &PullRequest{}},
Org: &Organization{},
}
ctx.TemplateContext = NewTemplateContextForWeb(ctx)
ctx.Flash = &middleware.Flash{DataStore: ctx, Values: url.Values{}}
return ctx
}
// Contexter initializes a classic context for a request.
func Contexter() func(next http.Handler) http.Handler {
rnd := templates.HTMLRenderer()
@ -127,21 +150,8 @@ func Contexter() func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
base, baseCleanUp := NewBaseContext(resp, req)
ctx := &Context{
Base: base,
Cache: mc.GetCache(),
Link: setting.AppSubURL + strings.TrimSuffix(req.URL.EscapedPath(), "/"),
Render: rnd,
Session: session.GetSession(req),
Repo: &Repository{PullRequest: &PullRequest{}},
Org: &Organization{},
}
defer baseCleanUp()
// TODO: "install.go" also shares the same logic, which should be refactored to a general function
ctx.TemplateContext = NewTemplateContext(ctx)
ctx.TemplateContext["Locale"] = ctx.Locale
ctx.TemplateContext["AvatarUtils"] = templates.NewAvatarUtils(ctx)
ctx := NewWebContext(base, rnd, session.GetSession(req))
ctx.Data.MergeFrom(middleware.CommonTemplateContextData())
ctx.Data["Context"] = ctx // TODO: use "ctx" in template and remove this
@ -172,8 +182,7 @@ func Contexter() func(next http.Handler) http.Handler {
}
}
// prepare an empty Flash message for current request
ctx.Flash = &middleware.Flash{DataStore: ctx, Values: url.Values{}}
// if there are new messages in the ctx.Flash, write them into cookie
ctx.Resp.Before(func(resp ResponseWriter) {
if val := ctx.Flash.Encode(); val != "" {
middleware.SetSiteCookie(ctx.Resp, CookieNameFlash, val, 0)

View File

@ -154,12 +154,10 @@ func PackageContexter() func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
base, baseCleanUp := NewBaseContext(resp, req)
ctx := &Context{
Base: base,
Render: renderer, // it is still needed when rendering 500 page in a package handler
}
defer baseCleanUp()
// it is still needed when rendering 500 page in a package handler
ctx := NewWebContext(base, renderer, nil)
ctx.Base.AppendContextValue(WebContextKey, ctx)
next.ServeHTTP(ctx.Resp, ctx.Req)
})

61
modules/doctor/fix8312.go Normal file
View File

@ -0,0 +1,61 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package doctor
import (
"context"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
org_model "code.gitea.io/gitea/models/organization"
"code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/modules/log"
"xorm.io/builder"
)
func fixOwnerTeamCreateOrgRepo(ctx context.Context, logger log.Logger, autofix bool) error {
count := 0
err := db.Iterate(
ctx,
builder.Eq{"authorize": perm.AccessModeOwner, "can_create_org_repo": false},
func(ctx context.Context, team *org_model.Team) error {
team.CanCreateOrgRepo = true
count++
if !autofix {
return nil
}
return models.UpdateTeam(team, false, false)
},
)
if err != nil {
logger.Critical("Unable to iterate across repounits to fix incorrect can_create_org_repo: Error %v", err)
return err
}
if !autofix {
if count == 0 {
logger.Info("Found no team with incorrect can_create_org_repo")
} else {
logger.Warn("Found %d teams with incorrect can_create_org_repo", count)
}
return nil
}
logger.Info("Fixed %d teams with incorrect can_create_org_repo", count)
return nil
}
func init() {
Register(&Check{
Title: "Check for incorrect can_create_org_repo for org owner teams",
Name: "fix-owner-team-create-org-repo",
IsDefault: false,
Run: fixOwnerTeamCreateOrgRepo,
Priority: 7,
})
}

View File

@ -495,7 +495,7 @@ func GetCommitFileStatus(ctx context.Context, repoPath, commitID string) (*Commi
}()
stderr := new(bytes.Buffer)
err := NewCommand(ctx, "log", "--name-status", "-c", "--pretty=format:", "--parents", "--no-renames", "-z", "-1").AddDynamicArguments(commitID).Run(&RunOpts{
err := NewCommand(ctx, "log", "--name-status", "-m", "--pretty=format:", "--first-parent", "--no-renames", "-z", "-1").AddDynamicArguments(commitID).Run(&RunOpts{
Dir: repoPath,
Stdout: w,
Stderr: stderr,

View File

@ -255,3 +255,26 @@ func TestParseCommitFileStatus(t *testing.T) {
assert.Equal(t, kase.modified, fileStatus.Modified)
}
}
func TestGetCommitFileStatusMerges(t *testing.T) {
bareRepo1Path := filepath.Join(testReposDir, "repo6_merge")
commitFileStatus, err := GetCommitFileStatus(DefaultContext, bareRepo1Path, "022f4ce6214973e018f02bf363bf8a2e3691f699")
assert.NoError(t, err)
expected := CommitFileStatus{
[]string{
"add_file.txt",
},
[]string{
"to_remove.txt",
},
[]string{
"to_modify.txt",
},
}
assert.Equal(t, commitFileStatus.Added, expected.Added)
assert.Equal(t, commitFileStatus.Removed, expected.Removed)
assert.Equal(t, commitFileStatus.Modified, expected.Modified)
}

View File

@ -374,27 +374,25 @@ heaploop:
break heaploop
}
parentRemaining.Remove(current.CommitID)
if current.Paths != nil {
for i, found := range current.Paths {
if !found {
continue
for i, found := range current.Paths {
if !found {
continue
}
changed[i] = false
if results[i] == "" {
results[i] = current.CommitID
if err := repo.LastCommitCache.Put(headRef, path.Join(treepath, paths[i]), current.CommitID); err != nil {
return nil, err
}
changed[i] = false
if results[i] == "" {
results[i] = current.CommitID
if err := repo.LastCommitCache.Put(headRef, path.Join(treepath, paths[i]), current.CommitID); err != nil {
delete(path2idx, paths[i])
remaining--
if results[0] == "" {
results[0] = current.CommitID
if err := repo.LastCommitCache.Put(headRef, treepath, current.CommitID); err != nil {
return nil, err
}
delete(path2idx, paths[i])
delete(path2idx, "")
remaining--
if results[0] == "" {
results[0] = current.CommitID
if err := repo.LastCommitCache.Put(headRef, treepath, current.CommitID); err != nil {
return nil, err
}
delete(path2idx, "")
remaining--
}
}
}
}

View File

@ -0,0 +1 @@
ref: refs/heads/main

View File

@ -0,0 +1,2 @@
x<01>ÍM
1 †a×=Eö$µÍLAÄ«ô'ÁiæþR½€g÷~_ÝÖu1 ˜@mZ)g<>2…Dj™Š*_“fŒÌs ¥4ïòaÏm“np>—Áˆç€Ì>!œÑ#ºú½1ù;p]ìxÿæuyIwÑN4Ã

View File

@ -0,0 +1,2 @@
x█нM
б0├aв9еЛ≥ЭM2 БU Ф ╛∙=©т╦yv/╪С╤╝к гН0:@╠Р$╠│Uя╛╚.≈[й>╚ ■l⌠▀IлsЙx РЗ8'T╞╟R╧д╓S,╙╠$x. ж И=n[╖│в═СНuГ╢s!+9╟┬ВBGvлfЧm Э≤▌uШ─зr┤ЫЪа>╝

View File

@ -0,0 +1,5 @@
xŤÎM
1 @a×=Eö¤?iń*mšÁÇ™xOŕćŰ=x˛.Ëlŕ™O¶©R˘Z80ŠÄ\[í*Ú%µb
<EFBFBD>&qď¶éË IŠŽČšÔç<C394>ť
7ęĚÔF쨜ĽwícŹuÓÝŕzx?¸ÜŔçš0ç
ś1 :ům™ţ¸6LóSÝŔí>&

View File

@ -0,0 +1 @@
022f4ce6214973e018f02bf363bf8a2e3691f699

View File

@ -0,0 +1 @@
ae4b035e7c4afbc000576cee3f713ea0c2f1e1e2

View File

@ -0,0 +1 @@
d1792641396ff7630d35fbb0b74b86b0c71bca77

View File

@ -0,0 +1 @@
38ec3e0cdc88bde01014bda4a5dd9fc835f41439

View File

@ -90,7 +90,7 @@ func (b *EventWriterBaseImpl) Run(ctx context.Context) {
if exprRegexp != nil {
fileLineCaller := fmt.Sprintf("%s:%d:%s", event.Origin.Filename, event.Origin.Line, event.Origin.Caller)
matched := exprRegexp.Match([]byte(fileLineCaller)) || exprRegexp.Match([]byte(event.Origin.MsgSimpleText))
matched := exprRegexp.MatchString(fileLineCaller) || exprRegexp.MatchString(event.Origin.MsgSimpleText)
if !matched {
continue
}

View File

@ -16,7 +16,6 @@ import (
"code.gitea.io/gitea/modules/notification/base"
"code.gitea.io/gitea/modules/notification/indexer"
"code.gitea.io/gitea/modules/notification/mail"
"code.gitea.io/gitea/modules/notification/mirror"
"code.gitea.io/gitea/modules/notification/ui"
"code.gitea.io/gitea/modules/repository"
"code.gitea.io/gitea/modules/setting"
@ -38,7 +37,6 @@ func NewContext() {
}
RegisterNotifier(indexer.NewNotifier())
RegisterNotifier(action.NewNotifier())
RegisterNotifier(mirror.NewNotifier())
}
// NotifyNewWikiPage notifies creating new wiki pages to notifiers

View File

@ -19,9 +19,9 @@ const (
packageName = "gitea"
packageVersion = "1.0.1"
description = "Package Description"
projectURL = "https://gitea.io"
repositoryURL = "https://gitea.io/gitea/gitea"
documentationURL = "https://docs.gitea.io"
projectURL = "https://gitea.com"
repositoryURL = "https://gitea.com/gitea/gitea"
documentationURL = "https://docs.gitea.com"
)
func TestParsePackage(t *testing.T) {

View File

@ -17,9 +17,9 @@ func TestParseImageConfig(t *testing.T) {
description := "Image Description"
author := "Gitea"
license := "MIT"
projectURL := "https://gitea.io"
projectURL := "https://gitea.com"
repositoryURL := "https://gitea.com/gitea"
documentationURL := "https://docs.gitea.io"
documentationURL := "https://docs.gitea.com"
configOCI := `{"config": {"labels": {"` + labelAuthors + `": "` + author + `", "` + labelLicenses + `": "` + license + `", "` + labelURL + `": "` + projectURL + `", "` + labelSource + `": "` + repositoryURL + `", "` + labelDocumentation + `": "` + documentationURL + `", "` + labelDescription + `": "` + description + `"}}, "history": [{"created_by": "do it 1"}, {"created_by": "dummy #(nop) do it 2"}]}`

View File

@ -18,9 +18,9 @@ const (
packageName = "gitea"
packageVersion = "1.0.1"
description = "Package Description"
projectURL = "https://gitea.io"
repositoryURL = "https://gitea.io/gitea/gitea"
documentationURL = "https://docs.gitea.io"
projectURL = "https://gitea.com"
repositoryURL = "https://gitea.com/gitea/gitea"
documentationURL = "https://docs.gitea.com"
)
const pubspecContent = `name: ` + packageName + `

View File

@ -106,15 +106,15 @@ func SyncRepoBranchesWithRepo(ctx context.Context, repo *repo_model.Repository,
return int64(len(allBranches)), nil
}
if err := db.WithTx(ctx, func(subCtx context.Context) error {
if err := db.WithTx(ctx, func(ctx context.Context) error {
if len(toAdd) > 0 {
if err := git_model.AddBranches(subCtx, toAdd); err != nil {
if err := git_model.AddBranches(ctx, toAdd); err != nil {
return err
}
}
for _, b := range toUpdate {
if _, err := db.GetEngine(subCtx).ID(b.ID).
if _, err := db.GetEngine(ctx).ID(b.ID).
Cols("commit_id, commit_message, pusher_id, commit_time, is_deleted").
Update(b); err != nil {
return err
@ -122,7 +122,7 @@ func SyncRepoBranchesWithRepo(ctx context.Context, repo *repo_model.Repository,
}
if len(toRemove) > 0 {
if err := git_model.DeleteBranches(subCtx, repo.ID, doerID, toRemove); err != nil {
if err := git_model.DeleteBranches(ctx, repo.ID, doerID, toRemove); err != nil {
return err
}
}

Some files were not shown because too many files have changed in this diff Show More