mirror of https://github.com/go-gitea/gitea
Merge branch 'main' into add-issue-planned-time
This commit is contained in:
commit
62094d8cf3
|
@ -88,7 +88,7 @@ func main() {
|
|||
}
|
||||
|
||||
func runEnvironmentToIni(c *cli.Context) error {
|
||||
setting.InitWorkPathAndCommonConfig(os.Getenv, setting.ArgWorkPathAndCustomConf{
|
||||
setting.InitWorkPathAndCfgProvider(os.Getenv, setting.ArgWorkPathAndCustomConf{
|
||||
WorkPath: c.String("work-path"),
|
||||
CustomPath: c.String("custom-path"),
|
||||
CustomConf: c.String("config"),
|
||||
|
|
|
@ -119,10 +119,13 @@ RUN_USER = ; git
|
|||
;; Permission for unix socket
|
||||
;UNIX_SOCKET_PERMISSION = 666
|
||||
;;
|
||||
;; Local (DMZ) URL for Gitea workers (such as SSH update) accessing web service.
|
||||
;; In most cases you do not need to change the default value.
|
||||
;; Alter it only if your SSH server node is not the same as HTTP node.
|
||||
;; Do not set this variable if PROTOCOL is set to 'unix'.
|
||||
;; Local (DMZ) URL for Gitea workers (such as SSH update) accessing web service. In
|
||||
;; most cases you do not need to change the default value. Alter it only if
|
||||
;; your SSH server node is not the same as HTTP node. For different protocol, the default
|
||||
;; values are different. If `PROTOCOL` is `http+unix`, the default value is `http://unix/`.
|
||||
;; If `PROTOCOL` is `fcgi` or `fcgi+unix`, the default value is `%(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/`.
|
||||
;; If listen on `0.0.0.0`, the default value is `%(PROTOCOL)s://localhost:%(HTTP_PORT)s/`, Otherwise the default
|
||||
;; value is `%(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/`.
|
||||
;LOCAL_ROOT_URL = %(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/
|
||||
;;
|
||||
;; When making local connections pass the PROXY protocol header.
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}-rootless
|
||||
{{#if build.tags}}
|
||||
{{#unless (contains "-rc" build.tag)}}
|
||||
{{#unless (contains "-dev" build.tag)}}
|
||||
tags:
|
||||
{{#each build.tags}}
|
||||
- {{this}}-rootless
|
||||
{{/each}}
|
||||
- "latest-rootless"
|
||||
{{/unless}}
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
manifests:
|
||||
-
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
image: gitea/gitea:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}{{#if (hasPrefix "refs/heads/release/v" build.ref)}}{{trimPrefix "refs/heads/release/v" build.ref}}-{{/if}}nightly{{/if}}
|
||||
{{#if build.tags}}
|
||||
{{#unless (contains "-rc" build.tag)}}
|
||||
{{#unless (contains "-dev" build.tag)}}
|
||||
tags:
|
||||
{{#each build.tags}}
|
||||
- {{this}}
|
||||
{{/each}}
|
||||
- "latest"
|
||||
{{/unless}}
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
manifests:
|
||||
-
|
||||
|
|
|
@ -108,6 +108,14 @@ Admin operations:
|
|||
- `--all`, `-A`: Force a password change for all users
|
||||
- `--exclude username`, `-e username`: Exclude the given user. Can be set multiple times.
|
||||
- `--unset`: Revoke forced password change for the given users
|
||||
- `generate-access-token`:
|
||||
- Options:
|
||||
- `--username value`, `-u value`: Username. Required.
|
||||
- `--token-name value`, `-t value`: Token name. Required.
|
||||
- `--scopes value`: Comma-separated list of scopes. Scopes follow the format `[read|write]:<block>` or `all` where `<block>` is one of the available visual groups you can see when opening the API page showing the available routes (for example `repo`).
|
||||
- Examples:
|
||||
- `gitea admin user generate-access-token --username myname --token-name mytoken`
|
||||
- `gitea admin user generate-access-token --help`
|
||||
- `regenerate`
|
||||
- Options:
|
||||
- `hooks`: Regenerate Git Hooks for all repositories
|
||||
|
|
|
@ -314,8 +314,11 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||
- `LOCAL_ROOT_URL`: **%(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/**: Local
|
||||
(DMZ) URL for Gitea workers (such as SSH update) accessing web service. In
|
||||
most cases you do not need to change the default value. Alter it only if
|
||||
your SSH server node is not the same as HTTP node. Do not set this variable
|
||||
if `PROTOCOL` is set to `http+unix`.
|
||||
your SSH server node is not the same as HTTP node. For different protocol, the default
|
||||
values are different. If `PROTOCOL` is `http+unix`, the default value is `http://unix/`.
|
||||
If `PROTOCOL` is `fcgi` or `fcgi+unix`, the default value is `%(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/`.
|
||||
If listen on `0.0.0.0`, the default value is `%(PROTOCOL)s://localhost:%(HTTP_PORT)s/`, Otherwise the default
|
||||
value is `%(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/`.
|
||||
- `LOCAL_USE_PROXY_PROTOCOL`: **%(USE_PROXY_PROTOCOL)s**: When making local connections pass the PROXY protocol header.
|
||||
This should be set to false if the local connection will go through the proxy.
|
||||
- `PER_WRITE_TIMEOUT`: **30s**: Timeout for any write to the connection. (Set to -1 to
|
||||
|
|
2
go.mod
2
go.mod
|
@ -122,7 +122,7 @@ require (
|
|||
mvdan.cc/xurls/v2 v2.4.0
|
||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
|
||||
xorm.io/builder v0.3.12
|
||||
xorm.io/xorm v1.3.3-0.20230219231735-056cecc97e9e
|
||||
xorm.io/xorm v1.3.3-0.20230623150031-18f8e7a86c75
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
4
go.sum
4
go.sum
|
@ -1923,5 +1923,5 @@ strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:
|
|||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM=
|
||||
xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/xorm v1.3.3-0.20230219231735-056cecc97e9e h1:d5PY6mwuQK5/7T6VKfFswaKMzLmGTHkJ/ZS7+cUIAjk=
|
||||
xorm.io/xorm v1.3.3-0.20230219231735-056cecc97e9e/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw=
|
||||
xorm.io/xorm v1.3.3-0.20230623150031-18f8e7a86c75 h1:ReBAlO50dCIXCWF8Gbi0ZRa62AGAwCJNCPaUNUa7JSg=
|
||||
xorm.io/xorm v1.3.3-0.20230623150031-18f8e7a86c75/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw=
|
||||
|
|
15
main.go
15
main.go
|
@ -47,7 +47,9 @@ func init() {
|
|||
// ./gitea -h
|
||||
// ./gitea web help
|
||||
// ./gitea web -h (due to cli lib limitation, this won't call our cmdHelp, so no extra info)
|
||||
// ./gitea admin help auth
|
||||
// ./gitea admin
|
||||
// ./gitea admin help
|
||||
// ./gitea admin auth help
|
||||
// ./gitea -c /tmp/app.ini -h
|
||||
// ./gitea -c /tmp/app.ini help
|
||||
// ./gitea help -c /tmp/app.ini
|
||||
|
@ -156,11 +158,7 @@ func prepareSubcommands(command *cli.Command, defaultFlags []cli.Flag) {
|
|||
|
||||
// prepareWorkPathAndCustomConf wraps the Action to prepare the work path and custom config
|
||||
// It can't use "Before", because each level's sub-command's Before will be called one by one, so the "init" would be done multiple times
|
||||
func prepareWorkPathAndCustomConf(a any) func(ctx *cli.Context) error {
|
||||
if a == nil {
|
||||
return nil
|
||||
}
|
||||
action := a.(func(*cli.Context) error)
|
||||
func prepareWorkPathAndCustomConf(action any) func(ctx *cli.Context) error {
|
||||
return func(ctx *cli.Context) error {
|
||||
var args setting.ArgWorkPathAndCustomConf
|
||||
curCtx := ctx
|
||||
|
@ -177,10 +175,11 @@ func prepareWorkPathAndCustomConf(a any) func(ctx *cli.Context) error {
|
|||
curCtx = curCtx.Parent()
|
||||
}
|
||||
setting.InitWorkPathAndCommonConfig(os.Getenv, args)
|
||||
if ctx.Bool("help") {
|
||||
if ctx.Bool("help") || action == nil {
|
||||
// the default behavior of "urfave/cli": "nil action" means "show help"
|
||||
return cmdHelp.Action.(func(ctx *cli.Context) error)(ctx)
|
||||
}
|
||||
return action(ctx)
|
||||
return action.(func(*cli.Context) error)(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,12 +36,13 @@ type ActionRun struct {
|
|||
TriggerUser *user_model.User `xorm:"-"`
|
||||
Ref string
|
||||
CommitSHA string
|
||||
IsForkPullRequest bool // If this is triggered by a PR from a forked repository or an untrusted user, we need to check if it is approved and limit permissions when running the workflow.
|
||||
NeedApproval bool // may need approval if it's a fork pull request
|
||||
ApprovedBy int64 `xorm:"index"` // who approved
|
||||
Event webhook_module.HookEventType
|
||||
EventPayload string `xorm:"LONGTEXT"`
|
||||
Status Status `xorm:"index"`
|
||||
IsForkPullRequest bool // If this is triggered by a PR from a forked repository or an untrusted user, we need to check if it is approved and limit permissions when running the workflow.
|
||||
NeedApproval bool // may need approval if it's a fork pull request
|
||||
ApprovedBy int64 `xorm:"index"` // who approved
|
||||
Event webhook_module.HookEventType // the webhook event that causes the workflow to run
|
||||
EventPayload string `xorm:"LONGTEXT"`
|
||||
TriggerEvent string // the trigger event defined in the `on` configuration of the triggered workflow
|
||||
Status Status `xorm:"index"`
|
||||
Started timeutil.TimeStamp
|
||||
Stopped timeutil.TimeStamp
|
||||
Created timeutil.TimeStamp `xorm:"created"`
|
||||
|
|
|
@ -123,7 +123,10 @@ func newXORMEngine() (*xorm.Engine, error) {
|
|||
|
||||
// SyncAllTables sync the schemas of all tables, is required by unit test code
|
||||
func SyncAllTables() error {
|
||||
return x.StoreEngine("InnoDB").Sync2(tables...)
|
||||
_, err := x.StoreEngine("InnoDB").SyncWithOptions(xorm.SyncOptions{
|
||||
WarnIfDatabaseColumnMissed: true,
|
||||
}, tables...)
|
||||
return err
|
||||
}
|
||||
|
||||
// InitEngine initializes the xorm.Engine and sets it as db.DefaultContext
|
||||
|
|
|
@ -229,39 +229,41 @@ func (issues IssueList) loadMilestones(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (issues IssueList) getProjectIDs() []int64 {
|
||||
ids := make(container.Set[int64], len(issues))
|
||||
for _, issue := range issues {
|
||||
ids.Add(issue.ProjectID())
|
||||
}
|
||||
return ids.Values()
|
||||
}
|
||||
func (issues IssueList) LoadProjects(ctx context.Context) error {
|
||||
issueIDs := issues.getIssueIDs()
|
||||
projectMaps := make(map[int64]*project_model.Project, len(issues))
|
||||
left := len(issueIDs)
|
||||
|
||||
func (issues IssueList) loadProjects(ctx context.Context) error {
|
||||
projectIDs := issues.getProjectIDs()
|
||||
if len(projectIDs) == 0 {
|
||||
return nil
|
||||
type projectWithIssueID struct {
|
||||
*project_model.Project `xorm:"extends"`
|
||||
IssueID int64
|
||||
}
|
||||
|
||||
projectMaps := make(map[int64]*project_model.Project, len(projectIDs))
|
||||
left := len(projectIDs)
|
||||
for left > 0 {
|
||||
limit := db.DefaultMaxInSize
|
||||
if left < limit {
|
||||
limit = left
|
||||
}
|
||||
|
||||
projects := make([]*projectWithIssueID, 0, limit)
|
||||
err := db.GetEngine(ctx).
|
||||
In("id", projectIDs[:limit]).
|
||||
Find(&projectMaps)
|
||||
Table("project").
|
||||
Select("project.*, project_issue.issue_id").
|
||||
Join("INNER", "project_issue", "project.id = project_issue.project_id").
|
||||
In("project_issue.issue_id", issueIDs[:limit]).
|
||||
Find(&projects)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, project := range projects {
|
||||
projectMaps[project.IssueID] = project.Project
|
||||
}
|
||||
left -= limit
|
||||
projectIDs = projectIDs[limit:]
|
||||
issueIDs = issueIDs[limit:]
|
||||
}
|
||||
|
||||
for _, issue := range issues {
|
||||
issue.Project = projectMaps[issue.ProjectID()]
|
||||
issue.Project = projectMaps[issue.ID]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -541,7 +543,7 @@ func (issues IssueList) loadAttributes(ctx context.Context) error {
|
|||
return fmt.Errorf("issue.loadAttributes: loadMilestones: %w", err)
|
||||
}
|
||||
|
||||
if err := issues.loadProjects(ctx); err != nil {
|
||||
if err := issues.LoadProjects(ctx); err != nil {
|
||||
return fmt.Errorf("issue.loadAttributes: loadProjects: %w", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -66,8 +66,12 @@ func TestIssueList_LoadAttributes(t *testing.T) {
|
|||
}
|
||||
if issue.ID == int64(1) {
|
||||
assert.Equal(t, int64(400), issue.TotalTrackedTime)
|
||||
assert.NotNil(t, issue.Project)
|
||||
} else if issue.ID == int64(2) {
|
||||
assert.Equal(t, int64(3682), issue.TotalTrackedTime)
|
||||
assert.Nil(t, issue.Project)
|
||||
} else {
|
||||
assert.Nil(t, issue.Project)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,11 +27,6 @@ func (issue *Issue) LoadProject(ctx context.Context) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
// ProjectID return project id if issue was assigned to one
|
||||
func (issue *Issue) ProjectID() int64 {
|
||||
return issue.projectID(db.DefaultContext)
|
||||
}
|
||||
|
||||
func (issue *Issue) projectID(ctx context.Context) int64 {
|
||||
var ip project_model.ProjectIssue
|
||||
has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip)
|
||||
|
|
|
@ -503,11 +503,11 @@ var migrations = []Migration{
|
|||
|
||||
// v260 -> v261
|
||||
NewMigration("Drop custom_labels column of action_runner table", v1_21.DropCustomLabelsColumnOfActionRunner),
|
||||
|
||||
// v261 -> v262
|
||||
NewMigration("Add variable table", v1_21.CreateVariableTable),
|
||||
|
||||
// v262 -> v263
|
||||
NewMigration("Add TriggerEvent to action_run table", v1_21.AddTriggerEventToActionRun),
|
||||
// v263 -> v264
|
||||
NewMigration("Add TimeEstimate to issue table", v1_21.AddTimeEstimateColumnToIssueTable),
|
||||
}
|
||||
|
||||
|
|
|
@ -7,10 +7,10 @@ import (
|
|||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func AddTimeEstimateColumnToIssueTable(x *xorm.Engine) error {
|
||||
type Issue struct {
|
||||
TimeEstimate int64 `xorm:"NOT NULL DEFAULT 0"`
|
||||
func AddTriggerEventToActionRun(x *xorm.Engine) error {
|
||||
type ActionRun struct {
|
||||
TriggerEvent string
|
||||
}
|
||||
|
||||
return x.Sync(new(Issue))
|
||||
return x.Sync(new(ActionRun))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_21 //nolint
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func AddTimeEstimateColumnToIssueTable(x *xorm.Engine) error {
|
||||
type Issue struct {
|
||||
TimeEstimate int64 `xorm:"NOT NULL DEFAULT 0"`
|
||||
}
|
||||
|
||||
return x.Sync(new(Issue))
|
||||
}
|
|
@ -8,33 +8,33 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
githubEventPullRequest = "pull_request"
|
||||
githubEventPullRequestTarget = "pull_request_target"
|
||||
githubEventPullRequestReviewComment = "pull_request_review_comment"
|
||||
githubEventPullRequestReview = "pull_request_review"
|
||||
githubEventRegistryPackage = "registry_package"
|
||||
githubEventCreate = "create"
|
||||
githubEventDelete = "delete"
|
||||
githubEventFork = "fork"
|
||||
githubEventPush = "push"
|
||||
githubEventIssues = "issues"
|
||||
githubEventIssueComment = "issue_comment"
|
||||
githubEventRelease = "release"
|
||||
githubEventPullRequestComment = "pull_request_comment"
|
||||
githubEventGollum = "gollum"
|
||||
GithubEventPullRequest = "pull_request"
|
||||
GithubEventPullRequestTarget = "pull_request_target"
|
||||
GithubEventPullRequestReviewComment = "pull_request_review_comment"
|
||||
GithubEventPullRequestReview = "pull_request_review"
|
||||
GithubEventRegistryPackage = "registry_package"
|
||||
GithubEventCreate = "create"
|
||||
GithubEventDelete = "delete"
|
||||
GithubEventFork = "fork"
|
||||
GithubEventPush = "push"
|
||||
GithubEventIssues = "issues"
|
||||
GithubEventIssueComment = "issue_comment"
|
||||
GithubEventRelease = "release"
|
||||
GithubEventPullRequestComment = "pull_request_comment"
|
||||
GithubEventGollum = "gollum"
|
||||
)
|
||||
|
||||
// canGithubEventMatch check if the input Github event can match any Gitea event.
|
||||
func canGithubEventMatch(eventName string, triggedEvent webhook_module.HookEventType) bool {
|
||||
switch eventName {
|
||||
case githubEventRegistryPackage:
|
||||
case GithubEventRegistryPackage:
|
||||
return triggedEvent == webhook_module.HookEventPackage
|
||||
|
||||
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#gollum
|
||||
case githubEventGollum:
|
||||
case GithubEventGollum:
|
||||
return triggedEvent == webhook_module.HookEventWiki
|
||||
|
||||
case githubEventIssues:
|
||||
case GithubEventIssues:
|
||||
switch triggedEvent {
|
||||
case webhook_module.HookEventIssues,
|
||||
webhook_module.HookEventIssueAssign,
|
||||
|
@ -46,7 +46,7 @@ func canGithubEventMatch(eventName string, triggedEvent webhook_module.HookEvent
|
|||
return false
|
||||
}
|
||||
|
||||
case githubEventPullRequest, githubEventPullRequestTarget:
|
||||
case GithubEventPullRequest, GithubEventPullRequestTarget:
|
||||
switch triggedEvent {
|
||||
case webhook_module.HookEventPullRequest,
|
||||
webhook_module.HookEventPullRequestSync,
|
||||
|
@ -58,7 +58,7 @@ func canGithubEventMatch(eventName string, triggedEvent webhook_module.HookEvent
|
|||
return false
|
||||
}
|
||||
|
||||
case githubEventPullRequestReview:
|
||||
case GithubEventPullRequestReview:
|
||||
switch triggedEvent {
|
||||
case webhook_module.HookEventPullRequestReviewApproved,
|
||||
webhook_module.HookEventPullRequestReviewComment,
|
||||
|
|
|
@ -21,85 +21,85 @@ func TestCanGithubEventMatch(t *testing.T) {
|
|||
// registry_package event
|
||||
{
|
||||
"registry_package matches",
|
||||
githubEventRegistryPackage,
|
||||
GithubEventRegistryPackage,
|
||||
webhook_module.HookEventPackage,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"registry_package cannot match",
|
||||
githubEventRegistryPackage,
|
||||
GithubEventRegistryPackage,
|
||||
webhook_module.HookEventPush,
|
||||
false,
|
||||
},
|
||||
// issues event
|
||||
{
|
||||
"issue matches",
|
||||
githubEventIssues,
|
||||
GithubEventIssues,
|
||||
webhook_module.HookEventIssueLabel,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"issue cannot match",
|
||||
githubEventIssues,
|
||||
GithubEventIssues,
|
||||
webhook_module.HookEventIssueComment,
|
||||
false,
|
||||
},
|
||||
// issue_comment event
|
||||
{
|
||||
"issue_comment matches",
|
||||
githubEventIssueComment,
|
||||
GithubEventIssueComment,
|
||||
webhook_module.HookEventIssueComment,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"issue_comment cannot match",
|
||||
githubEventIssueComment,
|
||||
GithubEventIssueComment,
|
||||
webhook_module.HookEventIssues,
|
||||
false,
|
||||
},
|
||||
// pull_request event
|
||||
{
|
||||
"pull_request matches",
|
||||
githubEventPullRequest,
|
||||
GithubEventPullRequest,
|
||||
webhook_module.HookEventPullRequestSync,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pull_request cannot match",
|
||||
githubEventPullRequest,
|
||||
GithubEventPullRequest,
|
||||
webhook_module.HookEventPullRequestComment,
|
||||
false,
|
||||
},
|
||||
// pull_request_target event
|
||||
{
|
||||
"pull_request_target matches",
|
||||
githubEventPullRequest,
|
||||
GithubEventPullRequest,
|
||||
webhook_module.HookEventPullRequest,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pull_request_target cannot match",
|
||||
githubEventPullRequest,
|
||||
GithubEventPullRequest,
|
||||
webhook_module.HookEventPullRequestComment,
|
||||
false,
|
||||
},
|
||||
// pull_request_review event
|
||||
{
|
||||
"pull_request_review matches",
|
||||
githubEventPullRequestReview,
|
||||
GithubEventPullRequestReview,
|
||||
webhook_module.HookEventPullRequestReviewComment,
|
||||
true,
|
||||
},
|
||||
{
|
||||
"pull_request_review cannot match",
|
||||
githubEventPullRequestReview,
|
||||
GithubEventPullRequestReview,
|
||||
webhook_module.HookEventPullRequestComment,
|
||||
false,
|
||||
},
|
||||
// other events
|
||||
{
|
||||
"create event",
|
||||
githubEventCreate,
|
||||
GithubEventCreate,
|
||||
webhook_module.HookEventCreate,
|
||||
true,
|
||||
},
|
||||
|
|
|
@ -20,6 +20,14 @@ import (
|
|||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type DetectedWorkflow struct {
|
||||
EntryName string
|
||||
TriggerEvent string
|
||||
Commit *git.Commit
|
||||
Ref string
|
||||
Content []byte
|
||||
}
|
||||
|
||||
func init() {
|
||||
model.OnDecodeNodeError = func(node yaml.Node, out interface{}, err error) {
|
||||
// Log the error instead of panic or fatal.
|
||||
|
@ -89,13 +97,13 @@ func GetEventsFromContent(content []byte) ([]*jobparser.Event, error) {
|
|||
return events, nil
|
||||
}
|
||||
|
||||
func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader) (map[string][]byte, error) {
|
||||
func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventType, payload api.Payloader) ([]*DetectedWorkflow, error) {
|
||||
entries, err := ListWorkflows(commit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
workflows := make(map[string][]byte, len(entries))
|
||||
workflows := make([]*DetectedWorkflow, 0, len(entries))
|
||||
for _, entry := range entries {
|
||||
content, err := GetContentFromEntry(entry)
|
||||
if err != nil {
|
||||
|
@ -109,7 +117,13 @@ func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventTy
|
|||
for _, evt := range events {
|
||||
log.Trace("detect workflow %q for event %#v matching %q", entry.Name(), evt, triggedEvent)
|
||||
if detectMatched(commit, triggedEvent, payload, evt) {
|
||||
workflows[entry.Name()] = content
|
||||
dwf := &DetectedWorkflow{
|
||||
EntryName: entry.Name(),
|
||||
TriggerEvent: evt.Name,
|
||||
Commit: commit,
|
||||
Content: content,
|
||||
}
|
||||
workflows = append(workflows, dwf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,77 +23,77 @@ func TestDetectMatched(t *testing.T) {
|
|||
expected bool
|
||||
}{
|
||||
{
|
||||
desc: "HookEventCreate(create) matches githubEventCreate(create)",
|
||||
desc: "HookEventCreate(create) matches GithubEventCreate(create)",
|
||||
triggedEvent: webhook_module.HookEventCreate,
|
||||
payload: nil,
|
||||
yamlOn: "on: create",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
desc: "HookEventIssues(issues) `opened` action matches githubEventIssues(issues)",
|
||||
desc: "HookEventIssues(issues) `opened` action matches GithubEventIssues(issues)",
|
||||
triggedEvent: webhook_module.HookEventIssues,
|
||||
payload: &api.IssuePayload{Action: api.HookIssueOpened},
|
||||
yamlOn: "on: issues",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
desc: "HookEventIssues(issues) `milestoned` action matches githubEventIssues(issues)",
|
||||
desc: "HookEventIssues(issues) `milestoned` action matches GithubEventIssues(issues)",
|
||||
triggedEvent: webhook_module.HookEventIssues,
|
||||
payload: &api.IssuePayload{Action: api.HookIssueMilestoned},
|
||||
yamlOn: "on: issues",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
desc: "HookEventPullRequestSync(pull_request_sync) matches githubEventPullRequest(pull_request)",
|
||||
desc: "HookEventPullRequestSync(pull_request_sync) matches GithubEventPullRequest(pull_request)",
|
||||
triggedEvent: webhook_module.HookEventPullRequestSync,
|
||||
payload: &api.PullRequestPayload{Action: api.HookIssueSynchronized},
|
||||
yamlOn: "on: pull_request",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
desc: "HookEventPullRequest(pull_request) `label_updated` action doesn't match githubEventPullRequest(pull_request) with no activity type",
|
||||
desc: "HookEventPullRequest(pull_request) `label_updated` action doesn't match GithubEventPullRequest(pull_request) with no activity type",
|
||||
triggedEvent: webhook_module.HookEventPullRequest,
|
||||
payload: &api.PullRequestPayload{Action: api.HookIssueLabelUpdated},
|
||||
yamlOn: "on: pull_request",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "HookEventPullRequest(pull_request) `label_updated` action matches githubEventPullRequest(pull_request) with `label` activity type",
|
||||
desc: "HookEventPullRequest(pull_request) `label_updated` action matches GithubEventPullRequest(pull_request) with `label` activity type",
|
||||
triggedEvent: webhook_module.HookEventPullRequest,
|
||||
payload: &api.PullRequestPayload{Action: api.HookIssueLabelUpdated},
|
||||
yamlOn: "on:\n pull_request:\n types: [labeled]",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
desc: "HookEventPullRequestReviewComment(pull_request_review_comment) matches githubEventPullRequestReviewComment(pull_request_review_comment)",
|
||||
desc: "HookEventPullRequestReviewComment(pull_request_review_comment) matches GithubEventPullRequestReviewComment(pull_request_review_comment)",
|
||||
triggedEvent: webhook_module.HookEventPullRequestReviewComment,
|
||||
payload: &api.PullRequestPayload{Action: api.HookIssueReviewed},
|
||||
yamlOn: "on:\n pull_request_review_comment:\n types: [created]",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
desc: "HookEventPullRequestReviewRejected(pull_request_review_rejected) doesn't match githubEventPullRequestReview(pull_request_review) with `dismissed` activity type (we don't support `dismissed` at present)",
|
||||
desc: "HookEventPullRequestReviewRejected(pull_request_review_rejected) doesn't match GithubEventPullRequestReview(pull_request_review) with `dismissed` activity type (we don't support `dismissed` at present)",
|
||||
triggedEvent: webhook_module.HookEventPullRequestReviewRejected,
|
||||
payload: &api.PullRequestPayload{Action: api.HookIssueReviewed},
|
||||
yamlOn: "on:\n pull_request_review:\n types: [dismissed]",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "HookEventRelease(release) `published` action matches githubEventRelease(release) with `published` activity type",
|
||||
desc: "HookEventRelease(release) `published` action matches GithubEventRelease(release) with `published` activity type",
|
||||
triggedEvent: webhook_module.HookEventRelease,
|
||||
payload: &api.ReleasePayload{Action: api.HookReleasePublished},
|
||||
yamlOn: "on:\n release:\n types: [published]",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
desc: "HookEventPackage(package) `created` action doesn't match githubEventRegistryPackage(registry_package) with `updated` activity type",
|
||||
desc: "HookEventPackage(package) `created` action doesn't match GithubEventRegistryPackage(registry_package) with `updated` activity type",
|
||||
triggedEvent: webhook_module.HookEventPackage,
|
||||
payload: &api.PackagePayload{Action: api.HookPackageCreated},
|
||||
yamlOn: "on:\n registry_package:\n types: [updated]",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "HookEventWiki(wiki) matches githubEventGollum(gollum)",
|
||||
desc: "HookEventWiki(wiki) matches GithubEventGollum(gollum)",
|
||||
triggedEvent: webhook_module.HookEventWiki,
|
||||
payload: nil,
|
||||
yamlOn: "on: gollum",
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
// Notifier defines an interface to notify receiver
|
||||
type Notifier interface {
|
||||
Run()
|
||||
NotifyAdoptRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository)
|
||||
NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository)
|
||||
NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository)
|
||||
NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository)
|
||||
|
|
|
@ -145,6 +145,10 @@ func (*NullNotifier) NotifyIssueChangeLabels(ctx context.Context, doer *user_mod
|
|||
func (*NullNotifier) NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) {
|
||||
}
|
||||
|
||||
// NotifyAdoptRepository places a place holder function
|
||||
func (*NullNotifier) NotifyAdoptRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) {
|
||||
}
|
||||
|
||||
// NotifyDeleteRepository places a place holder function
|
||||
func (*NullNotifier) NotifyDeleteRepository(ctx context.Context, doer *user_model.User, repo *repo_model.Repository) {
|
||||
}
|
||||
|
|
|
@ -29,6 +29,10 @@ func NewNotifier() base.Notifier {
|
|||
return &indexerNotifier{}
|
||||
}
|
||||
|
||||
func (r *indexerNotifier) NotifyAdoptRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) {
|
||||
r.NotifyMigrateRepository(ctx, doer, u, repo)
|
||||
}
|
||||
|
||||
func (r *indexerNotifier) NotifyCreateIssueComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository,
|
||||
issue *issues_model.Issue, comment *issues_model.Comment, mentions []*user_model.User,
|
||||
) {
|
||||
|
|
|
@ -274,6 +274,13 @@ func NotifyCreateRepository(ctx context.Context, doer, u *user_model.User, repo
|
|||
}
|
||||
}
|
||||
|
||||
// NotifyAdoptRepository notifies the adoption of a repository to notifiers
|
||||
func NotifyAdoptRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) {
|
||||
for _, notifier := range notifiers {
|
||||
notifier.NotifyAdoptRepository(ctx, doer, u, repo)
|
||||
}
|
||||
}
|
||||
|
||||
// NotifyMigrateRepository notifies create repository to notifiers
|
||||
func NotifyMigrateRepository(ctx context.Context, doer, u *user_model.User, repo *repo_model.Repository) {
|
||||
for _, notifier := range notifiers {
|
||||
|
|
|
@ -89,6 +89,12 @@ func (s *stringWithDefault) Set(v string) {
|
|||
|
||||
// InitWorkPathAndCommonConfig will set AppWorkPath, CustomPath and CustomConf, init default config provider by CustomConf and load common settings,
|
||||
func InitWorkPathAndCommonConfig(getEnvFn func(name string) string, args ArgWorkPathAndCustomConf) {
|
||||
InitWorkPathAndCfgProvider(getEnvFn, args)
|
||||
LoadCommonSettings()
|
||||
}
|
||||
|
||||
// InitWorkPathAndCfgProvider will set AppWorkPath, CustomPath and CustomConf, init default config provider by CustomConf
|
||||
func InitWorkPathAndCfgProvider(getEnvFn func(name string) string, args ArgWorkPathAndCustomConf) {
|
||||
tryAbsPath := func(paths ...string) string {
|
||||
s := paths[len(paths)-1]
|
||||
for i := len(paths) - 2; i >= 0; i-- {
|
||||
|
@ -186,6 +192,4 @@ func InitWorkPathAndCommonConfig(getEnvFn func(name string) string, args ArgWork
|
|||
AppWorkPath = tmpWorkPath.Value
|
||||
CustomPath = tmpCustomPath.Value
|
||||
CustomConf = tmpCustomConf.Value
|
||||
|
||||
LoadCommonSettings()
|
||||
}
|
||||
|
|
|
@ -696,6 +696,7 @@ requires_activation = Requires activation
|
|||
primary_email = Make Primary
|
||||
activate_email = Send Activation
|
||||
activations_pending = Activations Pending
|
||||
can_not_add_email_activations_pending = There is a pending activation, try again in a few minutes if you want to add a new email.
|
||||
delete_email = Remove
|
||||
email_deletion = Remove Email Address
|
||||
email_deletion_desc = The email address and related information will be removed from your account. Git commits by this email address will remain unchanged. Continue?
|
||||
|
|
|
@ -120,11 +120,14 @@ unpin=Открепить
|
|||
|
||||
artifacts=Артефакты
|
||||
|
||||
concept_system_global=Глобально
|
||||
concept_user_individual=Индивидуально
|
||||
concept_code_repository=Репозиторий
|
||||
concept_user_organization=Организация
|
||||
|
||||
show_timestamps=Отображать время
|
||||
show_log_seconds=Показывать секунды
|
||||
show_full_screen=Показать во весь экран
|
||||
|
||||
[aria]
|
||||
navbar=Панель навигации
|
||||
|
@ -133,6 +136,8 @@ footer.software=О программе
|
|||
footer.links=Ссылки
|
||||
|
||||
[heatmap]
|
||||
number_of_contributions_in_the_last_12_months=Принимал(а) участие %s раз за последние 12 месяцев
|
||||
no_contributions=Не принимал(а) участия
|
||||
less=Меньше
|
||||
more=Больше
|
||||
|
||||
|
@ -572,6 +577,7 @@ target_branch_not_exist=Целевая ветка не существует.
|
|||
|
||||
[user]
|
||||
change_avatar=Изменить свой аватар…
|
||||
joined_on=Присоединил(ся/ась) %s
|
||||
repositories=Репозитории
|
||||
activity=Активность
|
||||
followers=Подписчики
|
||||
|
@ -767,6 +773,8 @@ ssh_principal_deletion_desc=Удаление принципала сертифи
|
|||
ssh_key_deletion_success=Ключ SSH удален.
|
||||
gpg_key_deletion_success=Ключ GPG удалён.
|
||||
ssh_principal_deletion_success=Принципал удалён.
|
||||
added_on=Добавлено %s
|
||||
valid_until_date=Действительно до %s
|
||||
valid_forever=Действителен навсегда
|
||||
last_used=Последний раз использовался
|
||||
no_activity=Еще не применялся
|
||||
|
@ -798,7 +806,13 @@ access_token_deletion_cancel_action=Отменить
|
|||
access_token_deletion_confirm_action=Удалить
|
||||
access_token_deletion_desc=Удаление токена отзовёт доступ к вашей учетной записи у приложений, использующих его. Это действие не может быть отменено. Продолжить?
|
||||
delete_token_success=Токен удалён. Приложения, использующие его, больше не имеют доступа к вашему аккаунту.
|
||||
repo_and_org_access=Доступ к репозиторию и организации
|
||||
permissions_public_only=Только публичные
|
||||
permissions_access_all=Все (публичные, приватные и ограниченные)
|
||||
select_permissions=Выбрать разрешения
|
||||
scoped_token_desc=Выбранные полномочия токена ограничивают аутентификацию только соответствующими маршрутами <a %s>API</a>. Читайте <a %s>документацию</a> для получения дополнительной информации.
|
||||
at_least_one_permission=Необходимо выбрать хотя бы одно разрешение для создания токена
|
||||
permissions_list=Разрешения:
|
||||
|
||||
manage_oauth2_applications=Управление приложениями OAuth2
|
||||
edit_oauth2_application=Изменить приложение OAuth2
|
||||
|
@ -957,6 +971,7 @@ mirror_password_blank_placeholder=(Отменено)
|
|||
mirror_password_help=Смените имя пользователя для удаления пароля.
|
||||
watchers=Наблюдатели
|
||||
stargazers=Звездочеты
|
||||
stars_remove_warning=Данное действие удалит все звёзды из этого репозитория.
|
||||
forks=Форки
|
||||
reactions_more=и ещё %d
|
||||
unit_disabled=Администратор сайта отключил этот раздел репозитория.
|
||||
|
@ -1000,6 +1015,7 @@ template.one_item=Необходимо выбрать хотя бы один э
|
|||
template.invalid=Необходимо выбрать хранилище шаблонов
|
||||
|
||||
archive.title=Это репозиторий в архиве. Вы можете его клонировать или просматривать файлы, но не вносить изменения или открывать задачи/запросы на слияние.
|
||||
archive.title_date=Этот репозиторий архивирован %s. Вы можете смотреть файлы или клонировать его, но не можете вносить изменения, открывать задачи или делать запросы на слияние.
|
||||
archive.issue.nocomment=Этот репозиторий в архиве. Вы не можете комментировать задачи.
|
||||
archive.pull.nocomment=Это репозиторий в архиве. Вы не можете комментировать запросы на слияние.
|
||||
|
||||
|
@ -1683,7 +1699,7 @@ pulls.no_merge_access=У вас нет права для слияния данн
|
|||
pulls.merge_pull_request=Создать коммит на слияние
|
||||
pulls.rebase_merge_pull_request=Выполнить Rebase, а затем fast-forward слияние
|
||||
pulls.rebase_merge_commit_pull_request=Выполнить rebase, а затем создать коммит слияния
|
||||
pulls.squash_merge_pull_request=Создать объединенный (squash) коммит
|
||||
pulls.squash_merge_pull_request=Создать объединённый коммит
|
||||
pulls.merge_manually=Слито вручную
|
||||
pulls.merge_commit_id=ID коммита слияния
|
||||
pulls.require_signed_wont_sign=Данная ветка ожидает подписанные коммиты, однако слияние не будет подписано
|
||||
|
@ -1695,6 +1711,7 @@ pulls.rebase_conflict=Слияние не удалось: Произошел к
|
|||
pulls.rebase_conflict_summary=Сообщение об ошибке
|
||||
pulls.unrelated_histories=Слияние не удалось: У источника и цели слияния нет общей истории. Совет: попробуйте другую стратегию
|
||||
pulls.merge_out_of_date=Ошибка слияния: при создании слияния база данных была обновлена. Подсказка: попробуйте ещё раз.
|
||||
pulls.head_out_of_date=Ошибка слияния: во время слияния головной коммит был обновлён. Попробуйте ещё раз.
|
||||
pulls.push_rejected=Слияние не удалось: отправка была отклонена. Проверьте Git-хуки для этого репозитория.
|
||||
pulls.push_rejected_summary=Полная ошибка отклонения
|
||||
pulls.push_rejected_no_message=Слияние не удалось: отправка была отклонена, но сервер не указал причину.<br>Проверьте Git-хуки для этого репозитория
|
||||
|
@ -1899,6 +1916,10 @@ settings.githooks=Git-хуки
|
|||
settings.basic_settings=Основные параметры
|
||||
settings.mirror_settings=Настройки зеркалирования
|
||||
settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=В настоящее время это можно сделать только в меню «Новая миграция». Для получения дополнительной информации, пожалуйста, ознакомьтесь:
|
||||
settings.mirror_settings.docs.no_new_mirrors=Ваш репозиторий зеркалирует изменения в другой репозиторий или из него. Пожалуйста, имейте в виду, что в данный момент невозможно создавать новые зеркала.
|
||||
settings.mirror_settings.docs.can_still_use=Хотя вы не можете изменять существующие зеркала или создавать новые, вы можете по-прежнему использовать существующее зеркало.
|
||||
settings.mirror_settings.docs.pull_mirror_instructions=Чтобы настроить pull-зеркало, пожалуйста, ознакомьтесь:
|
||||
settings.mirror_settings.docs.doc_link_title=Как зеркалировать репозитории?
|
||||
settings.mirror_settings.docs.pulling_remote_title=Получение из удалённого репозитория
|
||||
settings.mirror_settings.mirrored_repository=Синхронизированное хранилище
|
||||
settings.mirror_settings.direction=Направление
|
||||
|
@ -2012,6 +2033,7 @@ settings.delete_notices_2=- Эта операция навсегда удали
|
|||
settings.delete_notices_fork_1=- Все форки станут независимыми репозиториями после удаления.
|
||||
settings.deletion_success=Репозиторий удалён.
|
||||
settings.update_settings_success=Настройки репозитория обновлены.
|
||||
settings.update_settings_no_unit=Должно быть разрешено хоть какое-то взаимодействие с репозиторием.
|
||||
settings.confirm_delete=Удалить репозиторий
|
||||
settings.add_collaborator=Добавить соавтора
|
||||
settings.add_collaborator_success=Соавтор добавлен.
|
||||
|
@ -2111,6 +2133,7 @@ settings.event_pull_request_sync=Синхронизация запроса на
|
|||
settings.event_pull_request_sync_desc=Запрос на слияние синхронизирован.
|
||||
settings.event_pull_request_review_request=Запрошена рецензия для запроса на слияние
|
||||
settings.event_pull_request_review_request_desc=Создан или удалён запрос на рецензию для запроса на слияние.
|
||||
settings.event_pull_request_approvals=Утверждения запросов на слияние
|
||||
settings.event_package=Пакеты
|
||||
settings.event_package_desc=Пакет создан или удален в репозитории.
|
||||
settings.branch_filter=Фильтр веток
|
||||
|
@ -2185,8 +2208,11 @@ settings.protect_merge_whitelist_committers_desc=Разрешить приним
|
|||
settings.protect_merge_whitelist_users=Пользователи с правом на слияние:
|
||||
settings.protect_merge_whitelist_teams=Команды, члены которых обладают правом на слияние:
|
||||
settings.protect_check_status_contexts=Включить проверку статуса
|
||||
settings.protect_status_check_patterns=Шаблоны проверки состояния:
|
||||
settings.protect_check_status_contexts_desc=Требуется пройти проверку состояния перед слиянием. Выберите, какие проверки состояния должны быть пройдены, прежде чем ветви можно будет объединить в ветвь, соответствующую этому правилу. Если этот параметр включен, коммиты сначала должны быть перемещены в другую ветвь, а затем объединены или перемещены непосредственно в ветвь, соответствующую этому правилу, после прохождения проверки состояния. Если контексты не выбраны, то последняя фиксация должна быть успешной независимо от контекста.
|
||||
settings.protect_check_status_contexts_list=Проверки состояния за последнюю неделю для этого репозитория
|
||||
settings.protect_invalid_status_check_pattern=Неверный шаблон проверки состояния: «%s».
|
||||
settings.protect_no_valid_status_check_patterns=Нет допустимых шаблонов проверки состояния.
|
||||
settings.protect_required_approvals=Необходимые одобрения:
|
||||
settings.protect_required_approvals_desc=Разрешить принятие запроса на слияние только с достаточным количеством положительных отзывов.
|
||||
settings.protect_approvals_whitelist_enabled=Ограничить утверждения белым списком пользователей или команд
|
||||
|
@ -2198,6 +2224,7 @@ settings.dismiss_stale_approvals_desc=Когда новые коммиты, из
|
|||
settings.require_signed_commits=Требовать подписанные коммиты
|
||||
settings.require_signed_commits_desc=Отклонить отправку изменений в эту ветку, если они не подписаны или не проверяемы.
|
||||
settings.protect_branch_name_pattern=Шаблон имени для защищённых веток
|
||||
settings.protect_patterns=Шаблоны
|
||||
settings.protect_protected_file_patterns=Шаблоны защищённых файлов (разделённые точкой с запятой ';'):
|
||||
settings.protect_protected_file_patterns_desc=Защищенные файлы нельзя изменить напрямую, даже если пользователь имеет право добавлять, редактировать или удалять файлы в этой ветке. Можно указать несколько шаблонов, разделяя их точкой с запятой (';'). О синтаксисе шаблонов читайте в документации <a href='https://godoc.org/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a>. Примеры: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
|
||||
settings.protect_unprotected_file_patterns=Шаблоны незащищённых файлов (разделённые точкой с запятой ';'):
|
||||
|
@ -2412,10 +2439,13 @@ branch.protected_deletion_failed=Ветка «%s» защищена. Её нел
|
|||
branch.default_deletion_failed=Ветка «%s» является веткой по умолчанию. Её нельзя удалить.
|
||||
branch.restore=Восстановить ветку «%s»
|
||||
branch.download=Скачать ветку «%s»
|
||||
branch.rename=Переименовать ветку «%s»
|
||||
branch.included_desc=Эта ветка является частью ветки по умолчанию
|
||||
branch.included=Включено
|
||||
branch.create_new_branch=Создать ветку из ветви:
|
||||
branch.confirm_create_branch=Создать ветку
|
||||
branch.warning_rename_default_branch=Вы переименовываете ветку по умолчанию.
|
||||
branch.rename_branch_to=Переименовать ветку «%s» в:
|
||||
branch.confirm_rename_branch=Переименовать ветку
|
||||
branch.create_branch_operation=Создать ветку
|
||||
branch.new_branch=Создать новую ветку
|
||||
|
@ -2746,6 +2776,7 @@ repos.size=Размер
|
|||
|
||||
packages.package_manage_panel=Управление пакетами
|
||||
packages.total_size=Общий размер: %s
|
||||
packages.unreferenced_size=Размер по ссылке: %s
|
||||
packages.owner=Владелец
|
||||
packages.creator=Автор
|
||||
packages.name=Наименование
|
||||
|
@ -3012,8 +3043,10 @@ config.git_pull_timeout=Лимит времени получения измен
|
|||
config.git_gc_timeout=Лимит времени сборки мусора
|
||||
|
||||
config.log_config=Конфигурация журнала
|
||||
config.logger_name_fmt=Журнал: %s
|
||||
config.disabled_logger=Отключен
|
||||
config.access_log_mode=Режим доступа к журналу
|
||||
config.access_log_template=Шаблон журнала доступа
|
||||
config.xorm_log_sql=Лог SQL
|
||||
|
||||
config.get_setting_failed=Получить параметр %s не удалось
|
||||
|
@ -3030,6 +3063,7 @@ monitor.execute_times=Количество выполнений
|
|||
monitor.process=Запущенные процессы
|
||||
monitor.stacktrace=Трассировки стека
|
||||
monitor.processes_count=%d процессов
|
||||
monitor.download_diagnosis_report=Скачать диагностический отчёт
|
||||
monitor.desc=Описание
|
||||
monitor.start=Время начала
|
||||
monitor.execute_time=Время выполнения
|
||||
|
@ -3050,9 +3084,10 @@ monitor.queue.numberinqueue=Позиция в очереди
|
|||
monitor.queue.review=Просмотр конфигурации
|
||||
monitor.queue.review_add=Просмотреть/добавить рабочих
|
||||
monitor.queue.settings.title=Настройки пула
|
||||
monitor.queue.settings.desc=Пулы увеличиваются динамически в ответ на блокировку очередей своих рабочих.
|
||||
monitor.queue.settings.maxnumberworkers=Максимальное количество рабочих
|
||||
monitor.queue.settings.maxnumberworkers.placeholder=В настоящее время %[1]d
|
||||
monitor.queue.settings.maxnumberworkers.error=Максимальное количество работников должно быть числом
|
||||
monitor.queue.settings.maxnumberworkers.error=Максимальное количество рабочих должно быть числом
|
||||
monitor.queue.settings.submit=Обновить настройки
|
||||
monitor.queue.settings.changed=Настройки обновлены
|
||||
monitor.queue.settings.remove_all_items=Удалить все
|
||||
|
@ -3166,7 +3201,7 @@ error.unit_not_allowed=У вас нет доступа к этому разде
|
|||
title=Пакеты
|
||||
desc=Управление пакетами репозитория.
|
||||
empty=Пока нет пакетов.
|
||||
empty.documentation=Дополнительную информацию о реестре пакетов можно найти в <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io/en-us/usage/packages/overview/">документации</a>.
|
||||
empty.documentation=Дополнительную информацию о реестре пакетов можно найти в <a target="_blank" rel="noopener noreferrer" href="%s">документации</a>.
|
||||
empty.repo=Вы загрузили пакет, но он здесь не отображается? Перейдите в <a href="%[1]s">настройки пакета</a> и свяжите его с этим репозиторием.
|
||||
filter.type=Тип
|
||||
filter.type.all=Все
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
secret_model "code.gitea.io/gitea/models/secret"
|
||||
actions_module "code.gitea.io/gitea/modules/actions"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/json"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
@ -54,8 +55,10 @@ func pickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv
|
|||
|
||||
func getSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) map[string]string {
|
||||
secrets := map[string]string{}
|
||||
if task.Job.Run.IsForkPullRequest {
|
||||
if task.Job.Run.IsForkPullRequest && task.Job.Run.TriggerEvent != actions_module.GithubEventPullRequestTarget {
|
||||
// ignore secrets for fork pull request
|
||||
// for the tasks triggered by pull_request_target event, they could access the secrets because they will run in the context of the base branch
|
||||
// see the documentation: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
|
||||
return secrets
|
||||
}
|
||||
|
||||
|
@ -116,6 +119,14 @@ func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct {
|
|||
event := map[string]interface{}{}
|
||||
_ = json.Unmarshal([]byte(t.Job.Run.EventPayload), &event)
|
||||
|
||||
// TriggerEvent is added in https://github.com/go-gitea/gitea/pull/25229
|
||||
// This fallback is for the old ActionRun that doesn't have the TriggerEvent field
|
||||
// and should be removed in 1.22
|
||||
eventName := t.Job.Run.TriggerEvent
|
||||
if eventName == "" {
|
||||
eventName = t.Job.Run.Event.Event()
|
||||
}
|
||||
|
||||
baseRef := ""
|
||||
headRef := ""
|
||||
if pullPayload, err := t.Job.Run.GetPullRequestEventPayload(); err == nil && pullPayload.PullRequest != nil && pullPayload.PullRequest.Base != nil && pullPayload.PullRequest.Head != nil {
|
||||
|
@ -137,7 +148,7 @@ func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct {
|
|||
"base_ref": baseRef, // string, The base_ref or target branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either pull_request or pull_request_target.
|
||||
"env": "", // string, Path on the runner to the file that sets environment variables from workflow commands. This file is unique to the current step and is a different file for each step in a job. For more information, see "Workflow commands for GitHub Actions."
|
||||
"event": event, // object, The full event webhook payload. You can access individual properties of the event using this context. This object is identical to the webhook payload of the event that triggered the workflow run, and is different for each event. The webhooks for each GitHub Actions event is linked in "Events that trigger workflows." For example, for a workflow run triggered by the push event, this object contains the contents of the push webhook payload.
|
||||
"event_name": t.Job.Run.Event.Event(), // string, The name of the event that triggered the workflow run.
|
||||
"event_name": eventName, // string, The name of the event that triggered the workflow run.
|
||||
"event_path": "", // string, The path to the file on the runner that contains the full event webhook payload.
|
||||
"graphql_url": "", // string, The URL of the GitHub GraphQL API.
|
||||
"head_ref": headRef, // string, The head_ref or source branch of the pull request in a workflow run. This property is only available when the event that triggers a workflow run is either pull_request or pull_request_target.
|
||||
|
|
|
@ -383,7 +383,7 @@ func ViewProject(ctx *context.Context) {
|
|||
ctx.HTML(http.StatusOK, tplProjectsView)
|
||||
}
|
||||
|
||||
func getActionIssues(ctx *context.Context) []*issues_model.Issue {
|
||||
func getActionIssues(ctx *context.Context) issues_model.IssueList {
|
||||
commaSeparatedIssueIDs := ctx.FormString("issue_ids")
|
||||
if len(commaSeparatedIssueIDs) == 0 {
|
||||
return nil
|
||||
|
@ -429,9 +429,14 @@ func UpdateIssueProject(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := issues.LoadProjects(ctx); err != nil {
|
||||
ctx.ServerError("LoadProjects", err)
|
||||
return
|
||||
}
|
||||
|
||||
projectID := ctx.FormInt64("id")
|
||||
for _, issue := range issues {
|
||||
oldProjectID := issue.ProjectID()
|
||||
oldProjectID := issue.Project.ID
|
||||
if oldProjectID == projectID {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -1988,7 +1988,7 @@ func checkIssueRights(ctx *context.Context, issue *issues_model.Issue) {
|
|||
}
|
||||
}
|
||||
|
||||
func getActionIssues(ctx *context.Context) []*issues_model.Issue {
|
||||
func getActionIssues(ctx *context.Context) issues_model.IssueList {
|
||||
commaSeparatedIssueIDs := ctx.FormString("issue_ids")
|
||||
if len(commaSeparatedIssueIDs) == 0 {
|
||||
return nil
|
||||
|
@ -2804,7 +2804,7 @@ func UpdateIssueStatus(ctx *context.Context) {
|
|||
log.Warn("Unrecognized action: %s", action)
|
||||
}
|
||||
|
||||
if _, err := issues_model.IssueList(issues).LoadRepositories(ctx); err != nil {
|
||||
if _, err := issues.LoadRepositories(ctx); err != nil {
|
||||
ctx.ServerError("LoadRepositories", err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -378,9 +378,14 @@ func UpdateIssueProject(ctx *context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if err := issues.LoadProjects(ctx); err != nil {
|
||||
ctx.ServerError("LoadProjects", err)
|
||||
return
|
||||
}
|
||||
|
||||
projectID := ctx.FormInt64("id")
|
||||
for _, issue := range issues {
|
||||
oldProjectID := issue.ProjectID()
|
||||
oldProjectID := issue.Project.ID
|
||||
if oldProjectID == projectID {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -273,6 +273,16 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
|
|||
return nil, nil
|
||||
}
|
||||
|
||||
if rctx.SidebarTocNode != nil {
|
||||
sb := &strings.Builder{}
|
||||
err = markdown.SpecializedMarkdown().Renderer().Render(sb, nil, rctx.SidebarTocNode)
|
||||
if err != nil {
|
||||
log.Error("Failed to render wiki sidebar TOC: %v", err)
|
||||
} else {
|
||||
ctx.Data["sidebarTocContent"] = sb.String()
|
||||
}
|
||||
}
|
||||
|
||||
if !isSideBar {
|
||||
buf.Reset()
|
||||
ctx.Data["sidebarEscapeStatus"], ctx.Data["sidebarContent"], err = renderFn(sidebarContent)
|
||||
|
@ -303,16 +313,6 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
|
|||
ctx.Data["footerPresent"] = false
|
||||
}
|
||||
|
||||
if rctx.SidebarTocNode != nil {
|
||||
sb := &strings.Builder{}
|
||||
err = markdown.SpecializedMarkdown().Renderer().Render(sb, nil, rctx.SidebarTocNode)
|
||||
if err != nil {
|
||||
log.Error("Failed to render wiki sidebar TOC: %v", err)
|
||||
} else {
|
||||
ctx.Data["sidebarTocContent"] = sb.String()
|
||||
}
|
||||
}
|
||||
|
||||
// get commit count - wiki revisions
|
||||
commitsCount, _ := wikiRepo.FileCommitsCount(wiki_service.DefaultBranch, pageFilename)
|
||||
ctx.Data["CommitCount"] = commitsCount
|
||||
|
|
|
@ -142,13 +142,46 @@ func notify(ctx context.Context, input *notifyInput) error {
|
|||
return fmt.Errorf("gitRepo.GetCommit: %w", err)
|
||||
}
|
||||
|
||||
var detectedWorkflows []*actions_module.DetectedWorkflow
|
||||
workflows, err := actions_module.DetectWorkflows(commit, input.Event, input.Payload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("DetectWorkflows: %w", err)
|
||||
}
|
||||
|
||||
if len(workflows) == 0 {
|
||||
log.Trace("repo %s with commit %s couldn't find workflows", input.Repo.RepoPath(), commit.ID)
|
||||
} else {
|
||||
for _, wf := range workflows {
|
||||
if wf.TriggerEvent != actions_module.GithubEventPullRequestTarget {
|
||||
wf.Ref = ref
|
||||
detectedWorkflows = append(detectedWorkflows, wf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if input.PullRequest != nil {
|
||||
// detect pull_request_target workflows
|
||||
baseRef := git.BranchPrefix + input.PullRequest.BaseBranch
|
||||
baseCommit, err := gitRepo.GetCommit(baseRef)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gitRepo.GetCommit: %w", err)
|
||||
}
|
||||
baseWorkflows, err := actions_module.DetectWorkflows(baseCommit, input.Event, input.Payload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("DetectWorkflows: %w", err)
|
||||
}
|
||||
if len(baseWorkflows) == 0 {
|
||||
log.Trace("repo %s with commit %s couldn't find pull_request_target workflows", input.Repo.RepoPath(), baseCommit.ID)
|
||||
} else {
|
||||
for _, wf := range baseWorkflows {
|
||||
if wf.TriggerEvent == actions_module.GithubEventPullRequestTarget {
|
||||
wf.Ref = baseRef
|
||||
detectedWorkflows = append(detectedWorkflows, wf)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(detectedWorkflows) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -172,18 +205,19 @@ func notify(ctx context.Context, input *notifyInput) error {
|
|||
}
|
||||
}
|
||||
|
||||
for id, content := range workflows {
|
||||
for _, dwf := range detectedWorkflows {
|
||||
run := &actions_model.ActionRun{
|
||||
Title: strings.SplitN(commit.CommitMessage, "\n", 2)[0],
|
||||
RepoID: input.Repo.ID,
|
||||
OwnerID: input.Repo.OwnerID,
|
||||
WorkflowID: id,
|
||||
WorkflowID: dwf.EntryName,
|
||||
TriggerUserID: input.Doer.ID,
|
||||
Ref: ref,
|
||||
CommitSHA: commit.ID.String(),
|
||||
Ref: dwf.Ref,
|
||||
CommitSHA: dwf.Commit.ID.String(),
|
||||
IsForkPullRequest: isForkPullRequest,
|
||||
Event: input.Event,
|
||||
EventPayload: string(p),
|
||||
TriggerEvent: dwf.TriggerEvent,
|
||||
Status: actions_model.StatusWaiting,
|
||||
}
|
||||
if need, err := ifNeedApproval(ctx, run, input.Repo, input.Doer); err != nil {
|
||||
|
@ -193,7 +227,7 @@ func notify(ctx context.Context, input *notifyInput) error {
|
|||
run.NeedApproval = need
|
||||
}
|
||||
|
||||
jobs, err := jobparser.Parse(content)
|
||||
jobs, err := jobparser.Parse(dwf.Content)
|
||||
if err != nil {
|
||||
log.Error("jobparser.Parse: %v", err)
|
||||
continue
|
||||
|
@ -259,8 +293,10 @@ func notifyPackage(ctx context.Context, sender *user_model.User, pd *packages_mo
|
|||
}
|
||||
|
||||
func ifNeedApproval(ctx context.Context, run *actions_model.ActionRun, repo *repo_model.Repository, user *user_model.User) (bool, error) {
|
||||
// don't need approval if it's not a fork PR
|
||||
if !run.IsForkPullRequest {
|
||||
// 1. don't need approval if it's not a fork PR
|
||||
// 2. don't need approval if the event is `pull_request_target` since the workflow will run in the context of base branch
|
||||
// see https://docs.github.com/en/actions/managing-workflow-runs/approving-workflow-runs-from-public-forks#about-workflow-runs-from-public-forks
|
||||
if !run.IsForkPullRequest || run.TriggerEvent == actions_module.GithubEventPullRequestTarget {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -70,9 +70,17 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts repo_mo
|
|||
if err := repo_module.CreateRepositoryByExample(ctx, doer, u, repo, true, false); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := adoptRepository(ctx, repoPath, doer, repo, opts); err != nil {
|
||||
|
||||
// Re-fetch the repository from database before updating it (else it would
|
||||
// override changes that were done earlier with sql)
|
||||
if repo, err = repo_model.GetRepositoryByID(ctx, repo.ID); err != nil {
|
||||
return fmt.Errorf("getRepositoryByID: %w", err)
|
||||
}
|
||||
|
||||
if err := adoptRepository(ctx, repoPath, doer, repo, opts.DefaultBranch); err != nil {
|
||||
return fmt.Errorf("createDelegateHooks: %w", err)
|
||||
}
|
||||
|
||||
if err := repo_module.CheckDaemonExportOK(ctx, repo); err != nil {
|
||||
return fmt.Errorf("checkDaemonExportOK: %w", err)
|
||||
}
|
||||
|
@ -95,12 +103,12 @@ func AdoptRepository(ctx context.Context, doer, u *user_model.User, opts repo_mo
|
|||
return nil, err
|
||||
}
|
||||
|
||||
notification.NotifyCreateRepository(ctx, doer, u, repo)
|
||||
notification.NotifyAdoptRepository(ctx, doer, u, repo)
|
||||
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
func adoptRepository(ctx context.Context, repoPath string, u *user_model.User, repo *repo_model.Repository, opts repo_module.CreateRepoOptions) (err error) {
|
||||
func adoptRepository(ctx context.Context, repoPath string, u *user_model.User, repo *repo_model.Repository, defaultBranch string) (err error) {
|
||||
isExist, err := util.IsExist(repoPath)
|
||||
if err != nil {
|
||||
log.Error("Unable to check if %s exists. Error: %v", repoPath, err)
|
||||
|
@ -114,12 +122,6 @@ func adoptRepository(ctx context.Context, repoPath string, u *user_model.User, r
|
|||
return fmt.Errorf("createDelegateHooks: %w", err)
|
||||
}
|
||||
|
||||
// Re-fetch the repository from database before updating it (else it would
|
||||
// override changes that were done earlier with sql)
|
||||
if repo, err = repo_model.GetRepositoryByID(ctx, repo.ID); err != nil {
|
||||
return fmt.Errorf("getRepositoryByID: %w", err)
|
||||
}
|
||||
|
||||
repo.IsEmpty = false
|
||||
|
||||
// Don't bother looking this repo in the context it won't be there
|
||||
|
@ -129,8 +131,8 @@ func adoptRepository(ctx context.Context, repoPath string, u *user_model.User, r
|
|||
}
|
||||
defer gitRepo.Close()
|
||||
|
||||
if len(opts.DefaultBranch) > 0 {
|
||||
repo.DefaultBranch = opts.DefaultBranch
|
||||
if len(defaultBranch) > 0 {
|
||||
repo.DefaultBranch = defaultBranch
|
||||
|
||||
if err = gitRepo.SetDefaultBranch(repo.DefaultBranch); err != nil {
|
||||
return fmt.Errorf("setDefaultBranch: %w", err)
|
||||
|
|
|
@ -11,16 +11,16 @@
|
|||
</a>
|
||||
|
||||
<!-- mobile right menu, it must be here because in mobile view, each item is a flex column, the first item is a full row column -->
|
||||
<div class="ui secondary menu item navbar-mobile-right gt-gap-2">
|
||||
<div class="ui secondary menu item navbar-mobile-right">
|
||||
{{if .IsSigned}}
|
||||
<a class="item mobile-right-item gt-mr-2 gt-p-3" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{.locale.Tr "notifications"}}" aria-label="{{.locale.Tr "notifications"}}">
|
||||
<a id="mobile-notifications-icon" class="item gt-w-auto gt-p-3" href="{{AppSubUrl}}/notifications" data-tooltip-content="{{.locale.Tr "notifications"}}" aria-label="{{.locale.Tr "notifications"}}">
|
||||
<div class="gt-relative">
|
||||
{{svg "octicon-bell"}}
|
||||
<span class="notification_count{{if not $notificationUnreadCount}} gt-hidden{{end}}">{{$notificationUnreadCount}}</span>
|
||||
</div>
|
||||
</a>
|
||||
{{end}}
|
||||
<button class="item mobile-right-item ui icon mini button gt-p-3 gt-m-0" id="navbar-expand-toggle">{{svg "octicon-three-bars"}}</button>
|
||||
<button class="item gt-w-auto ui icon mini button gt-p-3 gt-m-0" id="navbar-expand-toggle">{{svg "octicon-three-bars"}}</button>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -165,13 +165,6 @@
|
|||
<div class="item">item</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui button dropdown">
|
||||
<span class="text">button dropdown</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="menu">
|
||||
<div class="item">item</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui search selection dropdown">
|
||||
<span class="text">search ...</span>
|
||||
<input name="value" class="search">
|
||||
|
@ -212,18 +205,39 @@
|
|||
|
||||
<div>
|
||||
<div class="ui dropdown mini button">
|
||||
<span class="text">small dropdown</span>
|
||||
{{svg "octicon-triangle-down" 12 "dropdown icon"}}
|
||||
<div class="menu">
|
||||
<div class="item">item</div>
|
||||
</div>
|
||||
<span class="text">mini dropdown</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
</div>
|
||||
<div class="ui dropdown tiny button">
|
||||
<span class="text">tiny dropdown</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
</div>
|
||||
<div class="ui button dropdown">
|
||||
<span class="text">button dropdown</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
</div>
|
||||
<div class="ui dropdown large button">
|
||||
<span class="text">large dropdown</span>
|
||||
{{svg "octicon-triangle-down" 18 "dropdown icon"}}
|
||||
<div class="menu">
|
||||
<div class="item">item</div>
|
||||
</div>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="ui dropdown mini compact button">
|
||||
<span class="text">mini compact</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
</div>
|
||||
<div class="ui dropdown tiny compact button">
|
||||
<span class="text">tiny compact</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
</div>
|
||||
<div class="ui button compact dropdown">
|
||||
<span class="text">button compact</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
</div>
|
||||
<div class="ui dropdown large compact button">
|
||||
<span class="text">large compact</span>
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -54,9 +54,9 @@
|
|||
{{$description := .DescriptionHTML $.Context}}
|
||||
{{if $description}}<p>{{$description}}</p>{{end}}
|
||||
{{if .Topics}}
|
||||
<div class="ui tags">
|
||||
<div class="gt-df gt-fw gt-gap-2 gt-mb-3">
|
||||
{{range .Topics}}
|
||||
{{if ne . ""}}<a href="{{AppSubUrl}}/explore/repos?q={{.}}&topic=1"><div class="ui small label topic">{{.}}</div></a>{{end}}
|
||||
{{if ne . ""}}<a class="ui label" href="{{AppSubUrl}}/explore/repos?q={{.}}&topic=1">{{.}}</a>{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
{{.locale.Tr "repo.diff.browse_source"}}
|
||||
</a>
|
||||
{{if and ($.Permission.CanWrite $.UnitTypeCode) (not $.Repository.IsArchived) (not .IsDeleted)}}{{- /* */ -}}
|
||||
<div class="ui primary tiny floating dropdown icon button">{{.locale.Tr "repo.commit.operations"}}
|
||||
<div class="ui dropdown primary tiny button">
|
||||
{{.locale.Tr "repo.commit.operations"}}
|
||||
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
|
||||
<div class="menu">
|
||||
<div class="ui header">{{.locale.Tr "repo.commit.operations"}}</div>
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<script id="diff-data-script" type="module">
|
||||
const diffDataFiles = [{{range $i, $file := .Diff.Files}}{Name:"{{$file.Name}}",NameHash:"{{$file.NameHash}}",Type:{{$file.Type}},IsBin:{{$file.IsBin}},Addition:{{$file.Addition}},Deletion:{{$file.Deletion}}},{{end}}];
|
||||
const diffDataFiles = [{{range $i, $file := .Diff.Files}}{Name:"{{$file.Name}}",NameHash:"{{$file.NameHash}}",Type:{{$file.Type}},IsBin:{{$file.IsBin}},Addition:{{$file.Addition}},Deletion:{{$file.Deletion}},IsViewed:{{$file.IsViewed}}},{{end}}];
|
||||
const diffData = {
|
||||
isIncomplete: {{.Diff.IsIncomplete}},
|
||||
tooManyFilesMessage: "{{$.locale.Tr "repo.diff.too_many_files"}}",
|
||||
|
|
|
@ -192,7 +192,7 @@
|
|||
{{if .HasPullRequest}}
|
||||
<div class="ui segment grid title">
|
||||
<div class="twelve wide column issue-title">
|
||||
{{.locale.Tr "repo.pulls.has_pull_request" (Escape $.RepoLink) (Escape $.RepoRelPath) .PullRequest.Index | Safe}}
|
||||
{{.locale.Tr "repo.pulls.has_pull_request" (print (Escape $.RepoLink) "/pulls/" .PullRequest.Issue.Index) (Escape $.RepoRelPath) .PullRequest.Index | Safe}}
|
||||
<h1>
|
||||
<span id="issue-title">{{RenderIssueTitle $.Context .PullRequest.Issue.Title $.RepoLink $.Repository.ComposeMetas}}</span>
|
||||
<span class="index">#{{.PullRequest.Issue.Index}}</span>
|
||||
|
|
|
@ -192,9 +192,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="ui select-project list">
|
||||
<span class="no-select item {{if .Issue.ProjectID}}gt-hidden{{end}}">{{.locale.Tr "repo.issues.new.no_projects"}}</span>
|
||||
<span class="no-select item {{if .Issue.Project}}gt-hidden{{end}}">{{.locale.Tr "repo.issues.new.no_projects"}}</span>
|
||||
<div class="selected">
|
||||
{{if .Issue.ProjectID}}
|
||||
{{if .Issue.Project}}
|
||||
<a class="item muted sidebar-item-link" href="{{.Issue.Project.Link}}">
|
||||
{{svg .Issue.Project.IconName 18 "gt-mr-3"}}{{.Issue.Project.Title}}
|
||||
</a>
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
<div class="ui middle very relaxed page grid">
|
||||
<div class="column">
|
||||
{{template "repo/migrate/helper" .}}
|
||||
<div class="ui three stackable cards">
|
||||
<div class="ui cards migrate-entries">
|
||||
{{range .Services}}
|
||||
<a class="ui card gt-df gt-ac" href="{{AppSubUrl}}/repo/migrate?service_type={{.}}&org={{$.Org}}&mirror={{$.Mirror}}">
|
||||
<a class="ui card migrate-entry gt-df gt-ac" href="{{AppSubUrl}}/repo/migrate?service_type={{.}}&org={{$.Org}}&mirror={{$.Mirror}}">
|
||||
{{if eq .Name "github"}}
|
||||
{{svg "octicon-mark-github" 184 "gt-p-4"}}
|
||||
{{else if eq .Name "gitlab"}}
|
||||
|
|
|
@ -4,20 +4,22 @@
|
|||
{{$title := .title}}
|
||||
<div class="ui container">
|
||||
<div class="ui stackable grid">
|
||||
<div class="ui eight wide column text right gt-df gt-ac gt-je">
|
||||
<div class="ui eight wide column">
|
||||
<div class="ui header">
|
||||
<a class="file-revisions-btn ui basic button" title="{{.locale.Tr "repo.wiki.back_to_wiki"}}" href="{{.RepoLink}}/wiki/{{.PageURL}}"><span>{{.revision}}</span> {{svg "octicon-home"}}</a>
|
||||
{{$title}}
|
||||
<div class="ui sub header gt-word-break">
|
||||
{{$timeSince := TimeSince .Author.When $.locale}}
|
||||
{{.locale.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince | Safe}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui eight wide column text right">
|
||||
<div class="ui action small input" id="clone-panel">
|
||||
{{template "repo/clone_buttons" .}}
|
||||
{{template "repo/clone_script" .}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui header eight wide column">
|
||||
<a class="file-revisions-btn ui basic button" title="{{.locale.Tr "repo.wiki.back_to_wiki"}}" href="{{.RepoLink}}/wiki/{{.PageURL}}" ><span>{{.revision}}</span> {{svg "octicon-home"}}</a>
|
||||
{{$title}}
|
||||
<div class="ui sub header gt-word-break">
|
||||
{{$timeSince := TimeSince .Author.When $.locale}}
|
||||
{{.locale.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince | Safe}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2 class="ui top header">{{.locale.Tr "repo.wiki.wiki_page_revisions"}}</h2>
|
||||
<div class="gt-mt-4">
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<div role="main" aria-label="{{.Title}}" class="page-content repository wiki start">
|
||||
{{template "repo/header" .}}
|
||||
<div class="ui container">
|
||||
<div class="ui center segment">
|
||||
{{svg "octicon-book" 32}}
|
||||
<div class="ui center segment gt-py-5">
|
||||
{{svg "octicon-book" 48}}
|
||||
<h2>{{.locale.Tr "repo.wiki.welcome"}}</h2>
|
||||
<p>{{.locale.Tr "repo.wiki.welcome_desc"}}</p>
|
||||
{{if and .CanWriteWiki (not .Repository.IsMirror)}}
|
||||
|
|
|
@ -63,39 +63,41 @@
|
|||
<p>{{.FormatWarning}}</p>
|
||||
</div>
|
||||
{{end}}
|
||||
<div class="ui gt-mt-0 {{if or .sidebarPresent .sidebarTocContent}}grid equal width{{end}}">
|
||||
<div class="ui {{if or .sidebarPresent .sidebarTocContent}}eleven wide column{{else}}gt-ml-0{{end}} segment markup wiki-content-main">
|
||||
|
||||
<div class="wiki-content-parts">
|
||||
{{if .sidebarTocContent}}
|
||||
<div class="markup wiki-content-sidebar wiki-content-toc">
|
||||
{{.sidebarTocContent | Safe}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="markup wiki-content-main {{if or .sidebarTocContent .sidebarPresent}}with-sidebar{{end}}">
|
||||
{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .EscapeStatus "root" $}}
|
||||
{{.content | Safe}}
|
||||
</div>
|
||||
{{if or .sidebarPresent .sidebarTocContent}}
|
||||
<div class="column gt-pt-0">
|
||||
{{if .sidebarTocContent}}
|
||||
<div class="ui segment wiki-content-toc">
|
||||
{{.sidebarTocContent | Safe}}
|
||||
</div>
|
||||
|
||||
{{if .sidebarPresent}}
|
||||
<div class="markup wiki-content-sidebar">
|
||||
{{if and .CanWriteWiki (not .Repository.IsMirror)}}
|
||||
<a class="ui right floated muted" href="{{.RepoLink}}/wiki/_Sidebar?action=_edit" aria-label="{{.locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
|
||||
{{end}}
|
||||
{{if .sidebarPresent}}
|
||||
<div class="ui segment wiki-content-sidebar">
|
||||
{{if and .CanWriteWiki (not .Repository.IsMirror)}}
|
||||
<a class="ui right floated muted" href="{{.RepoLink}}/wiki/_Sidebar?action=_edit" aria-label="{{.locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
|
||||
{{end}}
|
||||
{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .sidebarEscapeStatus "root" $}}
|
||||
{{.sidebarContent | Safe}}
|
||||
</div>
|
||||
{{template "repo/unicode_escape_prompt" dict "EscapeStatus" .sidebarEscapeStatus "root" $}}
|
||||
{{.sidebarContent | Safe}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div class="gt-clear-both"></div>
|
||||
|
||||
{{if .footerPresent}}
|
||||
<div class="markup wiki-content-footer">
|
||||
{{if and .CanWriteWiki (not .Repository.IsMirror)}}
|
||||
<a class="ui right floated muted" href="{{.RepoLink}}/wiki/_Footer?action=_edit" aria-label="{{.locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
|
||||
{{end}}
|
||||
{{template "repo/unicode_escape_prompt" dict "footerEscapeStatus" .sidebarEscapeStatus "root" $}}
|
||||
{{.footerContent | Safe}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if .footerPresent}}
|
||||
<div class="ui segment wiki-content-footer">
|
||||
{{if and .CanWriteWiki (not .Repository.IsMirror)}}
|
||||
<a class="ui right floated muted" href="{{.RepoLink}}/wiki/_Footer?action=_edit" aria-label="{{.locale.Tr "repo.wiki.edit_page_button"}}">{{svg "octicon-pencil"}}</a>
|
||||
{{end}}
|
||||
{{template "repo/unicode_escape_prompt" dict "footerEscapeStatus" .sidebarEscapeStatus "root" $}}
|
||||
{{.footerContent | Safe}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -128,6 +128,10 @@
|
|||
{{.locale.Tr "settings.add_email"}}
|
||||
</button>
|
||||
</form>
|
||||
{{/* if ActivationsPending is false, then CanAddEmails must be true, so if CanAddEmails is false, ActivationsPending must be true */}}
|
||||
{{if not .CanAddEmails}}
|
||||
<div class="ui warning message">{{.locale.Tr "settings.can_not_add_email_activations_pending"}}</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<h4 class="ui top attached error header">
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
{{/* No account links, no way to add account links: Menu will not be shown. */}}
|
||||
{{if or .AccountLinks .OrderedOAuth2Names}}
|
||||
<h4 class="ui top attached header">
|
||||
{{.locale.Tr "settings.manage_account_links"}}
|
||||
{{if .OrderedOAuth2Names}}
|
||||
|
@ -23,20 +25,18 @@
|
|||
<div class="item">
|
||||
{{.locale.Tr "settings.manage_account_links_desc"}}
|
||||
</div>
|
||||
{{if .AccountLinks}}
|
||||
{{range $loginSource, $provider := .AccountLinks}}
|
||||
<div class="item gt-df gt-ac">
|
||||
<div class="gt-f1">
|
||||
<span data-tooltip-content="{{$provider}}">
|
||||
{{$loginSource.Name}}
|
||||
{{if $loginSource.IsActive}}<span class="text primary">{{$.locale.Tr "repo.settings.active"}}</span>{{end}}
|
||||
</span>
|
||||
</div>
|
||||
<button class="ui red tiny button delete-button" data-modal-id="delete-account-link" data-url="{{AppSubUrl}}/user/settings/security/account_link" data-id="{{$loginSource.ID}}">
|
||||
{{$.locale.Tr "settings.delete_key"}}
|
||||
</button>
|
||||
{{range $loginSource, $provider := .AccountLinks}}
|
||||
<div class="item gt-df gt-ac">
|
||||
<div class="gt-f1">
|
||||
<span data-tooltip-content="{{$provider}}">
|
||||
{{$loginSource.Name}}
|
||||
{{if $loginSource.IsActive}}<span class="text primary">{{$.locale.Tr "repo.settings.active"}}</span>{{end}}
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
<button class="ui red tiny button delete-button" data-modal-id="delete-account-link" data-url="{{AppSubUrl}}/user/settings/security/account_link" data-id="{{$loginSource.ID}}">
|
||||
{{$.locale.Tr "settings.delete_key"}}
|
||||
</button>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -51,3 +51,4 @@
|
|||
</div>
|
||||
{{template "base/modal_actions_confirm" .}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
unit_model "code.gitea.io/gitea/models/unit"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
actions_module "code.gitea.io/gitea/modules/actions"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
pull_service "code.gitea.io/gitea/services/pull"
|
||||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
files_service "code.gitea.io/gitea/services/repository/files"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestPullRequestTargetEvent(t *testing.T) {
|
||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the base repo
|
||||
user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}) // owner of the forked repo
|
||||
|
||||
// create the base repo
|
||||
baseRepo, err := repo_service.CreateRepository(db.DefaultContext, user2, user2, repo_module.CreateRepoOptions{
|
||||
Name: "repo-pull-request-target",
|
||||
Description: "test pull-request-target event",
|
||||
AutoInit: true,
|
||||
Gitignores: "Go",
|
||||
License: "MIT",
|
||||
Readme: "Default",
|
||||
DefaultBranch: "main",
|
||||
IsPrivate: false,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, baseRepo)
|
||||
|
||||
// enable actions
|
||||
err = repo_model.UpdateRepositoryUnits(baseRepo, []repo_model.RepoUnit{{
|
||||
RepoID: baseRepo.ID,
|
||||
Type: unit_model.TypeActions,
|
||||
}}, nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// create the forked repo
|
||||
forkedRepo, err := repo_service.ForkRepository(git.DefaultContext, user2, user3, repo_service.ForkRepoOptions{
|
||||
BaseRepo: baseRepo,
|
||||
Name: "forked-repo-pull-request-target",
|
||||
Description: "test pull-request-target event",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, forkedRepo)
|
||||
|
||||
// add workflow file to the base repo
|
||||
addWorkflowToBaseResp, err := files_service.ChangeRepoFiles(git.DefaultContext, baseRepo, user2, &files_service.ChangeRepoFilesOptions{
|
||||
Files: []*files_service.ChangeRepoFile{
|
||||
{
|
||||
Operation: "create",
|
||||
TreePath: ".gitea/workflows/pr.yml",
|
||||
Content: "name: test\non: pull_request_target\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - run: echo helloworld\n",
|
||||
},
|
||||
},
|
||||
Message: "add workflow",
|
||||
OldBranch: "main",
|
||||
NewBranch: "main",
|
||||
Author: &files_service.IdentityOptions{
|
||||
Name: user2.Name,
|
||||
Email: user2.Email,
|
||||
},
|
||||
Committer: &files_service.IdentityOptions{
|
||||
Name: user2.Name,
|
||||
Email: user2.Email,
|
||||
},
|
||||
Dates: &files_service.CommitDateOptions{
|
||||
Author: time.Now(),
|
||||
Committer: time.Now(),
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, addWorkflowToBaseResp)
|
||||
|
||||
// add a new file to the forked repo
|
||||
addFileToForkedResp, err := files_service.ChangeRepoFiles(git.DefaultContext, forkedRepo, user3, &files_service.ChangeRepoFilesOptions{
|
||||
Files: []*files_service.ChangeRepoFile{
|
||||
{
|
||||
Operation: "create",
|
||||
TreePath: "file_1.txt",
|
||||
Content: "file1",
|
||||
},
|
||||
},
|
||||
Message: "add file1",
|
||||
OldBranch: "main",
|
||||
NewBranch: "fork-branch-1",
|
||||
Author: &files_service.IdentityOptions{
|
||||
Name: user3.Name,
|
||||
Email: user3.Email,
|
||||
},
|
||||
Committer: &files_service.IdentityOptions{
|
||||
Name: user3.Name,
|
||||
Email: user3.Email,
|
||||
},
|
||||
Dates: &files_service.CommitDateOptions{
|
||||
Author: time.Now(),
|
||||
Committer: time.Now(),
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, addFileToForkedResp)
|
||||
|
||||
// create Pull
|
||||
pullIssue := &issues_model.Issue{
|
||||
RepoID: baseRepo.ID,
|
||||
Title: "Test pull-request-target-event",
|
||||
PosterID: user3.ID,
|
||||
Poster: user3,
|
||||
IsPull: true,
|
||||
}
|
||||
pullRequest := &issues_model.PullRequest{
|
||||
HeadRepoID: forkedRepo.ID,
|
||||
BaseRepoID: baseRepo.ID,
|
||||
HeadBranch: "fork-branch-1",
|
||||
BaseBranch: "main",
|
||||
HeadRepo: forkedRepo,
|
||||
BaseRepo: baseRepo,
|
||||
Type: issues_model.PullRequestGitea,
|
||||
}
|
||||
err = pull_service.NewPullRequest(git.DefaultContext, baseRepo, pullIssue, nil, nil, pullRequest, nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// load and compare ActionRun
|
||||
actionRun := unittest.AssertExistsAndLoadBean(t, &actions_model.ActionRun{RepoID: baseRepo.ID})
|
||||
assert.Equal(t, addWorkflowToBaseResp.Commit.SHA, actionRun.CommitSHA)
|
||||
assert.Equal(t, actions_module.GithubEventPullRequestTarget, actionRun.TriggerEvent)
|
||||
})
|
||||
}
|
|
@ -35,9 +35,6 @@
|
|||
font-weight: var(--font-weight-semibold);
|
||||
width: 220px;
|
||||
margin-right: 5px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
|
|
|
@ -2192,6 +2192,17 @@ table th[data-sortt-desc] .svg {
|
|||
- "> .ui.label > .delete.icon": the "x" icon for removing a label item in multiple selection dropdown
|
||||
*/
|
||||
|
||||
.ui.dropdown.mini.button,
|
||||
.ui.dropdown.tiny.button {
|
||||
padding-right: 20px;
|
||||
}
|
||||
.ui.dropdown.button {
|
||||
padding-right: 22px;
|
||||
}
|
||||
.ui.dropdown.large.button {
|
||||
padding-right: 24px;
|
||||
}
|
||||
|
||||
/* Gitea uses SVG images instead of Fomantic builtin "<i>" font icons, so we need to reset the icon styles */
|
||||
.ui.ui.dropdown > .icon.icon {
|
||||
position: initial; /* plain dropdown and button dropdown use flex layout for icons */
|
||||
|
|
|
@ -32,10 +32,6 @@
|
|||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ui.repository.list .item .ui.tags {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.ui.repository.list .repo-title .labels {
|
||||
word-break: normal;
|
||||
flex-shrink: 0;
|
||||
|
|
|
@ -75,6 +75,7 @@ Gitea's private styles use `g-` prefix.
|
|||
.gt-self-start { align-self: flex-start !important; }
|
||||
.gt-self-end { align-self: flex-end !important; }
|
||||
.gt-no-underline { text-decoration-line: none !important; }
|
||||
.gt-w-auto { width: auto !important; }
|
||||
|
||||
.gt-overflow-x-auto { overflow-x: auto !important; }
|
||||
.gt-overflow-x-scroll { overflow-x: scroll !important; }
|
||||
|
@ -85,6 +86,7 @@ Gitea's private styles use `g-` prefix.
|
|||
|
||||
.gt-float-left { float: left !important; }
|
||||
.gt-float-right { float: right !important; }
|
||||
.gt-clear-both { clear: both !important; }
|
||||
|
||||
.gt-font-light { font-weight: var(--font-weight-light) !important; }
|
||||
.gt-font-normal { font-weight: var(--font-weight-normal) !important; }
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
@import "./repo/issue-list.css";
|
||||
@import "./repo/list-header.css";
|
||||
@import "./repo/linebutton.css";
|
||||
@import "./repo/wiki.css";
|
||||
|
||||
@import "./editor/fileeditor.css";
|
||||
@import "./editor/combomarkdowneditor.css";
|
||||
|
|
|
@ -514,20 +514,6 @@
|
|||
padding-left: 2em;
|
||||
}
|
||||
|
||||
.repository.wiki.revisions .ui.container > .ui.stackable.grid {
|
||||
-ms-flex-direction: row-reverse;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.repository.wiki.revisions .ui.container > .ui.stackable.grid > .header {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.repository.wiki.revisions .ui.container > .ui.stackable.grid > .header .sub.header {
|
||||
padding-left: 52px;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.file-revisions-btn {
|
||||
display: block;
|
||||
float: left;
|
||||
|
|
|
@ -34,6 +34,10 @@
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
#navbar .dropdown .item {
|
||||
justify-content: stretch;
|
||||
}
|
||||
|
||||
#navbar a.item:hover,
|
||||
#navbar button.item:hover {
|
||||
background: var(--color-nav-hover-bg);
|
||||
|
@ -85,19 +89,19 @@
|
|||
#navbar.navbar-menu-open .item {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
#navbar.navbar-menu-open .navbar-left #navbar-logo {
|
||||
justify-content: flex-start;
|
||||
width: 50%;
|
||||
min-height: 48px;
|
||||
width: auto;
|
||||
}
|
||||
#navbar.navbar-menu-open .navbar-left .navbar-mobile-right {
|
||||
justify-content: flex-end;
|
||||
width: 50%;
|
||||
min-height: 48px;
|
||||
}
|
||||
#navbar.navbar-menu-open .mobile-right-item {
|
||||
width: auto !important;
|
||||
#navbar #mobile-notifications-icon {
|
||||
margin-right: 6px !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1887,50 +1887,9 @@
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.repository.wiki.start .ui.segment {
|
||||
padding-top: 70px;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
|
||||
.repository.wiki.start .ui.segment .svg {
|
||||
height: 48px;
|
||||
}
|
||||
|
||||
.repository.wiki.new .ui.attached.tabular.menu.previewtabs {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.file-view.markup {
|
||||
padding: 1em 2em;
|
||||
}
|
||||
|
||||
.wiki-content-main {
|
||||
padding: 1em 2em !important;
|
||||
margin-left: 1em !important;
|
||||
}
|
||||
|
||||
.wiki-pages-list .wiki-git-entry {
|
||||
margin-left: 10px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.wiki-pages-list td:hover .wiki-git-entry {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.repository.wiki .dividing.header .stackable.grid .button {
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.repository.wiki #clone-panel #repo-clone-url {
|
||||
width: 160px;
|
||||
}
|
||||
}
|
||||
|
||||
.repository .activity-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
@ -2988,22 +2947,6 @@ tbody.commit-list {
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
.wiki-content-sidebar .ui.message.unicode-escape-prompt p,
|
||||
.wiki-content-footer .ui.message.unicode-escape-prompt p {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.wiki-content-toc ul {
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
padding: 5px 0 5px 1em;
|
||||
}
|
||||
|
||||
.wiki-content-toc ul ul {
|
||||
border-left: 1px var(--color-secondary);
|
||||
border-left-style: dashed;
|
||||
}
|
||||
|
||||
/* fomantic's last-child selector does not work with hidden last child */
|
||||
.ui.buttons .unescape-button {
|
||||
border-top-right-radius: 0.28571429rem;
|
||||
|
@ -3157,18 +3100,37 @@ tbody.commit-list {
|
|||
}
|
||||
}
|
||||
|
||||
.repository.migrate .card {
|
||||
.migrate-entries {
|
||||
display: grid !important;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 25px;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.migrate-entries {
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.migrate-entry {
|
||||
transition: all 0.1s ease-in-out;
|
||||
box-shadow: none !important;
|
||||
border: 1px solid var(--color-secondary);
|
||||
color: var(--color-text);
|
||||
color: var(--color-text) !important;
|
||||
width: auto !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.repository.migrate .card:hover {
|
||||
.migrate-entry:hover {
|
||||
transform: scale(105%);
|
||||
box-shadow: 0 0.5rem 1rem var(--color-shadow) !important;
|
||||
}
|
||||
|
||||
.migrate-entry .description {
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.repository.file.list #repo-files-table .entry,
|
||||
.repository.file.list #repo-files-table .commit-list {
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
.repository.wiki .wiki-pages-list .wiki-git-entry {
|
||||
margin-left: 10px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.repository.wiki .wiki-pages-list td:hover .wiki-git-entry {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.repository.wiki .markup {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.repository.wiki .wiki-content-parts .markup {
|
||||
border: 1px solid var(--color-secondary);
|
||||
padding: 1em;
|
||||
margin-top: 1em;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
.repository.wiki .wiki-content-main.with-sidebar {
|
||||
float: left;
|
||||
width: 80%;
|
||||
max-width: calc(100% - 150px - 1em); /* match the min-width of .wiki-content-sidebar */
|
||||
}
|
||||
|
||||
.repository.wiki .wiki-content-sidebar {
|
||||
float: right;
|
||||
width: calc(20% - 1em);
|
||||
min-width: 150px;
|
||||
}
|
||||
|
||||
.repository.wiki .wiki-content-sidebar .ui.message.unicode-escape-prompt p {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.repository.wiki .wiki-content-footer {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.repository.wiki .wiki-content-toc ul {
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
padding: 5px 0 5px 1em;
|
||||
}
|
||||
|
||||
.repository.wiki .wiki-content-toc ul ul {
|
||||
border-left: 1px var(--color-secondary);
|
||||
border-left-style: dashed;
|
||||
}
|
||||
|
||||
@media (max-width: 767.98px) {
|
||||
.repository.wiki #clone-panel #repo-clone-url {
|
||||
width: 160px;
|
||||
}
|
||||
.repository.wiki .wiki-content-main.with-sidebar,
|
||||
.repository.wiki .wiki-content-sidebar {
|
||||
float: none;
|
||||
width: 100%;
|
||||
min-width: unset;
|
||||
max-width: unset;
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
/>
|
||||
<a
|
||||
v-if="item.isFile"
|
||||
class="file gt-ellipsis"
|
||||
:class="['file gt-ellipsis', {'viewed': item.file.IsViewed}]"
|
||||
:href="item.isFile ? '#diff-' + item.file.NameHash : ''"
|
||||
>{{ item.name }}</a>
|
||||
<SvgIcon
|
||||
|
@ -148,4 +148,8 @@ a:hover {
|
|||
text-decoration: none;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
a.file.viewed {
|
||||
color: var(--color-text-light-3);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -395,8 +395,6 @@ function initGlobalShowModal() {
|
|||
if (colorPickers.length > 0) {
|
||||
initCompColorPicker(); // FIXME: this might cause duplicate init
|
||||
}
|
||||
// all non-"ok" buttons which do not have "type" should not submit the form, should not be triggered by "Enter"
|
||||
$modal.find('form button:not(.ok):not([type])').attr('type', 'button');
|
||||
$modal.modal('setting', {
|
||||
onApprove: () => {
|
||||
// "form-fetch-action" can handle network errors gracefully,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import {diffTreeStore} from '../modules/stores.js';
|
||||
import {setFileFolding} from './file-fold.js';
|
||||
|
||||
const {csrfToken, pageData} = window.config;
|
||||
|
@ -53,9 +54,17 @@ export function initViewedCheckboxListenerFor() {
|
|||
const hasChangedLabel = form.parentNode.querySelector('.changed-since-last-review');
|
||||
hasChangedLabel?.remove();
|
||||
|
||||
const fileName = checkbox.getAttribute('name');
|
||||
|
||||
// check if the file is in our difftreestore and if we find it -> change the IsViewed status
|
||||
const fileInPageData = diffTreeStore().files.find((x) => x.Name === fileName);
|
||||
if (fileInPageData) {
|
||||
fileInPageData.IsViewed = this.checked;
|
||||
}
|
||||
|
||||
// Unfortunately, actual forms cause too many problems, hence another approach is needed
|
||||
const files = {};
|
||||
files[checkbox.getAttribute('name')] = this.checked;
|
||||
files[fileName] = this.checked;
|
||||
const data = {files};
|
||||
const headCommitSHA = form.getAttribute('data-headcommit');
|
||||
if (headCommitSHA) data.headCommitSHA = headCommitSHA;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import $ from 'jquery';
|
||||
import {initMarkupContent} from '../markup/content.js';
|
||||
import {validateTextareaNonEmpty, initComboMarkdownEditor} from './comp/ComboMarkdownEditor.js';
|
||||
import {fomanticMobileScreen} from '../modules/fomantic.js';
|
||||
|
||||
const {csrfToken} = window.config;
|
||||
|
||||
|
@ -70,6 +71,17 @@ async function initRepoWikiFormEditor() {
|
|||
});
|
||||
}
|
||||
|
||||
function collapseWikiTocForMobile(collapse) {
|
||||
if (collapse) {
|
||||
document.querySelector('.wiki-content-toc details')?.removeAttribute('open');
|
||||
}
|
||||
}
|
||||
|
||||
export function initRepoWikiForm() {
|
||||
if (!document.querySelector('.page-content.repository.wiki')) return;
|
||||
|
||||
fomanticMobileScreen.addEventListener('change', (e) => collapseWikiTocForMobile(e.matches));
|
||||
collapseWikiTocForMobile(fomanticMobileScreen.matches);
|
||||
|
||||
initRepoWikiFormEditor();
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ import {initAriaCheckboxPatch} from './aria/checkbox.js';
|
|||
import {initAriaDropdownPatch} from './aria/dropdown.js';
|
||||
import {svg} from '../svg.js';
|
||||
|
||||
export const fomanticMobileScreen = window.matchMedia('only screen and (max-width: 767.98px)');
|
||||
|
||||
export function initGiteaFomantic() {
|
||||
// Silence fomantic's error logging when tabs are used without a target content element
|
||||
$.fn.tab.settings.silent = true;
|
||||
|
|
Loading…
Reference in New Issue