Merge branch 'main' into rework-entry

This commit is contained in:
qwerty287 2024-04-03 08:10:01 +02:00
commit 53967dfce7
No known key found for this signature in database
GPG key ID: 1218A32A886A5002
29 changed files with 173 additions and 309 deletions

1
.gitignore vendored
View file

@ -41,6 +41,7 @@ extras/
/build/
/dist/
/data/
datastore/migration/testfiles/
docs/venv

View file

@ -10,7 +10,7 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/golangci/golangci-lint
rev: v1.57.1
rev: v1.57.2
hooks:
- id: golangci-lint
- repo: https://github.com/igorshubovych/markdownlint-cli

View file

@ -3,7 +3,7 @@ variables:
- &node_image 'docker.io/node:21-alpine'
- &xgo_image 'docker.io/techknowlogick/xgo:go-1.22.1'
- &xgo_version 'go-1.21.2'
- &buildx_plugin 'docker.io/woodpeckerci/plugin-docker-buildx:3.2.0'
- &buildx_plugin 'docker.io/woodpeckerci/plugin-docker-buildx:3.2.1'
- &platforms_release 'linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/386,linux/amd64,linux/ppc64le,linux/riscv64,linux/s390x,freebsd/arm64,freebsd/amd64,openbsd/arm64,openbsd/amd64'
- &platforms_server 'linux/arm/v7,linux/arm64/v8,linux/amd64,linux/ppc64le,linux/riscv64'
- &platforms_preview 'linux/amd64'

View file

@ -4048,6 +4048,9 @@ const docTemplate = `{
"active": {
"type": "boolean"
},
"allow_deploy": {
"type": "boolean"
},
"allow_pr": {
"type": "boolean"
},
@ -4123,6 +4126,9 @@ const docTemplate = `{
"RepoPatch": {
"type": "object",
"properties": {
"allow_deploy": {
"type": "boolean"
},
"allow_pr": {
"type": "boolean"
},

View file

@ -340,6 +340,12 @@ var flags = append([]cli.Flag{
Usage: "github pull requests use merge ref",
Value: true,
},
&cli.BoolFlag{
EnvVars: []string{"WOODPECKER_GITHUB_PUBLIC_ONLY"},
Name: "github-public-only",
Usage: "github tokens should only get access to public repos",
Value: false,
},
&cli.BoolFlag{
EnvVars: []string{"WOODPECKER_GITHUB_SKIP_VERIFY"},
Name: "github-skip-verify",

View file

@ -200,6 +200,7 @@ func setupGitHub(c *cli.Context) (forge.Forge, error) {
Secret: c.String("github-secret"),
SkipVerify: c.Bool("github-skip-verify"),
MergeRef: c.Bool("github-merge-ref"),
OnlyPublic: c.Bool("github-public-only"),
}
log.Trace().Msgf("forge (github) opts: %#v", opts)
return github.New(opts)

View file

@ -16,6 +16,15 @@ Your Version-Control-System will notify Woodpecker about events via webhooks. If
Enables handling webhook's pull request event. If disabled, then pipeline won't run for pull requests.
## Allow deployments
Enables a pipeline to be started with the `deploy` event from a successful pipeline.
:::danger
Only activate this option if you trust all users who have push access to your repository.
Otherwise, these users will be able to steal secrets that are only available for `deploy` events.
:::
## Protected
Every pipeline initiated by an webhook event needs to be approved by a project members with push permissions before being executed.

View file

@ -81,3 +81,9 @@ Read the value for `WOODPECKER_GITHUB_SECRET` from the specified filepath.
> Default: `false`
Configure if SSL verification should be skipped.
### `WOODPECKER_GITHUB_PUBLIC_ONLY`
> Default: `false`
Configures the GitHub OAuth client to only obtain a token that can manage public repositories.

View file

@ -40,6 +40,11 @@ steps:
You can use [Limit Ranges](https://kubernetes.io/docs/concepts/policy/limit-range/) if you want to set the limits by per-namespace basis.
### Runtime class
`runtimeClassName` specifies the name of the RuntimeClass which will be used to run this pod. If no `runtimeClassName` is specified, the default RuntimeHandler will be used.
See the [kubernetes documentation](https://kubernetes.io/docs/concepts/containers/runtime-class/) for more information on specifying runtime classes.
### Service account
`serviceAccountName` specifies the name of the ServiceAccount which the pod will mount. This service account must be created externally.

View file

@ -9,6 +9,7 @@ import (
// BackendOptions defines all the advanced options for the kubernetes backend
type BackendOptions struct {
Resources Resources `mapstructure:"resources"`
RuntimeClassName *string `mapstructure:"runtimeClassName"`
ServiceAccountName string `mapstructure:"serviceAccountName"`
NodeSelector map[string]string `mapstructure:"nodeSelector"`
Tolerations []Toleration `mapstructure:"tolerations"`

View file

@ -117,6 +117,7 @@ func podSpec(step *types.Step, config *config, options BackendOptions) (v1.PodSp
var err error
spec := v1.PodSpec{
RestartPolicy: v1.RestartPolicyNever,
RuntimeClassName: options.RuntimeClassName,
ServiceAccountName: options.ServiceAccountName,
ImagePullSecrets: imagePullSecretsReferences(config.ImagePullSecretNames),
HostAliases: hostAliases(step.ExtraHosts),
@ -135,9 +136,11 @@ func podSpec(step *types.Step, config *config, options BackendOptions) (v1.PodSp
func podContainer(step *types.Step, podName, goos string, options BackendOptions) (v1.Container, error) {
var err error
container := v1.Container{
Name: podName,
Image: step.Image,
WorkingDir: step.WorkingDir,
Name: podName,
Image: step.Image,
WorkingDir: step.WorkingDir,
Ports: containerPorts(step.Ports),
SecurityContext: containerSecurityContext(options.SecurityContext, step.Privileged),
}
if step.Pull {
@ -154,8 +157,6 @@ func podContainer(step *types.Step, podName, goos string, options BackendOptions
}
container.Env = mapToEnvVars(step.Environment)
container.Ports = containerPorts(step.Ports)
container.SecurityContext = containerSecurityContext(options.SecurityContext, step.Privileged)
container.Resources, err = resourceRequirements(options.Resources)
if err != nil {

View file

@ -240,6 +240,7 @@ func TestFullPod(t *testing.T) {
"nodeSelector": {
"storage": "ssd"
},
"runtimeClassName": "runc",
"serviceAccountName": "wp-svc-acc",
"securityContext": {
"runAsUser": 101,
@ -284,6 +285,7 @@ func TestFullPod(t *testing.T) {
"status": {}
}`
runtimeClass := "runc"
hostAliases := []types.HostAlias{
{Name: "cloudflare", IP: "1.1.1.1"},
{Name: "cf.v6", IP: "2606:4700:4700::64"},
@ -328,6 +330,7 @@ func TestFullPod(t *testing.T) {
SecurityContext: SecurityContextConfig{RunAsNonRoot: false},
}, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{
NodeSelector: map[string]string{"storage": "ssd"},
RuntimeClassName: &runtimeClass,
ServiceAccountName: "wp-svc-acc",
Tolerations: []Toleration{{Key: "net-port", Value: "100Mbit", Effect: TaintEffectNoSchedule}},
Resources: Resources{

View file

@ -1,117 +0,0 @@
// Copyright 2023 Woodpecker Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package compiler
import (
"path"
"strings"
yaml_types "go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/yaml/types"
)
// Cacher defines a compiler transform that can be used
// to implement default caching for a repository.
type Cacher interface {
Restore(repo, branch string, mounts []string) *yaml_types.Container
Rebuild(repo, branch string, mounts []string) *yaml_types.Container
}
type volumeCacher struct {
base string
}
func (c *volumeCacher) Restore(repo, branch string, mounts []string) *yaml_types.Container {
return &yaml_types.Container{
Name: "rebuild_cache",
Image: "plugins/volume-cache:1.0.0",
Settings: map[string]any{
"mount": mounts,
"path": "/cache",
"restore": true,
"file": strings.ReplaceAll(branch, "/", "_") + ".tar",
"fallback_to": "main.tar",
},
Volumes: yaml_types.Volumes{
Volumes: []*yaml_types.Volume{
{
Source: path.Join(c.base, repo),
Destination: "/cache",
// TODO add access mode
},
},
},
}
}
func (c *volumeCacher) Rebuild(repo, branch string, mounts []string) *yaml_types.Container {
return &yaml_types.Container{
Name: "rebuild_cache",
Image: "plugins/volume-cache:1.0.0",
Settings: map[string]any{
"mount": mounts,
"path": "/cache",
"rebuild": true,
"flush": true,
"file": strings.ReplaceAll(branch, "/", "_") + ".tar",
},
Volumes: yaml_types.Volumes{
Volumes: []*yaml_types.Volume{
{
Source: path.Join(c.base, repo),
Destination: "/cache",
// TODO add access mode
},
},
},
}
}
type s3Cacher struct {
bucket string
access string
secret string
region string
}
func (c *s3Cacher) Restore(_, _ string, mounts []string) *yaml_types.Container {
return &yaml_types.Container{
Name: "rebuild_cache",
Image: "plugins/s3-cache:latest",
Settings: map[string]any{
"mount": mounts,
"access_key": c.access,
"secret_key": c.secret,
"bucket": c.bucket,
"region": c.region,
"rebuild": true,
},
}
}
func (c *s3Cacher) Rebuild(_, _ string, mounts []string) *yaml_types.Container {
return &yaml_types.Container{
Name: "rebuild_cache",
Image: "plugins/s3-cache:latest",
Settings: map[string]any{
"mount": mounts,
"access_key": c.access,
"secret_key": c.secret,
"bucket": c.bucket,
"region": c.region,
"rebuild": true,
"flush": true,
},
}
}

View file

@ -16,7 +16,6 @@ package compiler
import (
"fmt"
"path"
backend_types "go.woodpecker-ci.org/woodpecker/v2/pipeline/backend/types"
"go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/metadata"
@ -34,7 +33,6 @@ type Registry struct {
Hostname string
Username string
Password string
Token string
}
type Secret struct {
@ -68,7 +66,7 @@ func (s *Secret) Match(event string) bool {
if len(s.Events) == 0 {
return true
}
// tread all pull events the same way
// treat all pull events the same way
if event == "pull_request_closed" {
event = "pull_request"
}
@ -82,8 +80,6 @@ func (s *Secret) Match(event string) bool {
return false
}
type secretMap map[string]Secret
type ResourceLimit struct {
MemSwapLimit int64
MemLimit int64
@ -106,8 +102,7 @@ type Compiler struct {
path string
metadata metadata.Metadata
registries []Registry
secrets secretMap
cacher Cacher
secrets map[string]Secret
reslimit ResourceLimit
defaultCloneImage string
trustedPipeline bool
@ -224,11 +219,6 @@ func (c *Compiler) Compile(conf *yaml_types.Workflow) (*backend_types.Config, er
}
}
err := c.setupCache(conf, config)
if err != nil {
return nil, err
}
// add services steps
if len(conf.Services.ContainerList) != 0 {
stage := new(backend_types.Stage)
@ -297,48 +287,5 @@ func (c *Compiler) Compile(conf *yaml_types.Workflow) (*backend_types.Config, er
config.Stages = append(config.Stages, stepStages...)
err = c.setupCacheRebuild(conf, config)
if err != nil {
return nil, err
}
return config, nil
}
func (c *Compiler) setupCache(conf *yaml_types.Workflow, ir *backend_types.Config) error {
if c.local || len(conf.Cache) == 0 || c.cacher == nil {
return nil
}
container := c.cacher.Restore(path.Join(c.metadata.Repo.Owner, c.metadata.Repo.Name), c.metadata.Curr.Commit.Branch, conf.Cache)
step, err := c.createProcess(container, backend_types.StepTypeCache)
if err != nil {
return err
}
stage := new(backend_types.Stage)
stage.Steps = append(stage.Steps, step)
ir.Stages = append(ir.Stages, stage)
return nil
}
func (c *Compiler) setupCacheRebuild(conf *yaml_types.Workflow, ir *backend_types.Config) error {
if c.local || len(conf.Cache) == 0 || c.metadata.Curr.Event != metadata.EventPush || c.cacher == nil {
return nil
}
container := c.cacher.Rebuild(path.Join(c.metadata.Repo.Owner, c.metadata.Repo.Name), c.metadata.Curr.Commit.Branch, conf.Cache)
step, err := c.createProcess(container, backend_types.StepTypeCache)
if err != nil {
return err
}
stage := new(backend_types.Stage)
stage.Steps = append(stage.Steps, step)
ir.Stages = append(ir.Stages, stage)
return nil
}

View file

@ -149,34 +149,6 @@ func WithEnviron(env map[string]string) Option {
}
}
// WithCacher configures the compiler with default cache settings.
func WithCacher(cacher Cacher) Option {
return func(compiler *Compiler) {
compiler.cacher = cacher
}
}
// WithVolumeCacher configures the compiler with default local volume
// caching enabled.
func WithVolumeCacher(base string) Option {
return func(compiler *Compiler) {
compiler.cacher = &volumeCacher{base: base}
}
}
// WithS3Cacher configures the compiler with default amazon s3
// caching enabled.
func WithS3Cacher(access, secret, region, bucket string) Option {
return func(compiler *Compiler) {
compiler.cacher = &s3Cacher{
access: access,
secret: secret,
bucket: bucket,
region: region,
}
}
}
// WithNetworks configures the compiler with additional networks
// to be connected to pipeline containers
func WithNetworks(networks ...string) Option {

View file

@ -166,30 +166,9 @@ func TestWithEnviron(t *testing.T) {
assert.Equal(t, "true", compiler.env["SHOW"])
}
func TestWithVolumeCacher(t *testing.T) {
compiler := New(
WithVolumeCacher("/cache"),
)
cacher, ok := compiler.cacher.(*volumeCacher)
assert.True(t, ok)
assert.Equal(t, "/cache", cacher.base)
}
func TestWithDefaultCloneImage(t *testing.T) {
compiler := New(
WithDefaultCloneImage("not-an-image"),
)
assert.Equal(t, "not-an-image", compiler.defaultCloneImage)
}
func TestWithS3Cacher(t *testing.T) {
compiler := New(
WithS3Cacher("some-access-key", "some-secret-key", "some-region", "some-bucket"),
)
cacher, ok := compiler.cacher.(*s3Cacher)
assert.True(t, ok)
assert.Equal(t, "some-bucket", cacher.bucket)
assert.Equal(t, "some-access-key", cacher.access)
assert.Equal(t, "some-region", cacher.region)
assert.Equal(t, "some-secret-key", cacher.secret)
}

View file

@ -696,6 +696,10 @@
},
"securityContext": {
"$ref": "#/definitions/step_backend_kubernetes_security_context"
},
"runtimeClassName": {
"description": "Read more: https://woodpecker-ci.org/docs/administration/backends/kubernetes#runtimeclassname",
"type": "string"
}
}
},

View file

@ -16,7 +16,6 @@ package types
import (
"go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/yaml/constraint"
"go.woodpecker-ci.org/woodpecker/v2/pipeline/frontend/yaml/types/base"
)
type (
@ -33,9 +32,8 @@ type (
SkipClone bool `yaml:"skip_clone"`
// Undocumented
Cache base.StringOrSlice `yaml:"cache,omitempty"`
Networks WorkflowNetworks `yaml:"networks,omitempty"`
Volumes WorkflowVolumes `yaml:"volumes,omitempty"`
Networks WorkflowNetworks `yaml:"networks,omitempty"`
Volumes WorkflowVolumes `yaml:"volumes,omitempty"`
// Deprecated
PlatformDoNotUseIt string `yaml:"platform,omitempty"` // TODO: remove in next major version

View file

@ -407,23 +407,22 @@ func PostPipeline(c *gin.Context) {
refreshUserToken(c, user)
// make Deploy overridable
pl.Deploy = c.DefaultQuery("deploy_to", pl.Deploy)
// make Event overridable to deploy
// TODO refactor to use own proper API for deploy
if event, ok := c.GetQuery("event"); ok {
// only allow deploy from push, tag and release
if pl.Event != model.EventPush && pl.Event != model.EventTag && pl.Event != model.EventRelease {
_ = c.AbortWithError(http.StatusBadRequest, fmt.Errorf("can only deploy push, tag and release pipelines"))
return
}
pl.Event = model.WebhookEvent(event)
if pl.Event != model.EventDeploy {
_ = c.AbortWithError(http.StatusBadRequest, model.ErrInvalidWebhookEvent)
return
}
if !repo.AllowDeploy {
_ = c.AbortWithError(http.StatusForbidden, fmt.Errorf("repo does not allow deployments"))
return
}
pl.Deploy = c.DefaultQuery("deploy_to", pl.Deploy)
}
// Read query string parameters into pipelineParams, exclude reserved params

View file

@ -86,6 +86,7 @@ func PostRepo(c *gin.Context) {
} else {
repo = from
repo.AllowPull = true
repo.AllowDeploy = false
repo.NetrcOnlyTrusted = true
repo.CancelPreviousPipelineEvents = server.Config.Pipeline.DefaultCancelPreviousPipelineEvents
}
@ -223,6 +224,9 @@ func PatchRepo(c *gin.Context) {
if in.AllowPull != nil {
repo.AllowPull = *in.AllowPull
}
if in.AllowDeploy != nil {
repo.AllowDeploy = *in.AllowDeploy
}
if in.IsGated != nil {
repo.IsGated = *in.IsGated
}

View file

@ -51,6 +51,7 @@ type Opts struct {
Secret string // GitHub oauth client secret.
SkipVerify bool // Skip ssl verification.
MergeRef bool // Clone pull requests using the merge ref.
OnlyPublic bool // Only obtain OAuth tokens with access to public repos.
}
// New returns a Forge implementation that integrates with a GitHub Cloud or
@ -63,6 +64,7 @@ func New(opts Opts) (forge.Forge, error) {
Secret: opts.Secret,
SkipVerify: opts.SkipVerify,
MergeRef: opts.MergeRef,
OnlyPublic: opts.OnlyPublic,
}
if opts.URL != defaultURL {
r.url = strings.TrimSuffix(opts.URL, "/")
@ -79,6 +81,7 @@ type client struct {
Secret string
SkipVerify bool
MergeRef bool
OnlyPublic bool
}
// Name returns the string name of this driver
@ -405,10 +408,17 @@ func (c *client) newContext(ctx context.Context) context.Context {
// helper function to return the GitHub oauth2 config
func (c *client) newConfig() *oauth2.Config {
scopes := []string{"user:email", "read:org"}
if c.OnlyPublic {
scopes = append(scopes, []string{"admin:repo_hook", "repo:status"}...)
} else {
scopes = append(scopes, "repo")
}
return &oauth2.Config{
ClientID: c.Client,
ClientSecret: c.Secret,
Scopes: []string{"repo", "user:email", "read:org"},
Scopes: scopes,
Endpoint: oauth2.Endpoint{
AuthURL: fmt.Sprintf("%s/login/oauth/authorize", c.url),
TokenURL: fmt.Sprintf("%s/login/oauth/access_token", c.url),

View file

@ -44,6 +44,7 @@ type Repo struct {
IsGated bool `json:"gated" xorm:"repo_gated"`
IsActive bool `json:"active" xorm:"repo_active"`
AllowPull bool `json:"allow_pr" xorm:"repo_allow_pr"`
AllowDeploy bool `json:"allow_deploy" xorm:"repo_allow_deploy"`
Config string `json:"config_file" xorm:"varchar(500) 'repo_config_path'"`
Hash string `json:"-" xorm:"varchar(500) 'repo_hash'"`
Perm *Perm `json:"-" xorm:"-"`
@ -112,6 +113,7 @@ type RepoPatch struct {
Timeout *int64 `json:"timeout,omitempty"`
Visibility *string `json:"visibility,omitempty"`
AllowPull *bool `json:"allow_pr,omitempty"`
AllowDeploy *bool `json:"allow_deploy,omitempty"`
CancelPreviousPipelineEvents *[]WebhookEvent `json:"cancel_previous_pipeline_events"`
NetrcOnlyTrusted *bool `json:"netrc_only_trusted"`
} // @name RepoPatch

View file

@ -17,7 +17,7 @@
"test": "echo 'No tests configured' && exit 0"
},
"dependencies": {
"@intlify/unplugin-vue-i18n": "^3.0.0",
"@intlify/unplugin-vue-i18n": "^4.0.0",
"@kyvg/vue3-notification": "^3.1.3",
"@vueuse/core": "^10.7.2",
"ansi_up": "^6.0.2",

View file

@ -9,8 +9,8 @@ overrides:
dependencies:
'@intlify/unplugin-vue-i18n':
specifier: ^3.0.0
version: 3.0.1(vue-i18n@9.10.2)
specifier: ^4.0.0
version: 4.0.0(vue-i18n@9.10.2)
'@kyvg/vue3-notification':
specifier: ^3.1.3
version: 3.2.1(vue@3.4.21)
@ -63,7 +63,7 @@ devDependencies:
version: 4.17.0
'@types/node':
specifier: ^20.11.5
version: 20.11.30
version: 20.12.2
'@types/node-emoji':
specifier: ^2.0.0
version: 2.1.0
@ -81,7 +81,7 @@ devDependencies:
version: 7.4.0(eslint@8.57.0)(typescript@5.4.3)
'@vitejs/plugin-vue':
specifier: ^5.0.3
version: 5.0.4(vite@5.2.6)(vue@3.4.21)
version: 5.0.4(vite@5.2.7)(vue@3.4.21)
'@vue/compiler-sfc':
specifier: ^3.4.15
version: 3.4.21
@ -135,13 +135,13 @@ devDependencies:
version: 0.26.0(vue@3.4.21)
vite:
specifier: ^5.0.12
version: 5.2.6(@types/node@20.11.30)
version: 5.2.7(@types/node@20.12.2)
vite-plugin-prismjs:
specifier: ^0.0.11
version: 0.0.11(prismjs@1.29.0)
vite-plugin-windicss:
specifier: ^1.9.3
version: 1.9.3(vite@5.2.6)
version: 1.9.3(vite@5.2.7)
vite-svg-loader:
specifier: ^5.1.0
version: 5.1.0(vue@3.4.21)
@ -664,8 +664,8 @@ packages:
- supports-color
dev: true
/@intlify/bundle-utils@7.5.1(vue-i18n@9.10.2):
resolution: {integrity: sha512-UovJl10oBIlmYEcWw+VIHdKY5Uv5sdPG0b/b6bOYxGLln3UwB75+2dlc0F3Fsa0RhoznQ5Rp589/BZpABpE4Xw==}
/@intlify/bundle-utils@8.0.0(vue-i18n@9.10.2):
resolution: {integrity: sha512-1B++zykRnMwQ+20SpsZI1JCnV/YJt9Oq7AGlEurzkWJOFtFAVqaGc/oV36PBRYeiKnTbY9VYfjBimr2Vt42wLQ==}
engines: {node: '>= 14.16'}
peerDependencies:
petite-vue-i18n: '*'
@ -682,7 +682,6 @@ packages:
escodegen: 2.1.0
estree-walker: 2.0.2
jsonc-eslint-parser: 2.4.0
magic-string: 0.30.8
mlly: 1.6.1
source-map-js: 1.2.0
vue-i18n: 9.10.2(vue@3.4.21)
@ -710,8 +709,8 @@ packages:
engines: {node: '>= 16'}
dev: false
/@intlify/unplugin-vue-i18n@3.0.1(vue-i18n@9.10.2):
resolution: {integrity: sha512-q1zJhA/WpoLBzAAuKA5/AEp0e+bMOM10ll/HxT4g1VAw/9JhC4TTobP9KobKH90JMZ4U2daLFlYQfKNd29lpqw==}
/@intlify/unplugin-vue-i18n@4.0.0(vue-i18n@9.10.2):
resolution: {integrity: sha512-q2Mhqa/mLi0tulfLFO4fMXXvEbkSZpI5yGhNNsLTNJJ41icEGUuyDe+j5zRZIKSkOJRgX6YbCyibTDJdRsukmw==}
engines: {node: '>= 14.16'}
peerDependencies:
petite-vue-i18n: '*'
@ -725,7 +724,7 @@ packages:
vue-i18n-bridge:
optional: true
dependencies:
'@intlify/bundle-utils': 7.5.1(vue-i18n@9.10.2)
'@intlify/bundle-utils': 8.0.0(vue-i18n@9.10.2)
'@intlify/shared': 9.10.2
'@rollup/pluginutils': 5.1.0
'@vue/compiler-sfc': 3.4.21
@ -816,104 +815,120 @@ packages:
estree-walker: 2.0.2
picomatch: 2.3.1
/@rollup/rollup-android-arm-eabi@4.13.0:
resolution: {integrity: sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==}
/@rollup/rollup-android-arm-eabi@4.13.2:
resolution: {integrity: sha512-3XFIDKWMFZrMnao1mJhnOT1h2g0169Os848NhhmGweEcfJ4rCi+3yMCOLG4zA61rbJdkcrM/DjVZm9Hg5p5w7g==}
cpu: [arm]
os: [android]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-android-arm64@4.13.0:
resolution: {integrity: sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==}
/@rollup/rollup-android-arm64@4.13.2:
resolution: {integrity: sha512-GdxxXbAuM7Y/YQM9/TwwP+L0omeE/lJAR1J+olu36c3LqqZEBdsIWeQ91KBe6nxwOnb06Xh7JS2U5ooWU5/LgQ==}
cpu: [arm64]
os: [android]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-darwin-arm64@4.13.0:
resolution: {integrity: sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==}
/@rollup/rollup-darwin-arm64@4.13.2:
resolution: {integrity: sha512-mCMlpzlBgOTdaFs83I4XRr8wNPveJiJX1RLfv4hggyIVhfB5mJfN4P8Z6yKh+oE4Luz+qq1P3kVdWrCKcMYrrA==}
cpu: [arm64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-darwin-x64@4.13.0:
resolution: {integrity: sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==}
/@rollup/rollup-darwin-x64@4.13.2:
resolution: {integrity: sha512-yUoEvnH0FBef/NbB1u6d3HNGyruAKnN74LrPAfDQL3O32e3k3OSfLrPgSJmgb3PJrBZWfPyt6m4ZhAFa2nZp2A==}
cpu: [x64]
os: [darwin]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-arm-gnueabihf@4.13.0:
resolution: {integrity: sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==}
/@rollup/rollup-linux-arm-gnueabihf@4.13.2:
resolution: {integrity: sha512-GYbLs5ErswU/Xs7aGXqzc3RrdEjKdmoCrgzhJWyFL0r5fL3qd1NPcDKDowDnmcoSiGJeU68/Vy+OMUluRxPiLQ==}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-arm64-gnu@4.13.0:
resolution: {integrity: sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==}
/@rollup/rollup-linux-arm64-gnu@4.13.2:
resolution: {integrity: sha512-L1+D8/wqGnKQIlh4Zre9i4R4b4noxzH5DDciyahX4oOz62CphY7WDWqJoQ66zNR4oScLNOqQJfNSIAe/6TPUmQ==}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-arm64-musl@4.13.0:
resolution: {integrity: sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==}
/@rollup/rollup-linux-arm64-musl@4.13.2:
resolution: {integrity: sha512-tK5eoKFkXdz6vjfkSTCupUzCo40xueTOiOO6PeEIadlNBkadH1wNOH8ILCPIl8by/Gmb5AGAeQOFeLev7iZDOA==}
cpu: [arm64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-riscv64-gnu@4.13.0:
resolution: {integrity: sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==}
/@rollup/rollup-linux-powerpc64le-gnu@4.13.2:
resolution: {integrity: sha512-zvXvAUGGEYi6tYhcDmb9wlOckVbuD+7z3mzInCSTACJ4DQrdSLPNUeDIcAQW39M3q6PDquqLWu7pnO39uSMRzQ==}
cpu: [ppc64le]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-riscv64-gnu@4.13.2:
resolution: {integrity: sha512-C3GSKvMtdudHCN5HdmAMSRYR2kkhgdOfye4w0xzyii7lebVr4riCgmM6lRiSCnJn2w1Xz7ZZzHKuLrjx5620kw==}
cpu: [riscv64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-x64-gnu@4.13.0:
resolution: {integrity: sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==}
/@rollup/rollup-linux-s390x-gnu@4.13.2:
resolution: {integrity: sha512-l4U0KDFwzD36j7HdfJ5/TveEQ1fUTjFFQP5qIt9gBqBgu1G8/kCaq5Ok05kd5TG9F8Lltf3MoYsUMw3rNlJ0Yg==}
cpu: [s390x]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-x64-gnu@4.13.2:
resolution: {integrity: sha512-xXMLUAMzrtsvh3cZ448vbXqlUa7ZL8z0MwHp63K2IIID2+DeP5iWIT6g1SN7hg1VxPzqx0xZdiDM9l4n9LRU1A==}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-linux-x64-musl@4.13.0:
resolution: {integrity: sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==}
/@rollup/rollup-linux-x64-musl@4.13.2:
resolution: {integrity: sha512-M/JYAWickafUijWPai4ehrjzVPKRCyDb1SLuO+ZyPfoXgeCEAlgPkNXewFZx0zcnoIe3ay4UjXIMdXQXOZXWqA==}
cpu: [x64]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-win32-arm64-msvc@4.13.0:
resolution: {integrity: sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==}
/@rollup/rollup-win32-arm64-msvc@4.13.2:
resolution: {integrity: sha512-2YWwoVg9KRkIKaXSh0mz3NmfurpmYoBBTAXA9qt7VXk0Xy12PoOP40EFuau+ajgALbbhi4uTj3tSG3tVseCjuA==}
cpu: [arm64]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-win32-ia32-msvc@4.13.0:
resolution: {integrity: sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==}
/@rollup/rollup-win32-ia32-msvc@4.13.2:
resolution: {integrity: sha512-2FSsE9aQ6OWD20E498NYKEQLneShWes0NGMPQwxWOdws35qQXH+FplabOSP5zEe1pVjurSDOGEVCE2agFwSEsw==}
cpu: [ia32]
os: [win32]
requiresBuild: true
dev: true
optional: true
/@rollup/rollup-win32-x64-msvc@4.13.0:
resolution: {integrity: sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==}
/@rollup/rollup-win32-x64-msvc@4.13.2:
resolution: {integrity: sha512-7h7J2nokcdPePdKykd8wtc8QqqkqxIrUz7MHj6aNr8waBRU//NLDVnNjQnqQO6fqtjrtCdftpbTuOKAyrAQETQ==}
cpu: [x64]
os: [win32]
requiresBuild: true
@ -951,8 +966,8 @@ packages:
node-emoji: 2.1.3
dev: true
/@types/node@20.11.30:
resolution: {integrity: sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==}
/@types/node@20.12.2:
resolution: {integrity: sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==}
dependencies:
undici-types: 5.26.5
dev: true
@ -1105,14 +1120,14 @@ packages:
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
dev: true
/@vitejs/plugin-vue@5.0.4(vite@5.2.6)(vue@3.4.21):
/@vitejs/plugin-vue@5.0.4(vite@5.2.7)(vue@3.4.21):
resolution: {integrity: sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==}
engines: {node: ^18.0.0 || >=20.0.0}
peerDependencies:
vite: ^5.0.0
vue: ^3.2.25
dependencies:
vite: 5.2.6(@types/node@20.11.30)
vite: 5.2.7(@types/node@20.12.2)
vue: 3.4.21(typescript@5.4.3)
dev: true
@ -3290,26 +3305,28 @@ packages:
glob: 7.2.3
dev: true
/rollup@4.13.0:
resolution: {integrity: sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==}
/rollup@4.13.2:
resolution: {integrity: sha512-MIlLgsdMprDBXC+4hsPgzWUasLO9CE4zOkj/u6j+Z6j5A4zRY+CtiXAdJyPtgCsc42g658Aeh1DlrdVEJhsL2g==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
dependencies:
'@types/estree': 1.0.5
optionalDependencies:
'@rollup/rollup-android-arm-eabi': 4.13.0
'@rollup/rollup-android-arm64': 4.13.0
'@rollup/rollup-darwin-arm64': 4.13.0
'@rollup/rollup-darwin-x64': 4.13.0
'@rollup/rollup-linux-arm-gnueabihf': 4.13.0
'@rollup/rollup-linux-arm64-gnu': 4.13.0
'@rollup/rollup-linux-arm64-musl': 4.13.0
'@rollup/rollup-linux-riscv64-gnu': 4.13.0
'@rollup/rollup-linux-x64-gnu': 4.13.0
'@rollup/rollup-linux-x64-musl': 4.13.0
'@rollup/rollup-win32-arm64-msvc': 4.13.0
'@rollup/rollup-win32-ia32-msvc': 4.13.0
'@rollup/rollup-win32-x64-msvc': 4.13.0
'@rollup/rollup-android-arm-eabi': 4.13.2
'@rollup/rollup-android-arm64': 4.13.2
'@rollup/rollup-darwin-arm64': 4.13.2
'@rollup/rollup-darwin-x64': 4.13.2
'@rollup/rollup-linux-arm-gnueabihf': 4.13.2
'@rollup/rollup-linux-arm64-gnu': 4.13.2
'@rollup/rollup-linux-arm64-musl': 4.13.2
'@rollup/rollup-linux-powerpc64le-gnu': 4.13.2
'@rollup/rollup-linux-riscv64-gnu': 4.13.2
'@rollup/rollup-linux-s390x-gnu': 4.13.2
'@rollup/rollup-linux-x64-gnu': 4.13.2
'@rollup/rollup-linux-x64-musl': 4.13.2
'@rollup/rollup-win32-arm64-msvc': 4.13.2
'@rollup/rollup-win32-ia32-msvc': 4.13.2
'@rollup/rollup-win32-x64-msvc': 4.13.2
fsevents: 2.3.3
dev: true
@ -3778,7 +3795,7 @@ packages:
- supports-color
dev: true
/vite-plugin-windicss@1.9.3(vite@5.2.6):
/vite-plugin-windicss@1.9.3(vite@5.2.7):
resolution: {integrity: sha512-PqNiIsrEftCrgn0xIpj8ZMSdpz8NZn+OJ3gKXnOF+hFzbHFrKGJA49ViOUKCHDOquxoGBZMmTjepWr8GrftKcQ==}
peerDependencies:
vite: ^2.0.1 || ^3.0.0 || ^4.0.0 || ^5.0.0
@ -3786,7 +3803,7 @@ packages:
'@windicss/plugin-utils': 1.9.3
debug: 4.3.4
kolorist: 1.8.0
vite: 5.2.6(@types/node@20.11.30)
vite: 5.2.7(@types/node@20.12.2)
windicss: 3.5.6
transitivePeerDependencies:
- supports-color
@ -3801,8 +3818,8 @@ packages:
vue: 3.4.21(typescript@5.4.3)
dev: true
/vite@5.2.6(@types/node@20.11.30):
resolution: {integrity: sha512-FPtnxFlSIKYjZ2eosBQamz4CbyrTizbZ3hnGJlh/wMtCrlp1Hah6AzBLjGI5I2urTfNnpovpHdrL6YRuBOPnCA==}
/vite@5.2.7(@types/node@20.12.2):
resolution: {integrity: sha512-k14PWOKLI6pMaSzAuGtT+Cf0YmIx12z9YGon39onaJNy8DLBfBJrzg9FQEmkAM5lpHBZs9wksWAsyF/HkpEwJA==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
@ -3829,10 +3846,10 @@ packages:
terser:
optional: true
dependencies:
'@types/node': 20.11.30
'@types/node': 20.12.2
esbuild: 0.20.2
postcss: 8.4.38
rollup: 4.13.0
rollup: 4.13.2
optionalDependencies:
fsevents: 2.3.3
dev: true

View file

@ -90,6 +90,10 @@
"allow": "Allow Pull Requests",
"desc": "Pipelines can run on pull requests."
},
"allow_deploy": {
"allow": "Allow deployments",
"desc": "Allow deployments from successful pipelines. Only use if you trust all users with push access."
},
"protected": {
"protected": "Protected",
"desc": "Every pipeline needs to be approved before being executed."

View file

@ -29,6 +29,11 @@
:label="$t('repo.settings.general.allow_pr.allow')"
:description="$t('repo.settings.general.allow_pr.desc')"
/>
<Checkbox
v-model="repoSettings.allow_deploy"
:label="$t('repo.settings.general.allow_deploy.allow')"
:description="$t('repo.settings.general.allow_deploy.desc')"
/>
<Checkbox
v-model="repoSettings.gated"
:label="$t('repo.settings.general.protected.protected')"
@ -132,6 +137,7 @@ function loadRepoSettings() {
gated: repo.value.gated,
trusted: repo.value.trusted,
allow_pr: repo.value.allow_pr,
allow_deploy: repo.value.allow_deploy,
cancel_previous_pipeline_events: repo.value.cancel_previous_pipeline_events || [],
netrc_only_trusted: repo.value.netrc_only_trusted,
};

View file

@ -56,6 +56,8 @@ export type Repo = {
// Whether pull requests should trigger a pipeline.
allow_pr: boolean;
allow_deploy: boolean;
config_file: string;
visibility: RepoVisibility;
@ -84,6 +86,7 @@ export type RepoSettings = Pick<
| 'trusted'
| 'gated'
| 'allow_pr'
| 'allow_deploy'
| 'cancel_previous_pipeline_events'
| 'netrc_only_trusted'
>;

View file

@ -45,10 +45,7 @@
@click="restartPipeline"
/>
<Button
v-if="
pipeline.status === 'success' &&
(pipeline.event === 'push' || pipeline.event === 'tag' || pipeline.event === 'release')
"
v-if="pipeline.status === 'success' && repo.allow_deploy"
class="flex-shrink-0"
:text="$t('repo.pipeline.actions.deploy')"
@click="showDeployPipelinePopup = true"