diff --git a/cmd/server/docs/docs.go b/cmd/server/docs/docs.go
index 6c1d65c4e..ddf38ecc1 100644
--- a/cmd/server/docs/docs.go
+++ b/cmd/server/docs/docs.go
@@ -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"
},
diff --git a/docs/docs/20-usage/71-project-settings.md b/docs/docs/20-usage/71-project-settings.md
index 573e85eee..24bdbe605 100644
--- a/docs/docs/20-usage/71-project-settings.md
+++ b/docs/docs/20-usage/71-project-settings.md
@@ -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.
diff --git a/server/api/pipeline.go b/server/api/pipeline.go
index 2a98f6a9c..4cd6f43e3 100644
--- a/server/api/pipeline.go
+++ b/server/api/pipeline.go
@@ -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
diff --git a/server/api/repo.go b/server/api/repo.go
index e812312ea..e9c4c3138 100644
--- a/server/api/repo.go
+++ b/server/api/repo.go
@@ -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
}
diff --git a/server/model/repo.go b/server/model/repo.go
index b99c66b15..877185c3a 100644
--- a/server/model/repo.go
+++ b/server/model/repo.go
@@ -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
diff --git a/web/src/assets/locales/en.json b/web/src/assets/locales/en.json
index 159120e5c..e792c6eee 100644
--- a/web/src/assets/locales/en.json
+++ b/web/src/assets/locales/en.json
@@ -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."
diff --git a/web/src/components/repo/settings/GeneralTab.vue b/web/src/components/repo/settings/GeneralTab.vue
index feea4493a..16381ebe3 100644
--- a/web/src/components/repo/settings/GeneralTab.vue
+++ b/web/src/components/repo/settings/GeneralTab.vue
@@ -29,6 +29,11 @@
:label="$t('repo.settings.general.allow_pr.allow')"
:description="$t('repo.settings.general.allow_pr.desc')"
/>
+
;
diff --git a/web/src/views/repo/pipeline/PipelineWrapper.vue b/web/src/views/repo/pipeline/PipelineWrapper.vue
index b54ae2c2e..9049d8f0c 100644
--- a/web/src/views/repo/pipeline/PipelineWrapper.vue
+++ b/web/src/views/repo/pipeline/PipelineWrapper.vue
@@ -45,10 +45,7 @@
@click="restartPipeline"
/>