mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2025-06-26 07:24:01 +00:00
Drop Gogs private mode (#1726)
You should use `WOODPECKER_AUTHENTICATE_PUBLIC_REPOS` instead if repos sent from forge as public should be authenticated
This commit is contained in:
parent
0f9188597e
commit
54d4ec04c0
@ -337,11 +337,6 @@ var flags = []cli.Flag{
|
|||||||
Usage: "gogs service account password",
|
Usage: "gogs service account password",
|
||||||
FilePath: os.Getenv("WOODPECKER_GOGS_GIT_PASSWORD_FILE"),
|
FilePath: os.Getenv("WOODPECKER_GOGS_GIT_PASSWORD_FILE"),
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
|
||||||
EnvVars: []string{"WOODPECKER_GOGS_PRIVATE_MODE"},
|
|
||||||
Name: "gogs-private-mode",
|
|
||||||
Usage: "gogs private mode enabled",
|
|
||||||
},
|
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
EnvVars: []string{"WOODPECKER_GOGS_SKIP_VERIFY"},
|
EnvVars: []string{"WOODPECKER_GOGS_SKIP_VERIFY"},
|
||||||
Name: "gogs-skip-verify",
|
Name: "gogs-skip-verify",
|
||||||
|
@ -218,11 +218,10 @@ func setupBitbucket(c *cli.Context) (forge.Forge, error) {
|
|||||||
// helper function to setup the Gogs forge from the CLI arguments.
|
// helper function to setup the Gogs forge from the CLI arguments.
|
||||||
func setupGogs(c *cli.Context) (forge.Forge, error) {
|
func setupGogs(c *cli.Context) (forge.Forge, error) {
|
||||||
opts := gogs.Opts{
|
opts := gogs.Opts{
|
||||||
URL: c.String("gogs-server"),
|
URL: c.String("gogs-server"),
|
||||||
Username: c.String("gogs-git-username"),
|
Username: c.String("gogs-git-username"),
|
||||||
Password: c.String("gogs-git-password"),
|
Password: c.String("gogs-git-password"),
|
||||||
PrivateMode: c.Bool("gogs-private-mode"),
|
SkipVerify: c.Bool("gogs-skip-verify"),
|
||||||
SkipVerify: c.Bool("gogs-skip-verify"),
|
|
||||||
}
|
}
|
||||||
log.Trace().Msgf("Forge (gogs) opts: %#v", opts)
|
log.Trace().Msgf("Forge (gogs) opts: %#v", opts)
|
||||||
return gogs.New(opts)
|
return gogs.New(opts)
|
||||||
|
@ -34,11 +34,6 @@ The password is used to authenticate and clone all private repositories.
|
|||||||
|
|
||||||
Read the value for `WOODPECKER_GOGS_GIT_PASSWORD` from the specified filepath
|
Read the value for `WOODPECKER_GOGS_GIT_PASSWORD` from the specified filepath
|
||||||
|
|
||||||
### `WOODPECKER_GOGS_PRIVATE_MODE`
|
|
||||||
> Default: `false`
|
|
||||||
|
|
||||||
TODO
|
|
||||||
|
|
||||||
### `WOODPECKER_GOGS_SKIP_VERIFY`
|
### `WOODPECKER_GOGS_SKIP_VERIFY`
|
||||||
> Default: `false`
|
> Default: `false`
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ Some versions need some changes to the server configuration or the pipeline conf
|
|||||||
- The pipelines are now also read from `.yaml` files, the new default order is `.woodpecker/*.yml` and `.woodpecker/*.yaml` (without any prioritization) -> `.woodpecker.yml` -> `.woodpecker.yaml` -> `.drone.yml`
|
- The pipelines are now also read from `.yaml` files, the new default order is `.woodpecker/*.yml` and `.woodpecker/*.yaml` (without any prioritization) -> `.woodpecker.yml` -> `.woodpecker.yaml` -> `.drone.yml`
|
||||||
- Dropped support for [Coding](https://coding.net/).
|
- Dropped support for [Coding](https://coding.net/).
|
||||||
- `/api/queue/resume` & `/api/queue/pause` endpoint methods were changed from `GET` to `POST`
|
- `/api/queue/resume` & `/api/queue/pause` endpoint methods were changed from `GET` to `POST`
|
||||||
|
- Dropped `WOODPECKER_GOGS_PRIVATE_MODE` (use `WOODPECKER_AUTHENTICATE_PUBLIC_REPOS`)
|
||||||
|
|
||||||
## 0.15.0
|
## 0.15.0
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ func PatchRepo(c *gin.Context) {
|
|||||||
if in.Visibility != nil {
|
if in.Visibility != nil {
|
||||||
switch *in.Visibility {
|
switch *in.Visibility {
|
||||||
case string(model.VisibilityInternal), string(model.VisibilityPrivate), string(model.VisibilityPublic):
|
case string(model.VisibilityInternal), string(model.VisibilityPrivate), string(model.VisibilityPublic):
|
||||||
repo.Visibility = model.RepoVisibly(*in.Visibility)
|
repo.Visibility = model.RepoVisibility(*in.Visibility)
|
||||||
default:
|
default:
|
||||||
c.String(http.StatusBadRequest, "Invalid visibility type")
|
c.String(http.StatusBadRequest, "Invalid visibility type")
|
||||||
return
|
return
|
||||||
|
@ -44,7 +44,7 @@ func (g *GitLab) convertGitLabRepo(_repo *gitlab.Project) (*model.Repo, error) {
|
|||||||
Link: _repo.WebURL,
|
Link: _repo.WebURL,
|
||||||
Clone: _repo.HTTPURLToRepo,
|
Clone: _repo.HTTPURLToRepo,
|
||||||
Branch: _repo.DefaultBranch,
|
Branch: _repo.DefaultBranch,
|
||||||
Visibility: model.RepoVisibly(_repo.Visibility),
|
Visibility: model.RepoVisibility(_repo.Visibility),
|
||||||
IsSCMPrivate: !_repo.Public,
|
IsSCMPrivate: !_repo.Public,
|
||||||
Perm: &model.Perm{
|
Perm: &model.Perm{
|
||||||
Pull: isRead(_repo),
|
Pull: isRead(_repo),
|
||||||
|
@ -18,7 +18,6 @@ package gogs
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"fmt"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -34,19 +33,17 @@ import (
|
|||||||
|
|
||||||
// Opts defines configuration options.
|
// Opts defines configuration options.
|
||||||
type Opts struct {
|
type Opts struct {
|
||||||
URL string // Gogs server url.
|
URL string // Gogs server url.
|
||||||
Username string // Optional machine account username.
|
Username string // Optional machine account username.
|
||||||
Password string // Optional machine account password.
|
Password string // Optional machine account password.
|
||||||
PrivateMode bool // Gogs is running in private mode.
|
SkipVerify bool // Skip ssl verification.
|
||||||
SkipVerify bool // Skip ssl verification.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
URL string
|
URL string
|
||||||
Username string
|
Username string
|
||||||
Password string
|
Password string
|
||||||
PrivateMode bool
|
SkipVerify bool
|
||||||
SkipVerify bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// New returns a Forge implementation that integrates with Gogs, an open
|
// New returns a Forge implementation that integrates with Gogs, an open
|
||||||
@ -61,11 +58,10 @@ func New(opts Opts) (forge.Forge, error) {
|
|||||||
u.Host = host
|
u.Host = host
|
||||||
}
|
}
|
||||||
return &client{
|
return &client{
|
||||||
URL: opts.URL,
|
URL: opts.URL,
|
||||||
Username: opts.Username,
|
Username: opts.Username,
|
||||||
Password: opts.Password,
|
Password: opts.Password,
|
||||||
PrivateMode: opts.PrivateMode,
|
SkipVerify: opts.SkipVerify,
|
||||||
SkipVerify: opts.SkipVerify,
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +127,7 @@ func (c *client) Login(_ context.Context, res http.ResponseWriter, req *http.Req
|
|||||||
|
|
||||||
// Auth is not supported by the Gogs driver.
|
// Auth is not supported by the Gogs driver.
|
||||||
func (c *client) Auth(_ context.Context, _, _ string) (string, error) {
|
func (c *client) Auth(_ context.Context, _, _ string) (string, error) {
|
||||||
return "", fmt.Errorf("Not Implemented")
|
return "", forge_types.ErrNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
// Teams is not supported by the Gogs driver.
|
// Teams is not supported by the Gogs driver.
|
||||||
@ -156,7 +152,7 @@ func (c *client) Repo(_ context.Context, u *model.User, _ model.ForgeRemoteID, o
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return toRepo(repo, c.PrivateMode), nil
|
return toRepo(repo), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repos returns a list of all repositories for the Gogs account, including
|
// Repos returns a list of all repositories for the Gogs account, including
|
||||||
@ -171,7 +167,7 @@ func (c *client) Repos(_ context.Context, u *model.User) ([]*model.Repo, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, repo := range all {
|
for _, repo := range all {
|
||||||
repos = append(repos, toRepo(repo, c.PrivateMode))
|
repos = append(repos, toRepo(repo))
|
||||||
}
|
}
|
||||||
return repos, err
|
return repos, err
|
||||||
}
|
}
|
||||||
@ -296,7 +292,7 @@ func (c *client) PullRequests(_ context.Context, _ *model.User, _ *model.Repo, _
|
|||||||
// Hook parses the incoming Gogs hook and returns the Repository and Pipeline
|
// Hook parses the incoming Gogs hook and returns the Repository and Pipeline
|
||||||
// details. If the hook is unsupported nil values are returned.
|
// details. If the hook is unsupported nil values are returned.
|
||||||
func (c *client) Hook(_ context.Context, r *http.Request) (*model.Repo, *model.Pipeline, error) {
|
func (c *client) Hook(_ context.Context, r *http.Request) (*model.Repo, *model.Pipeline, error) {
|
||||||
return parseHook(r, c.PrivateMode)
|
return parseHook(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OrgMembership returns if user is member of organization and if user
|
// OrgMembership returns if user is member of organization and if user
|
||||||
|
@ -46,17 +46,15 @@ func Test_gogs(t *testing.T) {
|
|||||||
g.Describe("Creating a forge", func() {
|
g.Describe("Creating a forge", func() {
|
||||||
g.It("Should return client with specified options", func() {
|
g.It("Should return client with specified options", func() {
|
||||||
forge, _ := New(Opts{
|
forge, _ := New(Opts{
|
||||||
URL: "http://localhost:8080",
|
URL: "http://localhost:8080",
|
||||||
Username: "someuser",
|
Username: "someuser",
|
||||||
Password: "password",
|
Password: "password",
|
||||||
SkipVerify: true,
|
SkipVerify: true,
|
||||||
PrivateMode: true,
|
|
||||||
})
|
})
|
||||||
g.Assert(forge.(*client).URL).Equal("http://localhost:8080")
|
g.Assert(forge.(*client).URL).Equal("http://localhost:8080")
|
||||||
g.Assert(forge.(*client).Username).Equal("someuser")
|
g.Assert(forge.(*client).Username).Equal("someuser")
|
||||||
g.Assert(forge.(*client).Password).Equal("password")
|
g.Assert(forge.(*client).Password).Equal("password")
|
||||||
g.Assert(forge.(*client).SkipVerify).Equal(true)
|
g.Assert(forge.(*client).SkipVerify).Equal(true)
|
||||||
g.Assert(forge.(*client).PrivateMode).Equal(true)
|
|
||||||
})
|
})
|
||||||
g.It("Should handle malformed url", func() {
|
g.It("Should handle malformed url", func() {
|
||||||
_, err := New(Opts{URL: "%gh&%ij"})
|
_, err := New(Opts{URL: "%gh&%ij"})
|
||||||
|
@ -29,7 +29,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// helper function that converts a Gogs repository to a Woodpecker repository.
|
// helper function that converts a Gogs repository to a Woodpecker repository.
|
||||||
func toRepo(from *gogs.Repository, privateMode bool) *model.Repo {
|
func toRepo(from *gogs.Repository) *model.Repo {
|
||||||
name := strings.Split(from.FullName, "/")[1]
|
name := strings.Split(from.FullName, "/")[1]
|
||||||
avatar := expandAvatar(
|
avatar := expandAvatar(
|
||||||
from.HTMLURL,
|
from.HTMLURL,
|
||||||
@ -43,7 +43,7 @@ func toRepo(from *gogs.Repository, privateMode bool) *model.Repo {
|
|||||||
FullName: from.FullName,
|
FullName: from.FullName,
|
||||||
Avatar: avatar,
|
Avatar: avatar,
|
||||||
Link: from.HTMLURL,
|
Link: from.HTMLURL,
|
||||||
IsSCMPrivate: from.Private || privateMode,
|
IsSCMPrivate: from.Private,
|
||||||
Clone: from.CloneURL,
|
Clone: from.CloneURL,
|
||||||
Branch: from.DefaultBranch,
|
Branch: from.DefaultBranch,
|
||||||
Perm: toPerm(from.Permissions),
|
Perm: toPerm(from.Permissions),
|
||||||
|
@ -107,7 +107,7 @@ func Test_parse(t *testing.T) {
|
|||||||
g.It("Should return a Repo struct from a push hook", func() {
|
g.It("Should return a Repo struct from a push hook", func() {
|
||||||
buf := bytes.NewBufferString(fixtures.HookPush)
|
buf := bytes.NewBufferString(fixtures.HookPush)
|
||||||
hook, _ := parsePush(buf)
|
hook, _ := parsePush(buf)
|
||||||
repo := toRepo(hook.Repo, false)
|
repo := toRepo(hook.Repo)
|
||||||
g.Assert(repo.Name).Equal(hook.Repo.Name)
|
g.Assert(repo.Name).Equal(hook.Repo.Name)
|
||||||
g.Assert(repo.Owner).Equal(hook.Repo.Owner.UserName)
|
g.Assert(repo.Owner).Equal(hook.Repo.Owner.UserName)
|
||||||
g.Assert(repo.FullName).Equal("gordon/hello-world")
|
g.Assert(repo.FullName).Equal("gordon/hello-world")
|
||||||
@ -131,7 +131,7 @@ func Test_parse(t *testing.T) {
|
|||||||
g.It("Should return a Repo struct from a pull_request hook", func() {
|
g.It("Should return a Repo struct from a pull_request hook", func() {
|
||||||
buf := bytes.NewBufferString(fixtures.HookPullRequest)
|
buf := bytes.NewBufferString(fixtures.HookPullRequest)
|
||||||
hook, _ := parsePullRequest(buf)
|
hook, _ := parsePullRequest(buf)
|
||||||
repo := toRepo(hook.Repo, false)
|
repo := toRepo(hook.Repo)
|
||||||
g.Assert(repo.Name).Equal(hook.Repo.Name)
|
g.Assert(repo.Name).Equal(hook.Repo.Name)
|
||||||
g.Assert(repo.Owner).Equal(hook.Repo.Owner.UserName)
|
g.Assert(repo.Owner).Equal(hook.Repo.Owner.UserName)
|
||||||
g.Assert(repo.FullName).Equal("gordon/hello-world")
|
g.Assert(repo.FullName).Equal("gordon/hello-world")
|
||||||
@ -176,7 +176,7 @@ func Test_parse(t *testing.T) {
|
|||||||
DefaultBranch: "master",
|
DefaultBranch: "master",
|
||||||
Permissions: &gogs.Permission{Admin: true},
|
Permissions: &gogs.Permission{Admin: true},
|
||||||
}
|
}
|
||||||
repo := toRepo(&from, false)
|
repo := toRepo(&from)
|
||||||
g.Assert(repo.FullName).Equal(from.FullName)
|
g.Assert(repo.FullName).Equal(from.FullName)
|
||||||
g.Assert(repo.Owner).Equal(from.Owner.UserName)
|
g.Assert(repo.Owner).Equal(from.Owner.UserName)
|
||||||
g.Assert(repo.Name).Equal("hello-world")
|
g.Assert(repo.Name).Equal("hello-world")
|
||||||
|
@ -39,21 +39,21 @@ const (
|
|||||||
|
|
||||||
// parseHook parses a Bitbucket hook from an http.Request request and returns
|
// parseHook parses a Bitbucket hook from an http.Request request and returns
|
||||||
// Repo and Pipeline detail. If a hook type is unsupported nil values are returned.
|
// Repo and Pipeline detail. If a hook type is unsupported nil values are returned.
|
||||||
func parseHook(r *http.Request, privateMode bool) (*model.Repo, *model.Pipeline, error) {
|
func parseHook(r *http.Request) (*model.Repo, *model.Pipeline, error) {
|
||||||
switch r.Header.Get(hookEvent) {
|
switch r.Header.Get(hookEvent) {
|
||||||
case hookPush:
|
case hookPush:
|
||||||
return parsePushHook(r.Body, privateMode)
|
return parsePushHook(r.Body)
|
||||||
case hookCreated:
|
case hookCreated:
|
||||||
return parseCreatedHook(r.Body, privateMode)
|
return parseCreatedHook(r.Body)
|
||||||
case hookPullRequest:
|
case hookPullRequest:
|
||||||
return parsePullRequestHook(r.Body, privateMode)
|
return parsePullRequestHook(r.Body)
|
||||||
}
|
}
|
||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parsePushHook parses a push hook and returns the Repo and Pipeline details.
|
// parsePushHook parses a push hook and returns the Repo and Pipeline details.
|
||||||
// If the commit type is unsupported nil values are returned.
|
// If the commit type is unsupported nil values are returned.
|
||||||
func parsePushHook(payload io.Reader, privateMode bool) (*model.Repo, *model.Pipeline, error) {
|
func parsePushHook(payload io.Reader) (*model.Repo, *model.Pipeline, error) {
|
||||||
var (
|
var (
|
||||||
repo *model.Repo
|
repo *model.Repo
|
||||||
pipeline *model.Pipeline
|
pipeline *model.Pipeline
|
||||||
@ -69,14 +69,14 @@ func parsePushHook(payload io.Reader, privateMode bool) (*model.Repo, *model.Pip
|
|||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
repo = toRepo(push.Repo, privateMode)
|
repo = toRepo(push.Repo)
|
||||||
pipeline = pipelineFromPush(push)
|
pipeline = pipelineFromPush(push)
|
||||||
return repo, pipeline, err
|
return repo, pipeline, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseCreatedHook parses a push hook and returns the Repo and Pipeline details.
|
// parseCreatedHook parses a push hook and returns the Repo and Pipeline details.
|
||||||
// If the commit type is unsupported nil values are returned.
|
// If the commit type is unsupported nil values are returned.
|
||||||
func parseCreatedHook(payload io.Reader, privateMode bool) (*model.Repo, *model.Pipeline, error) {
|
func parseCreatedHook(payload io.Reader) (*model.Repo, *model.Pipeline, error) {
|
||||||
var (
|
var (
|
||||||
repo *model.Repo
|
repo *model.Repo
|
||||||
pipeline *model.Pipeline
|
pipeline *model.Pipeline
|
||||||
@ -91,13 +91,13 @@ func parseCreatedHook(payload io.Reader, privateMode bool) (*model.Repo, *model.
|
|||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
repo = toRepo(push.Repo, privateMode)
|
repo = toRepo(push.Repo)
|
||||||
pipeline = pipelineFromTag(push)
|
pipeline = pipelineFromTag(push)
|
||||||
return repo, pipeline, err
|
return repo, pipeline, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// parsePullRequestHook parses a pull_request hook and returns the Repo and Pipeline details.
|
// parsePullRequestHook parses a pull_request hook and returns the Repo and Pipeline details.
|
||||||
func parsePullRequestHook(payload io.Reader, privateMode bool) (*model.Repo, *model.Pipeline, error) {
|
func parsePullRequestHook(payload io.Reader) (*model.Repo, *model.Pipeline, error) {
|
||||||
var (
|
var (
|
||||||
repo *model.Repo
|
repo *model.Repo
|
||||||
pipeline *model.Pipeline
|
pipeline *model.Pipeline
|
||||||
@ -116,7 +116,7 @@ func parsePullRequestHook(payload io.Reader, privateMode bool) (*model.Repo, *mo
|
|||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
repo = toRepo(pr.Repo, privateMode)
|
repo = toRepo(pr.Repo)
|
||||||
pipeline = pipelineFromPullRequest(pr)
|
pipeline = pipelineFromPullRequest(pr)
|
||||||
return repo, pipeline, err
|
return repo, pipeline, err
|
||||||
}
|
}
|
||||||
|
@ -39,4 +39,4 @@ func (ae *AuthError) Error() string {
|
|||||||
// check interface
|
// check interface
|
||||||
var _ error = new(AuthError)
|
var _ error = new(AuthError)
|
||||||
|
|
||||||
var ErrNotImplemented = errors.New("Not implemented")
|
var ErrNotImplemented = errors.New("not implemented")
|
||||||
|
@ -66,11 +66,11 @@ const (
|
|||||||
RepoPerforce SCMKind = "perforce"
|
RepoPerforce SCMKind = "perforce"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RepoVisibly represent to wat state a repo in woodpecker is visible to others
|
// RepoVisibility represent to wat state a repo in woodpecker is visible to others
|
||||||
type RepoVisibly string
|
type RepoVisibility string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VisibilityPublic RepoVisibly = "public"
|
VisibilityPublic RepoVisibility = "public"
|
||||||
VisibilityPrivate RepoVisibly = "private"
|
VisibilityPrivate RepoVisibility = "private"
|
||||||
VisibilityInternal RepoVisibly = "internal"
|
VisibilityInternal RepoVisibility = "internal"
|
||||||
)
|
)
|
||||||
|
@ -37,7 +37,7 @@ type Repo struct {
|
|||||||
Branch string `json:"default_branch,omitempty" xorm:"varchar(500) 'repo_branch'"`
|
Branch string `json:"default_branch,omitempty" xorm:"varchar(500) 'repo_branch'"`
|
||||||
SCMKind SCMKind `json:"scm,omitempty" xorm:"varchar(50) 'repo_scm'"`
|
SCMKind SCMKind `json:"scm,omitempty" xorm:"varchar(50) 'repo_scm'"`
|
||||||
Timeout int64 `json:"timeout,omitempty" xorm:"repo_timeout"`
|
Timeout int64 `json:"timeout,omitempty" xorm:"repo_timeout"`
|
||||||
Visibility RepoVisibly `json:"visibility" xorm:"varchar(10) 'repo_visibility'"`
|
Visibility RepoVisibility `json:"visibility" xorm:"varchar(10) 'repo_visibility'"`
|
||||||
IsSCMPrivate bool `json:"private" xorm:"repo_private"`
|
IsSCMPrivate bool `json:"private" xorm:"repo_private"`
|
||||||
IsTrusted bool `json:"trusted" xorm:"repo_trusted"`
|
IsTrusted bool `json:"trusted" xorm:"repo_trusted"`
|
||||||
IsGated bool `json:"gated" xorm:"repo_gated"`
|
IsGated bool `json:"gated" xorm:"repo_gated"`
|
||||||
|
Loading…
Reference in New Issue
Block a user