Skip to content

Commit 1750756

Browse files
authored
Merge branch 'main' into actionbg
2 parents 37207b9 + 226231e commit 1750756

File tree

17 files changed

+154
-53
lines changed

17 files changed

+154
-53
lines changed

models/asymkey/ssh_key_authorized_keys.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error {
139139
if err != nil {
140140
return err
141141
}
142+
defer f.Close()
143+
142144
scanner := bufio.NewScanner(f)
143145
for scanner.Scan() {
144146
line := scanner.Text()
@@ -148,15 +150,12 @@ func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error {
148150
}
149151
_, err = t.WriteString(line + "\n")
150152
if err != nil {
151-
f.Close()
152153
return err
153154
}
154155
}
155-
err = scanner.Err()
156-
if err != nil {
157-
return fmt.Errorf("scan: %w", err)
156+
if err = scanner.Err(); err != nil {
157+
return fmt.Errorf("RegeneratePublicKeys scan: %w", err)
158158
}
159-
f.Close()
160159
}
161160
return nil
162161
}

modules/actions/log.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func ReadLogs(ctx context.Context, inStorage bool, filename string, offset, limi
100100
}
101101

102102
if err := scanner.Err(); err != nil {
103-
return nil, fmt.Errorf("scan: %w", err)
103+
return nil, fmt.Errorf("ReadLogs scan: %w", err)
104104
}
105105

106106
return rows, nil

modules/git/commit.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,9 +397,8 @@ func (c *Commit) GetSubModules() (*ObjectCache, error) {
397397
}
398398
}
399399
}
400-
err = scanner.Err()
401-
if err != nil {
402-
return nil, fmt.Errorf("scan: %w", err)
400+
if err = scanner.Err(); err != nil {
401+
return nil, fmt.Errorf("GetSubModules scan: %w", err)
403402
}
404403

405404
return c.submoduleCache, nil

modules/git/repo_stats.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
124124
}
125125
}
126126
}
127-
err = scanner.Err()
128-
if err != nil {
129-
return fmt.Errorf("scan: %w", err)
127+
if err = scanner.Err(); err != nil {
128+
_ = stdoutReader.Close()
129+
return fmt.Errorf("GetCodeActivityStats scan: %w", err)
130130
}
131131
a := make([]*CodeActivityAuthor, 0, len(authors))
132132
for _, v := range authors {

modules/markup/csv/csv.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,8 @@ func (Renderer) fallbackRender(input io.Reader, tmpBlock *bufio.Writer) error {
124124
return err
125125
}
126126
}
127-
err = scan.Err()
128-
if err != nil {
129-
return fmt.Errorf("scan: %w", err)
127+
if err = scan.Err(); err != nil {
128+
return fmt.Errorf("fallbackRender scan: %w", err)
130129
}
131130

132131
_, err = tmpBlock.WriteString("</pre>")

options/locale/locale_en-US.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3626,6 +3626,7 @@ runs.scheduled = Scheduled
36263626
runs.pushed_by = pushed by
36273627
runs.invalid_workflow_helper = Workflow config file is invalid. Please check your config file: %s
36283628
runs.no_matching_online_runner_helper = No matching online runner with label: %s
3629+
runs.no_job_without_needs = The workflow must contain at least one job without dependencies.
36293630
runs.actor = Actor
36303631
runs.status = Status
36313632
runs.actors_no_select = All actors

routers/web/repo/actions/actions.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,13 @@ func List(ctx *context.Context) {
104104
workflows = append(workflows, workflow)
105105
continue
106106
}
107-
// Check whether have matching runner
107+
// The workflow must contain at least one job without "needs". Otherwise, a deadlock will occur and no jobs will be able to run.
108+
hasJobWithoutNeeds := false
109+
// Check whether have matching runner and a job without "needs"
108110
for _, j := range wf.Jobs {
111+
if !hasJobWithoutNeeds && len(j.Needs()) == 0 {
112+
hasJobWithoutNeeds = true
113+
}
109114
runsOnList := j.RunsOn()
110115
for _, ro := range runsOnList {
111116
if strings.Contains(ro, "${{") {
@@ -123,6 +128,9 @@ func List(ctx *context.Context) {
123128
break
124129
}
125130
}
131+
if !hasJobWithoutNeeds {
132+
workflow.ErrMsg = ctx.Locale.TrString("actions.runs.no_job_without_needs")
133+
}
126134
workflows = append(workflows, workflow)
127135
}
128136
}

routers/web/repo/actions/view.go

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -303,12 +303,25 @@ func Rerun(ctx *context_module.Context) {
303303
return
304304
}
305305

306-
if jobIndexStr != "" {
307-
jobs = []*actions_model.ActionRunJob{job}
306+
if jobIndexStr == "" { // rerun all jobs
307+
for _, j := range jobs {
308+
// if the job has needs, it should be set to "blocked" status to wait for other jobs
309+
shouldBlock := len(j.Needs) > 0
310+
if err := rerunJob(ctx, j, shouldBlock); err != nil {
311+
ctx.Error(http.StatusInternalServerError, err.Error())
312+
return
313+
}
314+
}
315+
ctx.JSON(http.StatusOK, struct{}{})
316+
return
308317
}
309318

310-
for _, j := range jobs {
311-
if err := rerunJob(ctx, j); err != nil {
319+
rerunJobs := actions_service.GetAllRerunJobs(job, jobs)
320+
321+
for _, j := range rerunJobs {
322+
// jobs other than the specified one should be set to "blocked" status
323+
shouldBlock := j.JobID != job.JobID
324+
if err := rerunJob(ctx, j, shouldBlock); err != nil {
312325
ctx.Error(http.StatusInternalServerError, err.Error())
313326
return
314327
}
@@ -317,14 +330,17 @@ func Rerun(ctx *context_module.Context) {
317330
ctx.JSON(http.StatusOK, struct{}{})
318331
}
319332

320-
func rerunJob(ctx *context_module.Context, job *actions_model.ActionRunJob) error {
333+
func rerunJob(ctx *context_module.Context, job *actions_model.ActionRunJob, shouldBlock bool) error {
321334
status := job.Status
322335
if !status.IsDone() {
323336
return nil
324337
}
325338

326339
job.TaskID = 0
327340
job.Status = actions_model.StatusWaiting
341+
if shouldBlock {
342+
job.Status = actions_model.StatusBlocked
343+
}
328344
job.Started = 0
329345
job.Stopped = 0
330346

routers/web/repo/compare.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -980,9 +980,8 @@ func getExcerptLines(commit *git.Commit, filePath string, idxLeft, idxRight, chu
980980
}
981981
diffLines = append(diffLines, diffLine)
982982
}
983-
err = scanner.Err()
984-
if err != nil {
985-
return nil, fmt.Errorf("scan: %w", err)
983+
if err = scanner.Err(); err != nil {
984+
return nil, fmt.Errorf("getExcerptLines scan: %w", err)
986985
}
987986
return diffLines, nil
988987
}

routers/web/repo/editor.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,9 @@ func editFilePost(ctx *context.Context, form forms.EditRepoFileForm, isNewFile b
333333
ctx.Error(http.StatusInternalServerError, err.Error())
334334
}
335335
} else if models.IsErrCommitIDDoesNotMatch(err) {
336-
ctx.RenderWithErr(ctx.Tr("repo.editor.commit_id_not_matching", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(ctx.Repo.CommitID)), tplEditFile, &form)
336+
ctx.RenderWithErr(ctx.Tr("repo.editor.commit_id_not_matching"), tplEditFile, &form)
337337
} else if git.IsErrPushOutOfDate(err) {
338-
ctx.RenderWithErr(ctx.Tr("repo.editor.push_out_of_date", ctx.Repo.RepoLink+"/compare/"+util.PathEscapeSegments(form.LastCommit)+"..."+util.PathEscapeSegments(form.NewBranchName)), tplEditFile, &form)
338+
ctx.RenderWithErr(ctx.Tr("repo.editor.push_out_of_date"), tplEditFile, &form)
339339
} else if git.IsErrPushRejected(err) {
340340
errPushRej := err.(*git.ErrPushRejected)
341341
if len(errPushRej.Message) == 0 {

services/actions/rerun.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package actions
5+
6+
import (
7+
actions_model "code.gitea.io/gitea/models/actions"
8+
"code.gitea.io/gitea/modules/container"
9+
)
10+
11+
// GetAllRerunJobs get all jobs that need to be rerun when job should be rerun
12+
func GetAllRerunJobs(job *actions_model.ActionRunJob, allJobs []*actions_model.ActionRunJob) []*actions_model.ActionRunJob {
13+
rerunJobs := []*actions_model.ActionRunJob{job}
14+
rerunJobsIDSet := make(container.Set[string])
15+
rerunJobsIDSet.Add(job.JobID)
16+
17+
for {
18+
found := false
19+
for _, j := range allJobs {
20+
if rerunJobsIDSet.Contains(j.JobID) {
21+
continue
22+
}
23+
for _, need := range j.Needs {
24+
if rerunJobsIDSet.Contains(need) {
25+
found = true
26+
rerunJobs = append(rerunJobs, j)
27+
rerunJobsIDSet.Add(j.JobID)
28+
break
29+
}
30+
}
31+
}
32+
if !found {
33+
break
34+
}
35+
}
36+
37+
return rerunJobs
38+
}

services/actions/rerun_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2024 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package actions
5+
6+
import (
7+
"testing"
8+
9+
actions_model "code.gitea.io/gitea/models/actions"
10+
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func TestGetAllRerunJobs(t *testing.T) {
15+
job1 := &actions_model.ActionRunJob{JobID: "job1"}
16+
job2 := &actions_model.ActionRunJob{JobID: "job2", Needs: []string{"job1"}}
17+
job3 := &actions_model.ActionRunJob{JobID: "job3", Needs: []string{"job2"}}
18+
job4 := &actions_model.ActionRunJob{JobID: "job4", Needs: []string{"job2", "job3"}}
19+
20+
jobs := []*actions_model.ActionRunJob{job1, job2, job3, job4}
21+
22+
testCases := []struct {
23+
job *actions_model.ActionRunJob
24+
rerunJobs []*actions_model.ActionRunJob
25+
}{
26+
{
27+
job1,
28+
[]*actions_model.ActionRunJob{job1, job2, job3, job4},
29+
},
30+
{
31+
job2,
32+
[]*actions_model.ActionRunJob{job2, job3, job4},
33+
},
34+
{
35+
job3,
36+
[]*actions_model.ActionRunJob{job3, job4},
37+
},
38+
{
39+
job4,
40+
[]*actions_model.ActionRunJob{job4},
41+
},
42+
}
43+
44+
for _, tc := range testCases {
45+
rerunJobs := GetAllRerunJobs(tc.job, jobs)
46+
assert.ElementsMatch(t, tc.rerunJobs, rerunJobs)
47+
}
48+
}

services/asymkey/ssh_key_authorized_principals.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ func regeneratePrincipalKeys(ctx context.Context, t io.StringWriter) error {
109109
if err != nil {
110110
return err
111111
}
112+
defer f.Close()
113+
112114
scanner := bufio.NewScanner(f)
113115
for scanner.Scan() {
114116
line := scanner.Text()
@@ -118,15 +120,12 @@ func regeneratePrincipalKeys(ctx context.Context, t io.StringWriter) error {
118120
}
119121
_, err = t.WriteString(line + "\n")
120122
if err != nil {
121-
f.Close()
122123
return err
123124
}
124125
}
125-
err = scanner.Err()
126-
if err != nil {
127-
return fmt.Errorf("scan: %w", err)
126+
if err = scanner.Err(); err != nil {
127+
return fmt.Errorf("regeneratePrincipalKeys scan: %w", err)
128128
}
129-
f.Close()
130129
}
131130
return nil
132131
}

services/doctor/authorizedkeys.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,11 @@ func checkAuthorizedKeys(ctx context.Context, logger log.Logger, autofix bool) e
5151
}
5252
linesInAuthorizedKeys.Add(line)
5353
}
54-
err = scanner.Err()
55-
if err != nil {
54+
if err = scanner.Err(); err != nil {
5655
return fmt.Errorf("scan: %w", err)
5756
}
58-
f.Close()
57+
// although there is a "defer close" above, here close explicitly before the generating, because it needs to open the file for writing again
58+
_ = f.Close()
5959

6060
// now we regenerate and check if there are any lines missing
6161
regenerated := &bytes.Buffer{}

templates/repo/issue/view_content/pull.tmpl

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -374,17 +374,15 @@
374374
*/}}
375375
{{if and $.StillCanManualMerge (not $showGeneralMergeForm)}}
376376
<div class="divider"></div>
377-
<div class="ui form">
378-
<form action="{{.Link}}/merge" method="post">
379-
{{.CsrfTokenHtml}}
380-
<div class="field">
381-
<input type="text" name="merge_commit_id" placeholder="{{ctx.Locale.Tr "repo.pulls.merge_commit_id"}}">
382-
</div>
383-
<button class="ui red button" type="submit" name="do" value="manually-merged">
384-
{{ctx.Locale.Tr "repo.pulls.merge_manually"}}
385-
</button>
386-
</form>
387-
</div>
377+
<form class="ui form form-fetch-action" action="{{.Link}}/merge" method="post">{{/* another similar form is in PullRequestMergeForm.vue*/}}
378+
{{.CsrfTokenHtml}}
379+
<div class="field">
380+
<input type="text" name="merge_commit_id" placeholder="{{ctx.Locale.Tr "repo.pulls.merge_commit_id"}}">
381+
</div>
382+
<button class="ui red button" type="submit" name="do" value="manually-merged">
383+
{{ctx.Locale.Tr "repo.pulls.merge_manually"}}
384+
</button>
385+
</form>
388386
{{end}}
389387

390388
{{if and .Issue.PullRequest.HeadRepo (not .Issue.PullRequest.HasMerged) (not .Issue.IsClosed)}}

templates/status/404.tmpl

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
{{template "base/head" .}}
2-
<div role="main" aria-label="{{.Title}}" class="page-content ui container center tw-w-screen {{if .IsRepo}}repository{{end}}">
2+
<div role="main" aria-label="{{.Title}}" class="page-content {{if .IsRepo}}repository{{end}}">
33
{{if .IsRepo}}{{template "repo/header" .}}{{end}}
4-
<div class="ui container center">
5-
<p style="margin-top: 100px"><img src="{{AssetUrlPrefix}}/img/404.png" alt="404"></p>
4+
<div class="ui container tw-text-center">
5+
<img class="tw-max-w-[80vw] tw-py-16" src="{{AssetUrlPrefix}}/img/404.png" alt="404">
66
<p>{{if .NotFoundPrompt}}{{.NotFoundPrompt}}{{else}}{{ctx.Locale.Tr "error404"}}{{end}}</p>
7-
{{if .NotFoundGoBackURL}}<a class="ui button green" href="{{.NotFoundGoBackURL}}">{{ctx.Locale.Tr "go_back"}}</a>{{end}}
8-
9-
<div class="divider"></div>
10-
<br>
11-
{{if .ShowFooterVersion}}<p>{{ctx.Locale.Tr "admin.config.app_ver"}}: {{AppVer}}</p>{{end}}
7+
{{if .NotFoundGoBackURL}}<a class="ui button" href="{{.NotFoundGoBackURL}}">{{ctx.Locale.Tr "go_back"}}</a>{{end}}
128
</div>
139
</div>
1410
{{template "base/footer" .}}

web_src/js/components/PullRequestMergeForm.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ export default {
9494
<!-- eslint-disable-next-line vue/no-v-html -->
9595
<div v-if="mergeForm.hasPendingPullRequestMerge" v-html="mergeForm.hasPendingPullRequestMergeTip" class="ui info message"/>
9696
97+
<!-- another similar form is in pull.tmpl (manual merge)-->
9798
<form class="ui form form-fetch-action" v-if="showActionForm" :action="mergeForm.baseLink+'/merge'" method="post">
9899
<input type="hidden" name="_csrf" :value="csrfToken">
99100
<input type="hidden" name="head_commit_id" v-model="mergeForm.pullHeadCommitID">

0 commit comments

Comments
 (0)