chore: initialize Gitea v1.27.2 fork
giteabot backport / giteabot (push) Canceled after 0s
giteabot / giteabot (push) Canceled after 0s
release-nightly / nightly-binary (push) Canceled after 0s
release-nightly / nightly-container (push) Canceled after 0s
cache-seeder / gobuild (push) Canceled after 0s
cache-seeder / lint (bindata, lint-backend) (push) Canceled after 0s
release-nightly-snapcraft / build-and-publish (push) Canceled after 0s
giteabot backport / giteabot (push) Canceled after 0s
giteabot / giteabot (push) Canceled after 0s
release-nightly / nightly-binary (push) Canceled after 0s
release-nightly / nightly-container (push) Canceled after 0s
cache-seeder / gobuild (push) Canceled after 0s
cache-seeder / lint (bindata, lint-backend) (push) Canceled after 0s
release-nightly-snapcraft / build-and-publish (push) Canceled after 0s
Includes direct password setup links in registration emails. Assisted-by: Codex:GPT-5
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
// Copyright 2025 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package actions
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
actions_model "gitea.dev/models/actions"
|
||||
repo_model "gitea.dev/models/repo"
|
||||
api "gitea.dev/modules/structs"
|
||||
"gitea.dev/modules/timeutil"
|
||||
"gitea.dev/modules/translation"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestViewPullRequestFromRun(t *testing.T) {
|
||||
repo := &repo_model.Repository{ID: 1, OwnerName: "owner", Name: "repo"}
|
||||
|
||||
t.Run("pull ref", func(t *testing.T) {
|
||||
run := &actions_model.ActionRun{Repo: repo, Ref: "refs/pull/123/head"}
|
||||
assert.Equal(t, &ViewPullRequest{Index: "#123", Link: "/owner/repo/pulls/123"}, viewPullRequestFromRun(t.Context(), run, nil))
|
||||
})
|
||||
|
||||
t.Run("pull request event payload", func(t *testing.T) {
|
||||
// a non-pull ref forces the payload branch instead of the ref branch
|
||||
run := &actions_model.ActionRun{Repo: repo, Ref: "refs/heads/feature"}
|
||||
payload := &api.PullRequestPayload{Index: 42}
|
||||
assert.Equal(t, &ViewPullRequest{Index: "#42", Link: "/owner/repo/pulls/42"}, viewPullRequestFromRun(t.Context(), run, payload))
|
||||
})
|
||||
|
||||
t.Run("nil repo", func(t *testing.T) {
|
||||
run := &actions_model.ActionRun{Ref: "refs/pull/1/head"}
|
||||
assert.Nil(t, viewPullRequestFromRun(t.Context(), run, nil))
|
||||
})
|
||||
}
|
||||
|
||||
func TestViewSummaryBranchFromRun(t *testing.T) {
|
||||
repo := &repo_model.Repository{ID: 1, OwnerName: "owner", Name: "repo"}
|
||||
|
||||
t.Run("pull request event same repo", func(t *testing.T) {
|
||||
run := &actions_model.ActionRun{Repo: repo, Ref: "refs/pull/7/head"}
|
||||
payload := &api.PullRequestPayload{
|
||||
PullRequest: &api.PullRequest{Head: &api.PRBranchInfo{
|
||||
Name: "feature",
|
||||
Ref: "refs/heads/feature",
|
||||
RepoID: 1,
|
||||
Repository: &api.Repository{Link: "/owner/repo"},
|
||||
}},
|
||||
}
|
||||
assert.Equal(t, ViewBranch{Name: "feature", Link: "/owner/repo/src/branch/feature"}, viewSummaryBranchFromRun(t.Context(), run, payload))
|
||||
})
|
||||
|
||||
t.Run("pull request event from fork prefixes owner", func(t *testing.T) {
|
||||
run := &actions_model.ActionRun{Repo: repo, Ref: "refs/pull/7/head"}
|
||||
payload := &api.PullRequestPayload{
|
||||
PullRequest: &api.PullRequest{Head: &api.PRBranchInfo{
|
||||
Name: "feature",
|
||||
Ref: "refs/heads/feature",
|
||||
RepoID: 2,
|
||||
Repository: &api.Repository{
|
||||
Link: "/forkowner/repo",
|
||||
Owner: &api.User{UserName: "forkowner"},
|
||||
},
|
||||
}},
|
||||
}
|
||||
assert.Equal(t, ViewBranch{Name: "forkowner:feature", Link: "/forkowner/repo/src/branch/feature"}, viewSummaryBranchFromRun(t.Context(), run, payload))
|
||||
})
|
||||
|
||||
t.Run("push to tag does not query branch", func(t *testing.T) {
|
||||
// a tag ref is not a branch, so no GetBranch DB lookup happens
|
||||
run := &actions_model.ActionRun{Repo: repo, Ref: "refs/tags/v1.0.0"}
|
||||
assert.Equal(t, ViewBranch{Name: "v1.0.0", Link: "/owner/repo/src/tag/v1.0.0"}, viewSummaryBranchFromRun(t.Context(), run, nil))
|
||||
})
|
||||
}
|
||||
|
||||
func TestConvertToViewModel(t *testing.T) {
|
||||
task := &actions_model.ActionTask{
|
||||
Status: actions_model.StatusSuccess,
|
||||
Steps: []*actions_model.ActionTaskStep{
|
||||
{Name: "Run step-name", Index: 0, Status: actions_model.StatusSuccess, LogLength: 1, Started: timeutil.TimeStamp(1), Stopped: timeutil.TimeStamp(5)},
|
||||
},
|
||||
Stopped: timeutil.TimeStamp(20),
|
||||
}
|
||||
|
||||
viewJobSteps, _, err := convertToViewModel(t.Context(), translation.MockLocale{}, nil, task)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedViewJobs := []*ViewJobStep{
|
||||
{
|
||||
Summary: "Set up job",
|
||||
Duration: "0s",
|
||||
Status: "success",
|
||||
},
|
||||
{
|
||||
Summary: "Run step-name",
|
||||
Duration: "4s",
|
||||
Status: "success",
|
||||
},
|
||||
{
|
||||
Summary: "Complete job",
|
||||
Duration: "15s",
|
||||
Status: "success",
|
||||
},
|
||||
}
|
||||
assert.Equal(t, expectedViewJobs, viewJobSteps)
|
||||
}
|
||||
|
||||
func TestConvertToViewModelCancellingTaskDoesNotRenderRunningSteps(t *testing.T) {
|
||||
task := &actions_model.ActionTask{
|
||||
Status: actions_model.StatusCancelling,
|
||||
Steps: []*actions_model.ActionTaskStep{
|
||||
{Name: "Run step-name", Index: 0, Status: actions_model.StatusRunning, LogLength: 1},
|
||||
},
|
||||
}
|
||||
|
||||
viewJobSteps, _, err := convertToViewModel(t.Context(), translation.MockLocale{}, nil, task)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedViewJobs := []*ViewJobStep{
|
||||
{
|
||||
Summary: "Set up job",
|
||||
Duration: "0s",
|
||||
Status: "success",
|
||||
},
|
||||
{
|
||||
Summary: "Run step-name",
|
||||
Duration: "0s",
|
||||
Status: "cancelling",
|
||||
},
|
||||
{
|
||||
Summary: "Complete job",
|
||||
Duration: "0s",
|
||||
Status: "waiting",
|
||||
},
|
||||
}
|
||||
assert.Equal(t, expectedViewJobs, viewJobSteps)
|
||||
}
|
||||
|
||||
func TestPendingNeeds(t *testing.T) {
|
||||
current := &actions_model.ActionRunJob{JobID: "deploy", Needs: []string{"build", "test"}}
|
||||
jobs := []*actions_model.ActionRunJob{
|
||||
current,
|
||||
{JobID: "build", Status: actions_model.StatusSuccess},
|
||||
{JobID: "test", Status: actions_model.StatusRunning},
|
||||
}
|
||||
// "test" is not done yet, "build" succeeded, so only "test" blocks.
|
||||
assert.Equal(t, []string{"test"}, pendingNeeds(current, jobs))
|
||||
|
||||
t.Run("all needs done", func(t *testing.T) {
|
||||
done := []*actions_model.ActionRunJob{
|
||||
current,
|
||||
{JobID: "build", Status: actions_model.StatusSuccess},
|
||||
{JobID: "test", Status: actions_model.StatusSkipped},
|
||||
}
|
||||
assert.Empty(t, pendingNeeds(current, done))
|
||||
})
|
||||
|
||||
t.Run("matrix expansion all required", func(t *testing.T) {
|
||||
matrix := []*actions_model.ActionRunJob{
|
||||
current,
|
||||
{JobID: "build", Status: actions_model.StatusSuccess},
|
||||
{JobID: "build", Status: actions_model.StatusRunning},
|
||||
{JobID: "test", Status: actions_model.StatusSuccess},
|
||||
}
|
||||
assert.Equal(t, []string{"build"}, pendingNeeds(current, matrix))
|
||||
})
|
||||
|
||||
t.Run("unresolved need treated as pending", func(t *testing.T) {
|
||||
missing := []*actions_model.ActionRunJob{current}
|
||||
assert.Equal(t, []string{"build", "test"}, pendingNeeds(current, missing))
|
||||
})
|
||||
|
||||
t.Run("parent job scope", func(t *testing.T) {
|
||||
// a same-named job under a different parent must not satisfy the need
|
||||
scoped := &actions_model.ActionRunJob{JobID: "deploy", Needs: []string{"build"}, ParentJobID: 5}
|
||||
jobs := []*actions_model.ActionRunJob{
|
||||
scoped,
|
||||
{JobID: "build", Status: actions_model.StatusSuccess, ParentJobID: 0},
|
||||
}
|
||||
assert.Equal(t, []string{"build"}, pendingNeeds(scoped, jobs))
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user