mirror of
https://github.com/go-gitea/gitea.git
synced 2026-06-21 16:52:02 +02:00
Merge branch 'main' into add-matrix-dynamic-job-input-support
This commit is contained in:
commit
f11b5d0357
2
Makefile
2
Makefile
@ -150,7 +150,7 @@ ESLINT_CONCURRENCY ?= 2
|
||||
|
||||
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
|
||||
SWAGGER_SPEC_INPUT := templates/swagger/v1_input.json
|
||||
SWAGGER_EXCLUDE := code.gitea.io/sdk
|
||||
SWAGGER_EXCLUDE := gitea.dev/sdk
|
||||
OPENAPI3_SPEC := templates/swagger/v1_openapi3_json.tmpl
|
||||
|
||||
TEST_MYSQL_HOST ?= mysql:3306
|
||||
|
||||
29
assets/go-licenses.json
generated
29
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
10
go.mod
10
go.mod
@ -3,8 +3,6 @@ module gitea.dev
|
||||
go 1.26.3
|
||||
|
||||
require (
|
||||
code.gitea.io/actions-proto-go v0.4.1
|
||||
code.gitea.io/sdk/gitea v0.25.1
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
||||
connectrpc.com/connect v1.20.0
|
||||
gitea.com/gitea/runner v1.0.5
|
||||
@ -14,6 +12,8 @@ require (
|
||||
gitea.com/go-chi/session v0.0.0-20251124165456-68e0254e989e
|
||||
gitea.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
|
||||
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4
|
||||
gitea.dev/actions-proto-go v0.5.0
|
||||
gitea.dev/sdk v1.0.1
|
||||
github.com/42wim/httpsig v1.2.4
|
||||
github.com/42wim/sshsig v0.0.0-20260317195500-b9f38cf0d432
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.20.0
|
||||
@ -23,7 +23,7 @@ require (
|
||||
github.com/ProtonMail/go-crypto v1.4.1
|
||||
github.com/PuerkitoBio/goquery v1.12.0
|
||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.3
|
||||
github.com/alecthomas/chroma/v2 v2.24.1
|
||||
github.com/alecthomas/chroma/v2 v2.25.0
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.16
|
||||
github.com/aws/aws-sdk-go-v2/service/codecommit v1.33.14
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
@ -33,8 +33,7 @@ require (
|
||||
github.com/caddyserver/certmagic v0.25.3
|
||||
github.com/charmbracelet/git-lfs-transfer v0.1.1-0.20260309112543-12416315a635
|
||||
github.com/chi-middleware/proxy v1.1.1
|
||||
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
|
||||
github.com/dlclark/regexp2 v1.12.0
|
||||
github.com/dlclark/regexp2/v2 v2.1.0
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.4
|
||||
@ -178,6 +177,7 @@ require (
|
||||
github.com/cyphar/filepath-securejoin v0.6.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/dlclark/regexp2 v1.12.0 // indirect
|
||||
github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 // indirect
|
||||
github.com/fatih/color v1.19.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.2 // indirect
|
||||
|
||||
17
go.sum
17
go.sum
@ -1,9 +1,5 @@
|
||||
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
|
||||
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
|
||||
code.gitea.io/actions-proto-go v0.4.1 h1:l0EYhjsgpUe/1VABo2eK7zcoNX2W44WOnb0MSLrKfls=
|
||||
code.gitea.io/actions-proto-go v0.4.1/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
|
||||
code.gitea.io/sdk/gitea v0.25.1 h1:yywxWwoV+SdjHtbC6unBiXojWdZOtoHuGhEazEXeWuE=
|
||||
code.gitea.io/sdk/gitea v0.25.1/go.mod h1:uDFWYBU8dgZsgOHwe6C/6olxvf8FHguNB3wW1i83fgg=
|
||||
code.pfad.fr/check v1.1.0 h1:GWvjdzhSEgHvEHe2uJujDcpmZoySKuHQNrZMfzfO0bE=
|
||||
code.pfad.fr/check v1.1.0/go.mod h1:NiUH13DtYsb7xp5wll0U4SXx7KhXQVCtRgdC96IPfoM=
|
||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570 h1:TXbikPqa7YRtfU9vS6QJBg77pUvbEb6StRdZO8t1bEY=
|
||||
@ -30,6 +26,10 @@ gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4 h1:IFT+hup2xejHq
|
||||
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4/go.mod h1:HBqmLbz56JWpfEGG0prskAV97ATNRoj5LDmPicD22hU=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
|
||||
gitea.dev/actions-proto-go v0.5.0 h1:Fc3DI4Fm3B3JBRXFUjegql+usoNAjjAw1cxMansfA2I=
|
||||
gitea.dev/actions-proto-go v0.5.0/go.mod h1:p4RX+D9oqiEEzzkPMXscw2CmaGuYFPWFc6xIOmDNDqs=
|
||||
gitea.dev/sdk v1.0.1 h1:CWXQUQvp2I6YKOWkhYo1Flx2sRNfMK1X9Op4oR2awXs=
|
||||
gitea.dev/sdk v1.0.1/go.mod h1:jCf5Uzz0Jkb61jxNgMxLOCWwle1J1B2nKdcRtxuK9rY=
|
||||
github.com/42wim/httpsig v1.2.4 h1:mI5bH0nm4xn7K18fo1K3okNDRq8CCJ0KbBYWyA6r8lU=
|
||||
github.com/42wim/httpsig v1.2.4/go.mod h1:yKsYfSyTBEohkPik224QPFylmzEBtda/kjyIAJjh3ps=
|
||||
github.com/42wim/sshsig v0.0.0-20260317195500-b9f38cf0d432 h1:3Fcz1QzlS7Jv4FT2KI3cHNSZL+KPN3dXxurn9f3YL/Y=
|
||||
@ -76,8 +76,8 @@ github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.8.3/go.mod h1:bnXbvnI9Mfqd
|
||||
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
github.com/alecthomas/chroma/v2 v2.24.1 h1:m5ffpfZbIb++k8AqFEKy9uVgY12xIQtBsQlc6DfZJQM=
|
||||
github.com/alecthomas/chroma/v2 v2.24.1/go.mod h1:l+ohZ9xRXIbGe7cIW+YZgOGbvuVLjMps/FYN/CwuabI=
|
||||
github.com/alecthomas/chroma/v2 v2.25.0 h1:DWkVlxrNpxPf+Qcfe04LBqUArxUiybK8ZQ9T7OFu68E=
|
||||
github.com/alecthomas/chroma/v2 v2.25.0/go.mod h1:+95AZrRWlpW9g6qXD7S7UdHviopsGP/kCIrtJcU3QoQ=
|
||||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs=
|
||||
github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
@ -236,13 +236,12 @@ github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454Wv
|
||||
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21 h1:PdsjTl0Cg+ZJgOx/CFV5NNgO1ThTreqdgKYiDCMHJwA=
|
||||
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21/go.mod h1:xJvkyD6Y2rZapGvPJLYo9dyx1s5dxBEDPa8T3YTuOk0=
|
||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2 v1.12.0 h1:0j4c5qQmnC6XOWNjP3PIXURXN2gWx76rd3KvgdPkCz8=
|
||||
github.com/dlclark/regexp2 v1.12.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
|
||||
github.com/dlclark/regexp2/v2 v2.1.0 h1:jHXRmHRZGbuQzDZjMlCAXOvQb75iv3HyLDzXGj5H1AY=
|
||||
github.com/dlclark/regexp2/v2 v2.1.0/go.mod h1:Bz5TMy5d8fPK0ximH0Yi9KvsRHNnvXqUx9XG6a4wB+I=
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707 h1:2tV76y6Q9BB+NEBasnqvs7e49aEBFI8ejC89PSnWH+4=
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
|
||||
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
"gitea.dev/models/db"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/shared/types"
|
||||
@ -21,7 +22,6 @@ import (
|
||||
"gitea.dev/modules/translation"
|
||||
"gitea.dev/modules/util"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
|
||||
@ -6,9 +6,8 @@ package actions
|
||||
import (
|
||||
"slices"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
"gitea.dev/modules/translation"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
)
|
||||
|
||||
// Status represents the status of ActionRun, ActionRunJob, ActionTask, or ActionTaskStep
|
||||
|
||||
@ -6,7 +6,8 @@ package actions
|
||||
import (
|
||||
"testing"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
"gitea.dev/models/db"
|
||||
"gitea.dev/models/unit"
|
||||
@ -20,7 +21,6 @@ import (
|
||||
"gitea.dev/modules/timeutil"
|
||||
"gitea.dev/modules/util"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
lru "github.com/hashicorp/golang-lru/v2"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"xorm.io/builder"
|
||||
|
||||
@ -7,12 +7,12 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
"gitea.dev/models/db"
|
||||
"gitea.dev/models/unittest"
|
||||
"gitea.dev/modules/actions/jobparser"
|
||||
"gitea.dev/modules/timeutil"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
@ -23,7 +23,7 @@ import (
|
||||
"gitea.dev/modules/timeutil"
|
||||
"gitea.dev/modules/util"
|
||||
|
||||
"github.com/dlclark/regexp2"
|
||||
"github.com/dlclark/regexp2/v2"
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
|
||||
@ -12,12 +12,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
"gitea.dev/models/dbfs"
|
||||
"gitea.dev/modules/log"
|
||||
"gitea.dev/modules/storage"
|
||||
"gitea.dev/modules/zstd"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
|
||||
@ -105,6 +105,7 @@
|
||||
"copy_error": "Échec de la copie",
|
||||
"copy_type_unsupported": "Ce type de fichier ne peut pas être copié",
|
||||
"copy_filename": "Copier le nom du fichier",
|
||||
"copy_output": "Copier la sortie",
|
||||
"write": "Écrire",
|
||||
"preview": "Aperçu",
|
||||
"loading": "Chargement…",
|
||||
@ -3439,7 +3440,7 @@
|
||||
"action.transfer_repo": "a transféré le dépôt <code>%s</code> vers <a href=\"%s\">%s</a>",
|
||||
"action.push_tag": "a poussé l’étiquette <a href=\"%[2]s\">%[3]s</a> de <a href=\"%[1]s\">%[4]s</a>",
|
||||
"action.delete_tag": "a supprimé l’étiquette %[2]s de <a href=\"%[1]s\">%[3]s</a>",
|
||||
"action.delete_branch": "a supprimée la branche %[2]s de <a href=\"%[1]s\">%[3]s</a>",
|
||||
"action.delete_branch": "a supprimé la branche %[2]s de <a href=\"%[1]s\">%[3]s</a>",
|
||||
"action.compare_branch": "Comparer",
|
||||
"action.compare_commits": "Comparer %d révisions",
|
||||
"action.compare_commits_general": "Comparer les révisions",
|
||||
@ -3758,6 +3759,8 @@
|
||||
"actions.runners.reset_registration_token_confirm": "Voulez-vous révoquer le jeton actuel et en générer un nouveau ?",
|
||||
"actions.runners.reset_registration_token_success": "Le jeton d’inscription de l’exécuteur a été réinitialisé avec succès",
|
||||
"actions.runs.all_workflows": "Tous les flux de travail",
|
||||
"actions.runs.other_workflows": "Autres flux de travail",
|
||||
"actions.runs.other_workflows_tooltip": "Les flux de travail qui ont été exécutés dans ce dépôt mais qui n’existent pas dans la branche par défaut.",
|
||||
"actions.runs.workflow_run_count_1": "%d exécution du workflow",
|
||||
"actions.runs.workflow_run_count_n": "%d exécutions du workflow",
|
||||
"actions.runs.commit": "Révision",
|
||||
@ -3773,6 +3776,8 @@
|
||||
"actions.runs.status": "Statut",
|
||||
"actions.runs.actors_no_select": "Tous les acteurs",
|
||||
"actions.runs.status_no_select": "Touts les statuts",
|
||||
"actions.runs.branch": "Branche",
|
||||
"actions.runs.branches_no_select": "Toutes les branches",
|
||||
"actions.runs.no_results": "Aucun résultat correspondant.",
|
||||
"actions.runs.no_workflows": "Il n'y a pas encore de workflows.",
|
||||
"actions.runs.no_workflows.quick_start": "Vous découvrez les Actions Gitea ? Consultez <a target=\"_blank\" rel=\"noopener noreferrer\" href=\"%s\">le didacticiel</a>.",
|
||||
|
||||
@ -105,6 +105,7 @@
|
||||
"copy_error": "复制失败",
|
||||
"copy_type_unsupported": "无法复制此类型的文件内容",
|
||||
"copy_filename": "复制文件名",
|
||||
"copy_output": "复制输出",
|
||||
"write": "撰写",
|
||||
"preview": "预览",
|
||||
"loading": "正在加载…",
|
||||
@ -1321,7 +1322,7 @@
|
||||
"repo.commits.desc": "浏览代码修改历史",
|
||||
"repo.commits.commits": "次代码提交",
|
||||
"repo.commits.no_commits": "没有共同的提交。「%s」和「%s」的历史完全不同。",
|
||||
"repo.commits.nothing_to_compare": "这些分支是相同的。",
|
||||
"repo.commits.nothing_to_compare": "没有差异可显示。",
|
||||
"repo.commits.search.tooltip": "您可以在关键词前加上前缀,如「author:」、「committer:」、「after:」或「before:」,例如「retrin author:Alice before:2019-01-13」。",
|
||||
"repo.commits.search_branch": "此分支",
|
||||
"repo.commits.search_all": "所有分支",
|
||||
@ -1783,9 +1784,9 @@
|
||||
"repo.pulls.select_commit_hold_shift_for_range": "选择提交。按住 Shift + 单击选择一个范围",
|
||||
"repo.pulls.review_only_possible_for_full_diff": "只有在查看全部差异时才能进行审核",
|
||||
"repo.pulls.filter_changes_by_commit": "按提交筛选",
|
||||
"repo.pulls.nothing_to_compare": "分支内容相同,无需创建合并请求。",
|
||||
"repo.pulls.nothing_to_compare": "没有差异可显示。无需创建合并请求。",
|
||||
"repo.pulls.no_common_history": "这些分支没有共同的合并基点。请选择不同的基点或比较分支。",
|
||||
"repo.pulls.nothing_to_compare_have_tag": "所选分支 / Git 标签相同。",
|
||||
"repo.pulls.nothing_to_compare_have_tag": "所选分支或 Git 标签之间没有差异可显示。",
|
||||
"repo.pulls.nothing_to_compare_and_allow_empty_pr": "这些分支是相等的,此合并请求将为空。",
|
||||
"repo.pulls.has_pull_request": "这些分支之间的合并请求已存在:<a href=\"%[1]s\">%[2]s#%[3]d</a>",
|
||||
"repo.pulls.create": "创建合并请求",
|
||||
@ -1819,6 +1820,7 @@
|
||||
"repo.pulls.required_status_check_failed": "一些必要的检查没有成功",
|
||||
"repo.pulls.required_status_check_missing": "缺少一些必要的检查。",
|
||||
"repo.pulls.required_status_check_administrator": "作为管理员,您仍可合并此合并请求",
|
||||
"repo.pulls.required_status_check_bypass_allowlist": "您可以在此次合并中绕过分支保护规则。",
|
||||
"repo.pulls.blocked_by_approvals": "此合并请求还没有足够的批准。已获批准数 %d 个,需获批准数 %d 个。",
|
||||
"repo.pulls.blocked_by_approvals_whitelisted": "此合并请求尚未获得足够的批准。已获得 %d/%d 个来自允许列表中用户或团队的批准。",
|
||||
"repo.pulls.blocked_by_rejection": "此合并请求有官方审核员请求的更改。",
|
||||
@ -2138,7 +2140,9 @@
|
||||
"repo.settings.pulls_desc": "启用合并请求",
|
||||
"repo.settings.pulls.ignore_whitespace": "忽略空白冲突",
|
||||
"repo.settings.pulls.enable_autodetect_manual_merge": "启用自动检查手动合并(注意:在某些特殊情况下可能会出现误判)",
|
||||
"repo.settings.pulls.allow_merge_update": "允许通过合并更新合并请求分支",
|
||||
"repo.settings.pulls.allow_rebase_update": "允许通过变基更新合并请求分支",
|
||||
"repo.settings.pulls.default_update_style": "默认分支更新风格",
|
||||
"repo.settings.pulls.default_target_branch": "新合并请求的默认目标分支",
|
||||
"repo.settings.pulls.default_target_branch_default": "默认分支(%s)",
|
||||
"repo.settings.pulls.default_delete_branch_after_merge": "默认合并后删除合并请求分支",
|
||||
@ -2413,6 +2417,11 @@
|
||||
"repo.settings.protect_merge_whitelist_committers_desc": "仅允许白名单用户或团队合并合并请求到此分支。",
|
||||
"repo.settings.protect_merge_whitelist_users": "合并白名单用户:",
|
||||
"repo.settings.protect_merge_whitelist_teams": "合并白名单团队:",
|
||||
"repo.settings.protect_bypass_allowlist": "绕过分支保护",
|
||||
"repo.settings.protect_enable_bypass_allowlist": "允许指定用户或团队绕过分支保护",
|
||||
"repo.settings.protect_enable_bypass_allowlist_desc": "列入白名单的用户或团队可以执行合并或推送操作,即使在通常情况下,这些操作会被所需的审批、状态检查或受保护文件规则所阻挡。",
|
||||
"repo.settings.protect_bypass_allowlist_users": "允许绕过保护的用户:",
|
||||
"repo.settings.protect_bypass_allowlist_teams": "允许绕过保护的团队:",
|
||||
"repo.settings.protect_check_status_contexts": "启用状态检查",
|
||||
"repo.settings.protect_status_check_patterns": "状态检查表达式:",
|
||||
"repo.settings.protect_status_check_patterns_desc": "输入表达式以指定在分支合并到匹配此规则的分支之前必须通过哪些状态检查。每一行指定一个表达式且表达式不能为空。",
|
||||
@ -2454,7 +2463,7 @@
|
||||
"repo.settings.block_outdated_branch": "如果合并请求已经过时,阻止合并",
|
||||
"repo.settings.block_outdated_branch_desc": "当头部分支落后基础分支时,不能合并。",
|
||||
"repo.settings.block_admin_merge_override": "管理员须遵守分支保护规则",
|
||||
"repo.settings.block_admin_merge_override_desc": "管理员须遵守分支保护规则,不能规避该规则。",
|
||||
"repo.settings.block_admin_merge_override_desc": "管理员必须遵守分支保护规则,且不得绕过这些规则。如果启用了绕过白名单功能,位于绕过白名单中的用户或团队仍可绕过这些规则。",
|
||||
"repo.settings.default_branch_desc": "选择一个默认分支用于提交代码。",
|
||||
"repo.settings.default_target_branch_desc": "如果在仓库高级设置的合并请求部分中进行了设置,则合并请求可以使用不同的默认目标分支。",
|
||||
"repo.settings.merge_style_desc": "合并方式",
|
||||
@ -3483,7 +3492,7 @@
|
||||
"gpg.default_key": "使用默认密钥签名",
|
||||
"gpg.error.extract_sign": "无法提取签名",
|
||||
"gpg.error.generate_hash": "无法生成提交的哈希",
|
||||
"gpg.error.no_committer_account": "没有帐户链接到提交者的邮箱",
|
||||
"gpg.error.no_committer_account": "没有帐户关联到提交者的邮箱",
|
||||
"gpg.error.no_gpg_keys_found": "找不到此签名对应的密钥",
|
||||
"gpg.error.not_signed_commit": "未签名的提交",
|
||||
"gpg.error.failed_retrieval_gpg_keys": "找不到任何与该提交者账号相关的密钥",
|
||||
@ -3622,7 +3631,13 @@
|
||||
"packages.terraform.delete.latest": "无法删除最新版本的 Terraform 状态。",
|
||||
"packages.vagrant.install": "若要添加一个 Vagrant box,请运行以下命令:",
|
||||
"packages.settings.link": "将此软件包链接到仓库",
|
||||
"packages.settings.link.description": "如果您将一个软件包与一个仓库链接起来,软件包将显示在仓库的软件包列表中。",
|
||||
"packages.settings.link.description": "如果您将软件包与仓库关联,该软件包将显示在仓库的软件包列表中。",
|
||||
"packages.settings.link.notice1": "仅同一所有者名下的仓库可以进行关联。",
|
||||
"packages.settings.link.notice2": "关联仓库不会更改软件包的可见性。",
|
||||
"packages.settings.link.notice3": "留空该字段将删除关联。",
|
||||
"packages.settings.visibility": "软件包可见性",
|
||||
"packages.settings.visibility.inherit": "软件包的可见性继承自其所有者,无法在此处单独更改。若要更改,请更新拥有此软件包的用户或组织的可见性设置。",
|
||||
"packages.settings.visibility.button": "更改所有者可见性",
|
||||
"packages.settings.link.select": "选择仓库",
|
||||
"packages.settings.link.button": "更新仓库链接",
|
||||
"packages.settings.link.success": "仓库链接已成功更新。",
|
||||
@ -3696,6 +3711,7 @@
|
||||
"actions.status.success": "成功",
|
||||
"actions.status.failure": "失败",
|
||||
"actions.status.cancelled": "已取消",
|
||||
"actions.status.cancelling": "取消中",
|
||||
"actions.status.skipped": "已忽略",
|
||||
"actions.status.blocked": "阻塞中",
|
||||
"actions.runners": "运行器",
|
||||
@ -3743,6 +3759,8 @@
|
||||
"actions.runners.reset_registration_token_confirm": "是否吊销当前令牌并生成一个新令牌?",
|
||||
"actions.runners.reset_registration_token_success": "成功重置运行器注册令牌",
|
||||
"actions.runs.all_workflows": "所有工作流",
|
||||
"actions.runs.other_workflows": "其他工作流",
|
||||
"actions.runs.other_workflows_tooltip": "在此仓库中已执行,但不存在于默认分支上的工作流。",
|
||||
"actions.runs.workflow_run_count_1": "%d 次工作流运行",
|
||||
"actions.runs.workflow_run_count_n": "%d 次工作流运行",
|
||||
"actions.runs.commit": "提交",
|
||||
@ -3758,6 +3776,8 @@
|
||||
"actions.runs.status": "状态",
|
||||
"actions.runs.actors_no_select": "所有操作者",
|
||||
"actions.runs.status_no_select": "所有状态",
|
||||
"actions.runs.branch": "分支",
|
||||
"actions.runs.branches_no_select": "所有分支",
|
||||
"actions.runs.no_results": "没有匹配的结果。",
|
||||
"actions.runs.no_workflows": "目前还没有工作流。",
|
||||
"actions.runs.no_workflows.quick_start": "不知道如何使用 Gitea 工作流吗?请查看<a target=\"_blank\" rel=\"noopener noreferrer\" href=\"%s\">快速开始指南</a>。",
|
||||
|
||||
@ -43,10 +43,6 @@
|
||||
"matchPackageNames": ["github.com/urfave/cli/v3"],
|
||||
"allowedVersions": "<3.6.2", // v3.6.2 breaks -c flag parsing in help commands
|
||||
},
|
||||
{
|
||||
"matchPackageNames": ["github.com/dlclark/regexp2"],
|
||||
"allowedVersions": "^1", // v2 fails to build on linux/386: https://github.com/dlclark/regexp2/issues/102
|
||||
},
|
||||
{
|
||||
"matchPackageNames": ["github.com/Azure/azure-sdk-for-go/sdk/azcore"],
|
||||
"allowedVersions": "<1.21.0", // v1.21.0+ uses API version unsupported by Azurite in CI
|
||||
|
||||
@ -8,10 +8,10 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
pingv1 "gitea.dev/actions-proto-go/ping/v1"
|
||||
"gitea.dev/actions-proto-go/ping/v1/pingv1connect"
|
||||
"gitea.dev/modules/log"
|
||||
|
||||
pingv1 "code.gitea.io/actions-proto-go/ping/v1"
|
||||
"code.gitea.io/actions-proto-go/ping/v1/pingv1connect"
|
||||
"connectrpc.com/connect"
|
||||
)
|
||||
|
||||
|
||||
@ -8,8 +8,9 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
pingv1 "code.gitea.io/actions-proto-go/ping/v1"
|
||||
"code.gitea.io/actions-proto-go/ping/v1/pingv1connect"
|
||||
pingv1 "gitea.dev/actions-proto-go/ping/v1"
|
||||
"gitea.dev/actions-proto-go/ping/v1/pingv1connect"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@ -9,6 +9,8 @@ import (
|
||||
"net/http"
|
||||
"slices"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
"gitea.dev/actions-proto-go/runner/v1/runnerv1connect"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
user_model "gitea.dev/models/user"
|
||||
@ -17,8 +19,6 @@ import (
|
||||
"gitea.dev/modules/util"
|
||||
actions_service "gitea.dev/services/actions"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"code.gitea.io/actions-proto-go/runner/v1/runnerv1connect"
|
||||
"connectrpc.com/connect"
|
||||
gouuid "github.com/google/uuid"
|
||||
"google.golang.org/grpc/codes"
|
||||
@ -310,6 +310,15 @@ func (s *Service) UpdateLog(
|
||||
rows = req.Msg.Rows[ack-req.Msg.Index:]
|
||||
}
|
||||
|
||||
// Ack a re-sent finalize idempotently. Appending new rows past the seal errors.
|
||||
if task.LogInStorage {
|
||||
if len(rows) > 0 {
|
||||
return nil, status.Errorf(codes.AlreadyExists, "log file has been archived")
|
||||
}
|
||||
res.Msg.AckIndex = ack
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Bail unless we have new rows or a NoMore to finalize. Even with
|
||||
// NoMore, bail when the runner has outrun the server — archiving a
|
||||
// log with a gap is worse than asking it to retry.
|
||||
@ -318,10 +327,6 @@ func (s *Service) UpdateLog(
|
||||
return res, nil
|
||||
}
|
||||
|
||||
if task.LogInStorage {
|
||||
return nil, status.Errorf(codes.AlreadyExists, "log file has been archived")
|
||||
}
|
||||
|
||||
// WriteLogs is called even with no rows: with offset==0 it bootstraps
|
||||
// an empty DBFS file so TransferLogs below has something to read when
|
||||
// the runner finalizes a task that produced no log output.
|
||||
|
||||
@ -6,9 +6,9 @@ package runner
|
||||
import (
|
||||
"testing"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
||||
@ -8,11 +8,11 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
"gitea.dev/models/db"
|
||||
secret_model "gitea.dev/models/secret"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
asymkey_model "gitea.dev/models/asymkey"
|
||||
"gitea.dev/models/auth"
|
||||
@ -36,7 +37,6 @@ import (
|
||||
asymkey_service "gitea.dev/services/asymkey"
|
||||
"gitea.dev/services/gitdiff"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"gitea.com/gitea/runner/act/model"
|
||||
)
|
||||
|
||||
|
||||
@ -17,7 +17,6 @@ import (
|
||||
"gitea.dev/modules/setting"
|
||||
"gitea.dev/services/mailer/token"
|
||||
|
||||
"github.com/dimiro1/reply"
|
||||
"github.com/emersion/go-imap"
|
||||
"github.com/emersion/go-imap/client"
|
||||
"github.com/jhillyerd/enmime/v2"
|
||||
@ -356,7 +355,7 @@ func getContentFromMailReader(env *enmime.Envelope) *MailContent {
|
||||
}
|
||||
|
||||
return &MailContent{
|
||||
Content: reply.FromText(env.Text),
|
||||
Content: extractReply(env.Text),
|
||||
Attachments: attachments,
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,3 +150,56 @@ func TestGetContentFromMailReader(t *testing.T) {
|
||||
assert.Equal(t, "mail content without signature", content.Content)
|
||||
assert.Empty(t, content.Attachments)
|
||||
}
|
||||
|
||||
func TestExtractReply(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{"plain text", "Email with only text.", "Email with only text."},
|
||||
{"crlf normalized", "line one\r\nline two\r\n", "line one\nline two"},
|
||||
{"trim blank lines", "\n\n\nactual reply\n\n\n", "actual reply"},
|
||||
{"signature delimiter", "the reply\n--\nJohn Doe\nAcme", "the reply"},
|
||||
{"rfc signature delimiter", "the reply\n-- \nJohn Doe", "the reply"},
|
||||
{"mobile signature", "My answer is yes.\n\nSent from my iPhone", "My answer is yes."},
|
||||
{"quote only kept", "> Email with only quote.", "> Email with only quote."},
|
||||
{"leading quote kept", "> This is a quote.\n\nAnd this is some text.", "> This is a quote.\n\nAnd this is some text."},
|
||||
{"trailing quote stripped", "My reply.\n\n> original line 1\n> original line 2", "My reply."},
|
||||
{"attribution and quote", "Looks good.\n\nOn Mon, Jan 1, 2024 John <j@x.com> wrote:\n> please review", "Looks good."},
|
||||
{"attribution without quote marks", "My reply.\n\nOn Wed, Sep 25, 2013, richard wrote:\noriginal text", "My reply."},
|
||||
{"original message separator", "Foo\n\n-------- Original Message --------\n\nTHE END.", "Foo"},
|
||||
{"outlook header block", "This is the actual reply.\n\nFrom: Some One <a@b.com>\nSent: Monday\nTo: Someone\nSubject: hi\n\nquoted body", "This is the actual reply."},
|
||||
{"french attribution", "C'est super !\n\nLe 4 janv. 2016 19:03, \"Neil\" <a@b.com> a écrit :\n> quoted", "C'est super !"},
|
||||
{"german attribution", "Hey :)\n\nAm 03.02.2016 3:35 schrieb Max <a@b.com>:\n> quoted", "Hey :)"},
|
||||
{"cyrillic wrote verb", "Yes.\n\n6 октября 2014 lidel написал:\n> quoted", "Yes."},
|
||||
{"localized signature", "My answer.\n\nEnvoyé depuis mon iPhone", "My answer."},
|
||||
{"swedish header block", "Hi everyone!\n\nFrån: Foo <a@b.com>\nSkickat: den 5 juni\nTill: x@y.com\nÄmne: hi\n\nbody", "Hi everyone!"},
|
||||
{"attribution only is empty", "On Mon, Jan 1, 2024 at 10:00 John <j@x.com> wrote:\n> please review", ""},
|
||||
{"prose ending in wrote kept", "Hi Bob,\nThanks for the report you wrote\nI'll fix it.", "Hi Bob,\nThanks for the report you wrote\nI'll fix it."},
|
||||
{"on with year and no time kept", "Hi,\nOn the 2024 roadmap we have three items.\nPlease review.", "Hi,\nOn the 2024 roadmap we have three items.\nPlease review."},
|
||||
{"date prose kept", "Notes:\n5 issues 2024 fixed at 9:15 today\nmore notes", "Notes:\n5 issues 2024 fixed at 9:15 today\nmore notes"},
|
||||
{"header needs from first", "Quick note:\nTo: which server?\nFrom: tests pass.\nThanks", "Quick note:\nTo: which server?\nFrom: tests pass.\nThanks"},
|
||||
{"indented header block", "Reply text.\n\n From: A <a@b.com>\n Sent: Monday\n To: x\n Subject: hi\n\nbody", "Reply text."},
|
||||
{"chinese signature", "回复内容\n\n發自我的iPhone", "回复内容"},
|
||||
{"japanese signature", "返信します\n\niPhoneから送信", "返信します"},
|
||||
{"chinese header block", "回复内容\n\n发件人:张三\n收件人:李四\n主题:你好\n\n原文", "回复内容"},
|
||||
{"japanese header block", "本文です\n\n差出人:山田\n宛先:田中\n件名:こんにちは\n\n原文", "本文です"},
|
||||
{"name-first attribution", "Okay.\n\nErlend <meta@x.com> schrieb am Di., 16. Aug. 2016\num 12:52 Uhr:\n> quoted", "Okay."},
|
||||
{"chinese attribution", "你好,谢谢回复。\n\n在 2024年1月1日,张三 <z@x.com> 写道:\n> 原始内容", "你好,谢谢回复。"},
|
||||
{"japanese attribution", "了解しました。\n\n田中さんは書きました:\n> 引用", "了解しました。"},
|
||||
{"korean attribution", "감사합니다.\n\n홍길동님이 작성:\n> 인용", "감사합니다."},
|
||||
{"email mention kept", "I asked Bob <bob@x.com> and he wrote back yes.\nSo we proceed.", "I asked Bob <bob@x.com> and he wrote back yes.\nSo we proceed."},
|
||||
{"trailing mailbox glyph", "My reply here.\n\nᐧ", "My reply here."},
|
||||
{"on with year and time prose kept", "On the 2024 roadmap we should meet at 10:00.\nI'll send invites.", "On the 2024 roadmap we should meet at 10:00.\nI'll send invites."},
|
||||
{"spanish year and time prose kept", "El informe del 2024 estará listo a las 10:00.\nGracias.", "El informe del 2024 estará listo a las 10:00.\nGracias."},
|
||||
{"chinese prose kept", "谢谢,已测试。\n发自我的内心的感谢", "谢谢,已测试。\n发自我的内心的感谢"},
|
||||
{"korean prose kept", "확인했습니다.\n이 문서는 회사에서 보냄", "확인했습니다.\n이 문서는 회사에서 보냄"},
|
||||
{"japanese prose kept", "了解しました。\n資料は会議から送信", "了解しました。\n資料は会議から送信"},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
assert.Equal(t, c.expected, extractReply(c.input))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
137
services/mailer/incoming/reply.go
Normal file
137
services/mailer/incoming/reply.go
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package incoming
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"gitea.dev/modules/util"
|
||||
)
|
||||
|
||||
const (
|
||||
yearToken = `\b\d{4}\b` // 4-digit year
|
||||
timeToken = `\b\d{1,2}[:.]\d{2}\b` // HH:MM or HH.MM
|
||||
// "wrote" verbs ending an attribution line; CJK ones are matched without a
|
||||
// preceding word-separator since those scripts don't space their words
|
||||
wroteVerbs = `wrote|writes|schrieb|skrev|napisał|escreveu|escribió|написал|пише|a écrit`
|
||||
cjkWroteVerbs = `写道|寫道|書きました|작성`
|
||||
// device names anchoring CJK mobile signatures, so prose isn't mistaken for one
|
||||
cjkDevice = `iphone|ipad|ipod|android|galaxy|手机|手機|平板`
|
||||
)
|
||||
|
||||
// forwarded-mail header fields across the common mail clients/locales. headerFromFields
|
||||
// (the "From"-equivalents) must begin a block; headerFields is the full set allowed to
|
||||
// follow. Matched as a prefix by headerLine, so adding a locale is a one-line change.
|
||||
var (
|
||||
headerFromFields = []string{
|
||||
"from", "fra", "de", "von", "da", "van", "från", "expéditeur",
|
||||
"发件人", "寄件者", "差出人", "보낸사람",
|
||||
}
|
||||
headerFields = append([]string{
|
||||
"to", "cc", "bcc", "sent", "date", "subject", "reply-to",
|
||||
"til", "emne", "an", "betreff", "gesendet", "para", "assunto", "asunto",
|
||||
"risposta", "inviato", "oggetto", "destinataire", "objet", "répondre à",
|
||||
"aan", "onderwerp", "beantwoorden", "skickat", "till", "ämne",
|
||||
"收件人", "主题", "主旨", "主題", "收件者", "抄送", "日期", "宛先", "件名", "받는사람", "제목",
|
||||
}, headerFromFields...)
|
||||
)
|
||||
|
||||
// patterns are compiled on first use so the incoming-mail feature adds nothing to startup.
|
||||
var patterns = sync.OnceValue(func() (ret struct {
|
||||
signature, attribution, separator *regexp.Regexp
|
||||
},
|
||||
) {
|
||||
// "-- " delimiter and common mobile footers with frequent localizations. The CJK
|
||||
// forms require a device name so ordinary prose like "发自我的内心" or "会議から送信"
|
||||
// is not mistaken for a signature.
|
||||
ret.signature = regexp.MustCompile(`(?i)^(--|__|—` +
|
||||
`|sent (from|via|with) .+|get outlook for .+` +
|
||||
`|envoyé depuis mon .+|sendt fra min .+|von meinem .+|verzonden (met|vanaf) .+` +
|
||||
`|(發|发)自我的.*(` + cjkDevice + `).*` +
|
||||
`|.*(` + cjkDevice + `).*(から送信|에서 보냄|傳送|发送))$`)
|
||||
|
||||
// attribution introducing quoted history: a line ending in a "wrote:" verb
|
||||
// (Latin/Cyrillic or CJK), a "Name <email> wrote" line, a lead word directly
|
||||
// followed by a day number or weekday plus a year and a time, or an ISO-date-led
|
||||
// line. The date phrasing, trailing colon and the email before the verb guard
|
||||
// against prose (so "On the 2024 roadmap … at 10:00" is not an attribution).
|
||||
ret.attribution = regexp.MustCompile(`(?i)^>*\s*(` +
|
||||
`.*[\s">'](` + wroteVerbs + `)\s*[::]` +
|
||||
`|.*(` + cjkWroteVerbs + `)\s*[::]` +
|
||||
`|.*<\S+@\S+>\s+(` + wroteVerbs + `)\b.*` +
|
||||
`|(on|at|le|am|el|em|den|il|op|dnia|w dniu)\b[\s,]*(\d|(?:mon|tue|wed|thu|fri|sat|sun)\b).*` + yearToken + `.*` + timeToken + `.*` +
|
||||
`|\d{4}-\d{2}-\d{2}\b.*` + timeToken + `.*` +
|
||||
`)$`)
|
||||
|
||||
// a dash/underscore rule line, or text fenced by dashes such as
|
||||
// "-------- Original Message --------" or "-----Mensaje original-----"
|
||||
ret.separator = regexp.MustCompile(`(?i)^\s*\*?\s*([-_]{5,}|-{2,}.+-{2,}|original message|forwarded message)\s*\*?\s*$`)
|
||||
return ret
|
||||
})
|
||||
|
||||
// extractReply returns the user-written part of a plain-text email body, dropping
|
||||
// quoted history, the reply attribution, signatures and forwarded headers. It is a
|
||||
// slim, dependency-free reimplementation based on github.com/dimiro1/reply (MIT),
|
||||
// covering the common mail-client formats and languages; bottom posting and
|
||||
// forwarded bodies are not handled.
|
||||
func extractReply(text string) string {
|
||||
p := patterns()
|
||||
lines := strings.Split(util.NormalizeStringEOL(text), "\n")
|
||||
|
||||
// cut at the first line that begins quoted history, a signature or a header block
|
||||
for i := range lines {
|
||||
trimmed := strings.TrimSpace(lines[i])
|
||||
if p.signature.MatchString(trimmed) || p.attribution.MatchString(trimmed) ||
|
||||
p.separator.MatchString(trimmed) || headerBlock(trimmed, lines[i+1:]) {
|
||||
lines = lines[:i]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// drop the trailing block of quoted/blank lines, unless the whole body is quoted
|
||||
end := len(lines)
|
||||
for end > 0 {
|
||||
// "ᐧ" is the trailing marker some mobile clients (Mailbox) append
|
||||
if t := strings.TrimSpace(lines[end-1]); t != "" && t != "ᐧ" && !strings.HasPrefix(t, ">") {
|
||||
break
|
||||
}
|
||||
end--
|
||||
}
|
||||
if end > 0 {
|
||||
lines = lines[:end]
|
||||
}
|
||||
|
||||
return strings.TrimSpace(strings.Join(lines, "\n"))
|
||||
}
|
||||
|
||||
// headerBlock reports whether a forwarded-mail header block starts here: the
|
||||
// (already-trimmed) first line is a "From" field and the next non-blank line is
|
||||
// another field, so a lone "Subject:" sentence is not a boundary.
|
||||
func headerBlock(first string, rest []string) bool {
|
||||
if !headerLine(first, headerFromFields) {
|
||||
return false
|
||||
}
|
||||
for _, next := range rest {
|
||||
if t := strings.TrimSpace(next); t != "" {
|
||||
return headerLine(t, headerFields)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// headerLine reports whether the already-trimmed line is a "Field:" header for one
|
||||
// of fields. An ASCII colon must be followed by a space so prose like "To:do this"
|
||||
// is ignored; the CJK fullwidth colon ":" needs no space.
|
||||
func headerLine(line string, fields []string) bool {
|
||||
lower := strings.ToLower(line)
|
||||
for _, field := range fields {
|
||||
if rest, ok := strings.CutPrefix(lower, field); ok &&
|
||||
(strings.HasPrefix(rest, ": ") || strings.HasPrefix(rest, ":")) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -16,8 +16,7 @@ import (
|
||||
"gitea.dev/modules/log"
|
||||
base "gitea.dev/modules/migration"
|
||||
"gitea.dev/modules/structs"
|
||||
|
||||
gitea_sdk "code.gitea.io/sdk/gitea"
|
||||
gitea_sdk "gitea.dev/sdk"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -67,6 +66,7 @@ func (f *GiteaDownloaderFactory) GitServiceType() structs.GitServiceType {
|
||||
// GiteaDownloader implements a Downloader interface to get repository information's
|
||||
type GiteaDownloader struct {
|
||||
base.NullDownloader
|
||||
ctx context.Context
|
||||
client *gitea_sdk.Client
|
||||
baseURL string
|
||||
repoOwner string
|
||||
@ -84,7 +84,6 @@ func NewGiteaDownloader(ctx context.Context, baseURL, repoPath, username, passwo
|
||||
baseURL,
|
||||
gitea_sdk.SetToken(token),
|
||||
gitea_sdk.SetBasicAuth(username, password),
|
||||
gitea_sdk.SetContext(ctx),
|
||||
gitea_sdk.SetHTTPClient(NewMigrationHTTPClient()),
|
||||
)
|
||||
if err != nil {
|
||||
@ -95,7 +94,7 @@ func NewGiteaDownloader(ctx context.Context, baseURL, repoPath, username, passwo
|
||||
path := strings.Split(repoPath, "/")
|
||||
|
||||
paginationSupport := true
|
||||
if err = giteaClient.CheckServerVersionConstraint(">=1.12"); err != nil {
|
||||
if err = giteaClient.CheckServerVersionConstraint(ctx, ">=1.12"); err != nil {
|
||||
paginationSupport = false
|
||||
}
|
||||
|
||||
@ -103,7 +102,7 @@ func NewGiteaDownloader(ctx context.Context, baseURL, repoPath, username, passwo
|
||||
// (default would be 50 but this can differ)
|
||||
maxPerPage := 10
|
||||
// gitea instances >=1.13 can tell us what maximum they have
|
||||
apiConf, _, err := giteaClient.GetGlobalAPISettings()
|
||||
apiConf, _, err := giteaClient.Settings.GetGlobalAPISettings(ctx)
|
||||
if err != nil {
|
||||
log.Info("Unable to get global API settings. Ignoring these.")
|
||||
log.Debug("giteaClient.GetGlobalAPISettings. Error: %v", err)
|
||||
@ -113,6 +112,7 @@ func NewGiteaDownloader(ctx context.Context, baseURL, repoPath, username, passwo
|
||||
}
|
||||
|
||||
return &GiteaDownloader{
|
||||
ctx: ctx,
|
||||
client: giteaClient,
|
||||
baseURL: baseURL,
|
||||
repoOwner: path[0],
|
||||
@ -140,7 +140,7 @@ func (g *GiteaDownloader) GetRepoInfo(_ context.Context) (*base.Repository, erro
|
||||
return nil, errors.New("error: GiteaDownloader is nil")
|
||||
}
|
||||
|
||||
repo, _, err := g.client.GetRepo(g.repoOwner, g.repoName)
|
||||
repo, _, err := g.client.Repositories.GetRepo(g.ctx, g.repoOwner, g.repoName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -159,7 +159,7 @@ func (g *GiteaDownloader) GetRepoInfo(_ context.Context) (*base.Repository, erro
|
||||
|
||||
// GetTopics return gitea topics
|
||||
func (g *GiteaDownloader) GetTopics(_ context.Context) ([]string, error) {
|
||||
topics, _, err := g.client.ListRepoTopics(g.repoOwner, g.repoName, gitea_sdk.ListRepoTopicsOptions{})
|
||||
topics, _, err := g.client.Repositories.ListRepoTopics(g.ctx, g.repoOwner, g.repoName, gitea_sdk.ListRepoTopicsOptions{})
|
||||
return topics, err
|
||||
}
|
||||
|
||||
@ -175,7 +175,7 @@ func (g *GiteaDownloader) GetMilestones(ctx context.Context) ([]*base.Milestone,
|
||||
default:
|
||||
}
|
||||
|
||||
ms, _, err := g.client.ListRepoMilestones(g.repoOwner, g.repoName, gitea_sdk.ListMilestoneOption{
|
||||
ms, _, err := g.client.Repositories.ListMilestones(g.ctx, g.repoOwner, g.repoName, gitea_sdk.ListMilestoneOption{
|
||||
ListOptions: gitea_sdk.ListOptions{
|
||||
PageSize: g.maxPerPage,
|
||||
Page: i,
|
||||
@ -240,7 +240,7 @@ func (g *GiteaDownloader) GetLabels(ctx context.Context) ([]*base.Label, error)
|
||||
default:
|
||||
}
|
||||
|
||||
ls, _, err := g.client.ListRepoLabels(g.repoOwner, g.repoName, gitea_sdk.ListLabelsOptions{ListOptions: gitea_sdk.ListOptions{
|
||||
ls, _, err := g.client.Repositories.ListRepoLabels(g.ctx, g.repoOwner, g.repoName, gitea_sdk.ListLabelsOptions{ListOptions: gitea_sdk.ListOptions{
|
||||
PageSize: g.maxPerPage,
|
||||
Page: i,
|
||||
}})
|
||||
@ -288,7 +288,7 @@ func (g *GiteaDownloader) convertGiteaRelease(rel *gitea_sdk.Release) *base.Rele
|
||||
Created: asset.Created,
|
||||
DownloadURL: &asset.DownloadURL,
|
||||
DownloadFunc: func() (io.ReadCloser, error) {
|
||||
asset, _, err := g.client.GetReleaseAttachment(g.repoOwner, g.repoName, rel.ID, assetID)
|
||||
asset, _, err := g.client.Releases.GetReleaseAttachment(g.ctx, g.repoOwner, g.repoName, rel.ID, assetID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -328,7 +328,7 @@ func (g *GiteaDownloader) GetReleases(ctx context.Context) ([]*base.Release, err
|
||||
default:
|
||||
}
|
||||
|
||||
rl, _, err := g.client.ListReleases(g.repoOwner, g.repoName, gitea_sdk.ListReleasesOptions{ListOptions: gitea_sdk.ListOptions{
|
||||
rl, _, err := g.client.Releases.ListReleases(g.ctx, g.repoOwner, g.repoName, gitea_sdk.ListReleasesOptions{ListOptions: gitea_sdk.ListOptions{
|
||||
PageSize: g.maxPerPage,
|
||||
Page: i,
|
||||
}})
|
||||
@ -347,7 +347,7 @@ func (g *GiteaDownloader) GetReleases(ctx context.Context) ([]*base.Release, err
|
||||
}
|
||||
|
||||
func (g *GiteaDownloader) getIssueReactions(ctx context.Context, index int64) ([]*base.Reaction, error) {
|
||||
if err := g.client.CheckServerVersionConstraint(">=1.11"); err != nil {
|
||||
if err := g.client.CheckServerVersionConstraint(g.ctx, ">=1.11"); err != nil {
|
||||
log.Info("GiteaDownloader: instance to old, skip getIssueReactions")
|
||||
return nil, nil
|
||||
}
|
||||
@ -362,7 +362,7 @@ func (g *GiteaDownloader) getIssueReactions(ctx context.Context, index int64) ([
|
||||
default:
|
||||
}
|
||||
|
||||
reactions, _, err := g.client.ListIssueReactions(g.repoOwner, g.repoName, index, gitea_sdk.ListIssueReactionsOptions{ListOptions: gitea_sdk.ListOptions{
|
||||
reactions, _, err := g.client.Issues.ListIssueReactions(g.ctx, g.repoOwner, g.repoName, index, gitea_sdk.ListIssueReactionsOptions{ListOptions: gitea_sdk.ListOptions{
|
||||
PageSize: g.maxPerPage,
|
||||
Page: i,
|
||||
}})
|
||||
@ -387,11 +387,11 @@ func (g *GiteaDownloader) getIssueReactions(ctx context.Context, index int64) ([
|
||||
|
||||
func (g *GiteaDownloader) getCommentReactions(commentID int64) ([]*base.Reaction, error) {
|
||||
var reactions []*base.Reaction
|
||||
if err := g.client.CheckServerVersionConstraint(">=1.11"); err != nil {
|
||||
if err := g.client.CheckServerVersionConstraint(g.ctx, ">=1.11"); err != nil {
|
||||
log.Info("GiteaDownloader: instance to old, skip getCommentReactions")
|
||||
return reactions, nil
|
||||
}
|
||||
rl, _, err := g.client.GetIssueCommentReactions(g.repoOwner, g.repoName, commentID)
|
||||
rl, _, err := g.client.Issues.GetIssueCommentReactions(g.ctx, g.repoOwner, g.repoName, commentID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -413,7 +413,7 @@ func (g *GiteaDownloader) GetIssues(ctx context.Context, page, perPage int) ([]*
|
||||
}
|
||||
allIssues := make([]*base.Issue, 0, perPage)
|
||||
|
||||
issues, _, err := g.client.ListRepoIssues(g.repoOwner, g.repoName, gitea_sdk.ListIssueOption{
|
||||
issues, _, err := g.client.Issues.ListRepoIssues(g.ctx, g.repoOwner, g.repoName, gitea_sdk.ListIssueOption{
|
||||
ListOptions: gitea_sdk.ListOptions{Page: page, PageSize: perPage},
|
||||
State: gitea_sdk.StateAll,
|
||||
Type: gitea_sdk.IssueTypeIssue,
|
||||
@ -481,7 +481,7 @@ func (g *GiteaDownloader) GetComments(ctx context.Context, commentable base.Comm
|
||||
default:
|
||||
}
|
||||
|
||||
comments, _, err := g.client.ListIssueComments(g.repoOwner, g.repoName, commentable.GetForeignIndex(), gitea_sdk.ListIssueCommentOptions{ListOptions: gitea_sdk.ListOptions{
|
||||
comments, _, err := g.client.Issues.ListIssueComments(g.ctx, g.repoOwner, g.repoName, commentable.GetForeignIndex(), gitea_sdk.ListIssueCommentOptions{ListOptions: gitea_sdk.ListOptions{
|
||||
PageSize: g.maxPerPage,
|
||||
Page: i,
|
||||
}})
|
||||
@ -522,7 +522,7 @@ func (g *GiteaDownloader) GetPullRequests(ctx context.Context, page, perPage int
|
||||
}
|
||||
allPRs := make([]*base.PullRequest, 0, perPage)
|
||||
|
||||
prs, _, err := g.client.ListRepoPullRequests(g.repoOwner, g.repoName, gitea_sdk.ListPullRequestsOptions{
|
||||
prs, _, err := g.client.PullRequests.ListRepoPullRequests(g.ctx, g.repoOwner, g.repoName, gitea_sdk.ListPullRequestsOptions{
|
||||
ListOptions: gitea_sdk.ListOptions{
|
||||
Page: page,
|
||||
PageSize: perPage,
|
||||
@ -637,7 +637,7 @@ func (g *GiteaDownloader) GetPullRequests(ctx context.Context, page, perPage int
|
||||
|
||||
// GetReviews returns pull requests review
|
||||
func (g *GiteaDownloader) GetReviews(ctx context.Context, reviewable base.Reviewable) ([]*base.Review, error) {
|
||||
if err := g.client.CheckServerVersionConstraint(">=1.12"); err != nil {
|
||||
if err := g.client.CheckServerVersionConstraint(g.ctx, ">=1.12"); err != nil {
|
||||
log.Info("GiteaDownloader: instance to old, skip GetReviews")
|
||||
return nil, nil
|
||||
}
|
||||
@ -652,7 +652,7 @@ func (g *GiteaDownloader) GetReviews(ctx context.Context, reviewable base.Review
|
||||
default:
|
||||
}
|
||||
|
||||
prl, _, err := g.client.ListPullReviews(g.repoOwner, g.repoName, reviewable.GetForeignIndex(), gitea_sdk.ListPullReviewsOptions{ListOptions: gitea_sdk.ListOptions{
|
||||
prl, _, err := g.client.PullRequests.ListPullReviews(g.ctx, g.repoOwner, g.repoName, reviewable.GetForeignIndex(), gitea_sdk.ListPullReviewsOptions{ListOptions: gitea_sdk.ListOptions{
|
||||
Page: i,
|
||||
PageSize: g.maxPerPage,
|
||||
}})
|
||||
@ -667,7 +667,7 @@ func (g *GiteaDownloader) GetReviews(ctx context.Context, reviewable base.Review
|
||||
continue
|
||||
}
|
||||
|
||||
rcl, _, err := g.client.ListPullReviewComments(g.repoOwner, g.repoName, reviewable.GetForeignIndex(), pr.ID)
|
||||
rcl, _, err := g.client.PullRequests.ListPullReviewComments(g.ctx, g.repoOwner, g.repoName, reviewable.GetForeignIndex(), pr.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@ -18,7 +18,9 @@ test('comment on and close an issue', async ({page, request}) => {
|
||||
await page.getByRole('button', {name: 'Comment', exact: true}).click();
|
||||
await expect(page.locator('.comment-body').filter({hasText: body})).toBeVisible();
|
||||
|
||||
// posting reloaded the page with an empty box, so the status button now reads "Close Issue"
|
||||
// wait for the form to re-initialize (the empty box disables the comment button); a close click
|
||||
// before that does a native submit which lands on a raw JSON page instead of reloading the issue
|
||||
await expect(page.getByRole('button', {name: 'Comment', exact: true})).toBeDisabled();
|
||||
await page.getByRole('button', {name: 'Close Issue'}).click();
|
||||
await expect(page.getByRole('button', {name: 'Reopen Issue'})).toBeVisible();
|
||||
});
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
"gitea.dev/models/db"
|
||||
@ -24,7 +25,6 @@ import (
|
||||
actions_web "gitea.dev/routers/web/repo/actions"
|
||||
actions_service "gitea.dev/services/actions"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
"gitea.dev/models/unittest"
|
||||
@ -18,7 +19,6 @@ import (
|
||||
"gitea.dev/modules/json"
|
||||
"gitea.dev/routers/web/repo/actions"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
@ -13,6 +13,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
"gitea.dev/models/db"
|
||||
@ -26,7 +27,6 @@ import (
|
||||
"gitea.dev/modules/timeutil"
|
||||
actions_service "gitea.dev/services/actions"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"connectrpc.com/connect"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
"gitea.dev/models/dbfs"
|
||||
@ -18,7 +19,6 @@ import (
|
||||
actions_module "gitea.dev/modules/actions"
|
||||
"gitea.dev/modules/storage"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"connectrpc.com/connect"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -73,5 +73,19 @@ jobs:
|
||||
|
||||
_, err = dbfs.Open(t.Context(), actions_module.DBFSPrefix+freshTask.LogFilename)
|
||||
assert.ErrorIs(t, err, os.ErrNotExist, "DBFS row must be cleaned up after TransferLogs")
|
||||
|
||||
// The runner re-sends its final UpdateLog when the response was lost.
|
||||
// A sealed log must ack the re-send and still reject new appended rows.
|
||||
t.Run("re-sent finalize is idempotent", func(t *testing.T) {
|
||||
finalize := &runnerv1.UpdateLogRequest{TaskId: task.Id, Index: 0, Rows: nil, NoMore: true}
|
||||
resp, err := runner.client.runnerServiceClient.UpdateLog(t.Context(), connect.NewRequest(finalize))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 0, resp.Msg.AckIndex)
|
||||
|
||||
_, err = runner.client.runnerServiceClient.UpdateLog(t.Context(), connect.NewRequest(&runnerv1.UpdateLogRequest{
|
||||
TaskId: task.Id, Index: 0, Rows: []*runnerv1.LogRow{{Content: "late"}}, NoMore: true,
|
||||
}))
|
||||
require.Error(t, err, "appending rows past the seal must be rejected")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
@ -20,7 +21,6 @@ import (
|
||||
"gitea.dev/modules/storage"
|
||||
"gitea.dev/modules/test"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
"gitea.dev/models/db"
|
||||
@ -24,7 +25,6 @@ import (
|
||||
"gitea.dev/modules/timeutil"
|
||||
actions_web "gitea.dev/routers/web/repo/actions"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
"gitea.dev/models/db"
|
||||
@ -17,7 +18,6 @@ import (
|
||||
"gitea.dev/modules/setting"
|
||||
actions_web "gitea.dev/routers/web/repo/actions"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -10,13 +10,13 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
pingv1 "gitea.dev/actions-proto-go/ping/v1"
|
||||
"gitea.dev/actions-proto-go/ping/v1/pingv1connect"
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
"gitea.dev/actions-proto-go/runner/v1/runnerv1connect"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
"gitea.dev/modules/setting"
|
||||
|
||||
pingv1 "code.gitea.io/actions-proto-go/ping/v1"
|
||||
"code.gitea.io/actions-proto-go/ping/v1/pingv1connect"
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"code.gitea.io/actions-proto-go/runner/v1/runnerv1connect"
|
||||
"connectrpc.com/connect"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
@ -16,13 +16,13 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
"gitea.dev/models/unittest"
|
||||
user_model "gitea.dev/models/user"
|
||||
"gitea.dev/tests"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -18,6 +18,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
@ -32,7 +33,6 @@ import (
|
||||
"gitea.dev/routers/api/actions"
|
||||
actions_service "gitea.dev/services/actions"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
runnerv1 "gitea.dev/actions-proto-go/runner/v1"
|
||||
actions_model "gitea.dev/models/actions"
|
||||
auth_model "gitea.dev/models/auth"
|
||||
db_model "gitea.dev/models/db"
|
||||
@ -34,7 +35,6 @@ import (
|
||||
"gitea.dev/services/actions"
|
||||
"gitea.dev/tests"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user