Hide PR tab if PRs are disabled (#3004)

Closes https://github.com/woodpecker-ci/woodpecker/issues/2988
This commit is contained in:
qwerty287 2023-12-24 10:04:18 +01:00 committed by GitHub
parent 030db4e110
commit 9d9bcbf363
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 37 additions and 13 deletions

View file

@ -4135,6 +4135,9 @@ const docTemplate = `{
"owner": {
"type": "string"
},
"pr_enabled": {
"type": "boolean"
},
"private": {
"type": "boolean"
},

View file

@ -15,8 +15,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.31.0
// protoc v4.24.4
// protoc-gen-go v1.32.0
// protoc v4.25.1
// source: woodpecker.proto
package proto
@ -1221,11 +1221,11 @@ var file_woodpecker_proto_rawDesc = []byte{
0x68, 0x12, 0x31, 0x0a, 0x04, 0x41, 0x75, 0x74, 0x68, 0x12, 0x12, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x00, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x6f, 0x2e, 0x77, 0x6f, 0x6f, 0x64, 0x70,
0x73, 0x65, 0x22, 0x00, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x6f, 0x2e, 0x77, 0x6f, 0x6f, 0x64, 0x70,
0x65, 0x63, 0x6b, 0x65, 0x72, 0x2d, 0x63, 0x69, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x77, 0x6f, 0x6f,
0x64, 0x70, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x2f, 0x70, 0x69, 0x70, 0x65, 0x6c, 0x69, 0x6e, 0x65,
0x2f, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
0x64, 0x70, 0x65, 0x63, 0x6b, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x69, 0x70, 0x65, 0x6c,
0x69, 0x6e, 0x65, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View file

@ -16,7 +16,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v4.24.4
// - protoc v4.25.1
// source: woodpecker.proto
package proto

View file

@ -367,7 +367,7 @@ func (c *config) PullRequests(ctx context.Context, u *model.User, r *model.Repo,
if err != nil {
return nil, err
}
result := []*model.PullRequest{}
var result []*model.PullRequest
for _, pullRequest := range pullRequests {
result = append(result, &model.PullRequest{
Index: model.ForgeRemoteID(strconv.Itoa(int(pullRequest.ID))),

View file

@ -62,6 +62,7 @@ func convertRepo(from *internal.Repo, perm *internal.RepoPerm) *model.Repo {
SCMKind: model.SCMKind(from.Scm),
Branch: from.Mainbranch.Name,
Perm: convertPerm(perm),
PREnabled: true,
}
if repo.SCMKind == model.RepoHg {
repo.Branch = "default"

View file

@ -49,6 +49,7 @@ func toRepo(from *gitea.Repository) *model.Repo {
CloneSSH: from.SSHURL,
Branch: from.DefaultBranch,
Perm: toPerm(from.Permissions),
PREnabled: from.HasPullRequests,
}
}

View file

@ -95,6 +95,7 @@ func convertRepo(from *github.Repository) *model.Repo {
Avatar: from.GetOwner().GetAvatarURL(),
Perm: convertPerm(from.GetPermissions()),
SCMKind: model.RepoGit,
PREnabled: true,
}
return repo
}
@ -152,6 +153,7 @@ func convertRepoHook(eventRepo *github.PushEventRepository) *model.Repo {
CloneSSH: eventRepo.GetSSHURL(),
Branch: eventRepo.GetDefaultBranch(),
SCMKind: model.RepoGit,
PREnabled: true,
}
if repo.FullName == "" {
repo.FullName = repo.Owner + "/" + repo.Name

View file

@ -52,6 +52,7 @@ func (g *GitLab) convertGitLabRepo(_repo *gitlab.Project) (*model.Repo, error) {
Push: isWrite(_repo),
Admin: isAdmin(_repo),
},
PREnabled: _repo.MergeRequestsEnabled,
}
if len(repo.Avatar) != 0 && !strings.HasPrefix(repo.Avatar, "http") {

View file

@ -1,4 +1,4 @@
// Code generated by mockery v2.38.0. DO NOT EDIT.
// Code generated by mockery v2.39.1. DO NOT EDIT.
package mocks

View file

@ -36,6 +36,7 @@ type Repo struct {
CloneSSH string `json:"clone_url_ssh" xorm:"varchar(1000) 'repo_clone_ssh'"`
Branch string `json:"default_branch,omitempty" xorm:"varchar(500) 'repo_branch'"`
SCMKind SCMKind `json:"scm,omitempty" xorm:"varchar(50) 'repo_scm'"`
PREnabled bool `json:"pr_enabled" xorm:"DEFAULT TRUE 'repo_pr_enabled'"`
Timeout int64 `json:"timeout,omitempty" xorm:"repo_timeout"`
Visibility RepoVisibility `json:"visibility" xorm:"varchar(10) 'repo_visibility'"`
IsSCMPrivate bool `json:"private" xorm:"repo_private"`
@ -66,7 +67,7 @@ func (r *Repo) ResetVisibility() {
func ParseRepo(str string) (user, repo string, err error) {
parts := strings.Split(str, "/")
if len(parts) != 2 {
err = fmt.Errorf("Error: Invalid or missing repository. eg octocat/hello-world")
err = fmt.Errorf("error: Invalid or missing repository. eg octocat/hello-world")
return
}
user = parts[0]
@ -85,6 +86,7 @@ func (r *Repo) Update(from *Repo) {
r.Avatar = from.Avatar
r.ForgeURL = from.ForgeURL
r.SCMKind = from.SCMKind
r.PREnabled = from.PREnabled
if len(from.Clone) > 0 {
r.Clone = from.Clone
}

View file

@ -1,4 +1,4 @@
// Code generated by mockery v2.38.0. DO NOT EDIT.
// Code generated by mockery v2.39.1. DO NOT EDIT.
package mocks

5
web/components.d.ts vendored
View file

@ -62,14 +62,19 @@ declare module 'vue' {
IMdiBitbucket: typeof import('~icons/mdi/bitbucket')['default']
IMdiChevronRight: typeof import('~icons/mdi/chevron-right')['default']
IMdiClockTimeEightOutline: typeof import('~icons/mdi/clock-time-eight-outline')['default']
IMdiCloseThick: typeof import('~icons/mdi/close-thick')['default']
IMdiErrorOutline: typeof import('~icons/mdi/error-outline')['default']
IMdiFormatListBulleted: typeof import('~icons/mdi/format-list-bulleted')['default']
IMdiGestureTap: typeof import('~icons/mdi/gesture-tap')['default']
IMdiGithub: typeof import('~icons/mdi/github')['default']
IMdiLoading: typeof import('~icons/mdi/loading')['default']
IMdiPlay: typeof import('~icons/mdi/play')['default']
IMdiRadioboxBlank: typeof import('~icons/mdi/radiobox-blank')['default']
IMdiRadioboxIndeterminateVariant: typeof import('~icons/mdi/radiobox-indeterminate-variant')['default']
IMdiSourceBranch: typeof import('~icons/mdi/source-branch')['default']
IMdisourceCommit: typeof import('~icons/mdi/source-commit')['default']
IMdiSourcePull: typeof import('~icons/mdi/source-pull')['default']
IMdiStop: typeof import('~icons/mdi/stop')['default']
IMdiSync: typeof import('~icons/mdi/sync')['default']
IMdiTagOutline: typeof import('~icons/mdi/tag-outline')['default']
InputField: typeof import('./src/components/form/InputField.vue')['default']

View file

@ -10,9 +10,12 @@ export type Repo = {
forge_remote_id: string;
// The source control management being used.
// Currently this is either 'git' or 'hg' (Mercurial).
// Currently, this is either 'git' or 'hg' (Mercurial).
scm: string;
// Whether the forge repo has PRs enabled.
pr_enabled: boolean;
// The id of the organization that owns the repository.
org_id: number;

View file

@ -20,6 +20,9 @@ const repoPermissions = inject<Ref<RepoPermissions>>('repo-permissions');
if (!repo || !repoPermissions) {
throw new Error('Unexpected: "repo" and "repoPermissions" should be provided at this place');
}
if (!repo.value.pr_enabled || !repo.value.allow_pr) {
throw new Error('Unexpected: pull requests are disabled for repo');
}
const allPipelines = inject<Ref<Pipeline[]>>('pipelines');
const pipelines = computed(

View file

@ -29,6 +29,9 @@ const repo = inject<Ref<Repo>>('repo');
if (!repo) {
throw new Error('Unexpected: "repo" should be provided at this place');
}
if (!repo.value.pr_enabled || !repo.value.allow_pr) {
throw new Error('Unexpected: pull requests are disabled for repo');
}
async function loadPullRequests(page: number): Promise<PullRequest[]> {
if (!repo) {

View file

@ -37,7 +37,7 @@
<Tab id="activity" :title="$t('repo.activity')" />
<Tab id="branches" :title="$t('repo.branches')" />
<Tab id="pull_requests" :title="$t('repo.pull_requests')" />
<Tab v-if="repo.pr_enabled && repo.allow_pr" id="pull_requests" :title="$t('repo.pull_requests')" />
<router-view />
</Scaffold>