mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-25 11:21:02 +00:00
Add release
event trigger (#3226)
Supersedes #764 Bitbucket does not support release webhooks. --------- Co-authored-by: Patrick Schratz <patrick.schratz@gmail.com>
This commit is contained in:
parent
da4bd8b97d
commit
9df572ef31
35 changed files with 628 additions and 18 deletions
|
@ -102,5 +102,6 @@ func secretCreate(c *cli.Context) error {
|
|||
var defaultSecretEvents = []string{
|
||||
woodpecker.EventPush,
|
||||
woodpecker.EventTag,
|
||||
woodpecker.EventRelease,
|
||||
woodpecker.EventDeploy,
|
||||
}
|
||||
|
|
|
@ -3937,6 +3937,9 @@ const docTemplate = `{
|
|||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"is_prerelease": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -4383,6 +4386,7 @@ const docTemplate = `{
|
|||
"pull_request",
|
||||
"pull_request_closed",
|
||||
"tag",
|
||||
"release",
|
||||
"deployment",
|
||||
"cron",
|
||||
"manual"
|
||||
|
@ -4392,6 +4396,7 @@ const docTemplate = `{
|
|||
"EventPull",
|
||||
"EventPullClosed",
|
||||
"EventTag",
|
||||
"EventRelease",
|
||||
"EventDeploy",
|
||||
"EventCron",
|
||||
"EventManual"
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
- `pull_request`: A pull request event is triggered when a pull request is opened or a new commit is pushed to it.
|
||||
- `pull_request_closed`: A pull request closed event is triggered when a pull request is closed or merged.
|
||||
- `tag`: A tag event is triggered when a tag is pushed.
|
||||
- `release`: A release event is triggered when a release is created.
|
||||
- `manual`: A manual event is triggered when a user manually triggers a pipeline.
|
||||
- `cron`: A cron event is triggered when a cron job is executed.
|
||||
|
||||
|
|
|
@ -269,7 +269,7 @@ when:
|
|||
|
||||
#### `event`
|
||||
|
||||
Available events: `push`, `pull_request`, `pull_request_closed`, `tag`, `deployment`, `cron`, `manual`
|
||||
Available events: `push`, `pull_request`, `pull_request_closed`, `tag`, `release`, `deployment`, `cron`, `manual`
|
||||
|
||||
Execute a step if the build event is a `tag`:
|
||||
|
||||
|
|
|
@ -77,6 +77,7 @@ This is the reference list of all environment variables available to your pipeli
|
|||
| `CI_COMMIT_AUTHOR` | commit author username |
|
||||
| `CI_COMMIT_AUTHOR_EMAIL` | commit author email address |
|
||||
| `CI_COMMIT_AUTHOR_AVATAR` | commit author avatar |
|
||||
| `CI_COMMIT_PRERELEASE` | release is a pre-release (empty if event is not `release`) |
|
||||
| | **Current pipeline** |
|
||||
| `CI_PIPELINE_NUMBER` | pipeline number |
|
||||
| `CI_PIPELINE_PARENT` | number of parent pipeline |
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
| Event: Push | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Event: Tag | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Event: Pull-Request | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| Event: Release | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |
|
||||
| Event: Deploy | :white_check_mark: | :x: | :x: | :x: |
|
||||
| [Multiple workflows](../../20-usage/25-workflows.md) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
|
||||
| [when.path filter](../../20-usage/20-workflow-syntax.md#path) | :white_check_mark: | :white_check_mark: | :white_check_mark: | :x: |
|
||||
|
|
|
@ -20,6 +20,7 @@ const (
|
|||
EventPull = "pull_request"
|
||||
EventPullClosed = "pull_request_closed"
|
||||
EventTag = "tag"
|
||||
EventRelease = "release"
|
||||
EventDeploy = "deployment"
|
||||
EventCron = "cron"
|
||||
EventManual = "manual"
|
||||
|
|
|
@ -125,9 +125,12 @@ func (m *Metadata) Environ() map[string]string {
|
|||
// TODO Deprecated, remove in 3.x
|
||||
"CI_COMMIT_URL": m.Curr.ForgeURL,
|
||||
}
|
||||
if m.Curr.Event == EventTag || strings.HasPrefix(m.Curr.Commit.Ref, "refs/tags/") {
|
||||
if m.Curr.Event == EventTag || m.Curr.Event == EventRelease || strings.HasPrefix(m.Curr.Commit.Ref, "refs/tags/") {
|
||||
params["CI_COMMIT_TAG"] = strings.TrimPrefix(m.Curr.Commit.Ref, "refs/tags/")
|
||||
}
|
||||
if m.Curr.Event == EventRelease {
|
||||
params["CI_COMMIT_PRERELEASE"] = strconv.FormatBool(m.Curr.Commit.IsPrerelease)
|
||||
}
|
||||
if m.Curr.Event == EventPull {
|
||||
params["CI_COMMIT_PULL_REQUEST"] = pullRegexp.FindString(m.Curr.Commit.Ref)
|
||||
params["CI_COMMIT_PULL_REQUEST_LABELS"] = strings.Join(m.Curr.Commit.PullRequestLabels, ",")
|
||||
|
|
|
@ -69,6 +69,7 @@ type (
|
|||
Author Author `json:"author,omitempty"`
|
||||
ChangedFiles []string `json:"changed_files,omitempty"`
|
||||
PullRequestLabels []string `json:"labels,omitempty"`
|
||||
IsPrerelease bool `json:"is_prerelease,omitempty"`
|
||||
}
|
||||
|
||||
// Author defines runtime metadata for a commit author.
|
||||
|
|
|
@ -414,7 +414,7 @@ func PostPipeline(c *gin.Context) {
|
|||
if event, ok := c.GetQuery("event"); ok {
|
||||
pl.Event = model.WebhookEvent(event)
|
||||
|
||||
if err := model.ValidateWebhookEvent(pl.Event); err != nil {
|
||||
if err := pl.Event.Validate(); err != nil {
|
||||
_ = c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1071,3 +1071,79 @@ const HookPullRequestClosed = `
|
|||
"review": null
|
||||
}
|
||||
`
|
||||
|
||||
const HookRelease = `
|
||||
{
|
||||
"action": "published",
|
||||
"release": {
|
||||
"id": 48,
|
||||
"tag_name": "0.0.5",
|
||||
"target_commitish": "main",
|
||||
"name": "Version 0.0.5",
|
||||
"body": "",
|
||||
"url": "https://git.xxx/api/v1/repos/anbraten/demo/releases/48",
|
||||
"html_url": "https://git.xxx/anbraten/demo/releases/tag/0.0.5",
|
||||
"tarball_url": "https://git.xxx/anbraten/demo/archive/0.0.5.tar.gz",
|
||||
"zipball_url": "https://git.xxx/anbraten/demo/archive/0.0.5.zip",
|
||||
"draft": false,
|
||||
"prerelease": false,
|
||||
"created_at": "2022-02-09T20:23:05Z",
|
||||
"published_at": "2022-02-09T20:23:05Z",
|
||||
"author": {"id":1,"login":"anbraten","full_name":"Anton Bracke","email":"anbraten@noreply.xxx","avatar_url":"https://git.xxx/user/avatar/anbraten/-1","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2018-03-21T10:04:48Z","restricted":false,"active":false,"prohibit_login":false,"location":"world","website":"https://xxx","description":"","visibility":"public","followers_count":1,"following_count":1,"starred_repos_count":1,"username":"anbraten"},
|
||||
"assets": []
|
||||
},
|
||||
"repository": {
|
||||
"id": 77,
|
||||
"owner": {"id":1,"login":"anbraten","full_name":"Anton Bracke","email":"anbraten@noreply.xxx","avatar_url":"https://git.xxx/user/avatar/anbraten/-1","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2018-03-21T10:04:48Z","restricted":false,"active":false,"prohibit_login":false,"location":"world","website":"https://xxx","description":"","visibility":"public","followers_count":1,"following_count":1,"starred_repos_count":1,"username":"anbraten"},
|
||||
"name": "demo",
|
||||
"full_name": "anbraten/demo",
|
||||
"description": "",
|
||||
"empty": false,
|
||||
"private": true,
|
||||
"fork": false,
|
||||
"template": false,
|
||||
"parent": null,
|
||||
"mirror": false,
|
||||
"size": 59,
|
||||
"html_url": "https://git.xxx/anbraten/demo",
|
||||
"ssh_url": "ssh://git@git.xxx:22/anbraten/demo.git",
|
||||
"clone_url": "https://git.xxx/anbraten/demo.git",
|
||||
"original_url": "",
|
||||
"website": "",
|
||||
"stars_count": 0,
|
||||
"forks_count": 1,
|
||||
"watchers_count": 1,
|
||||
"open_issues_count": 2,
|
||||
"open_pr_counter": 2,
|
||||
"release_counter": 4,
|
||||
"default_branch": "main",
|
||||
"archived": false,
|
||||
"created_at": "2021-08-30T20:54:13Z",
|
||||
"updated_at": "2022-01-09T01:29:23Z",
|
||||
"permissions": {
|
||||
"admin": true,
|
||||
"push": true,
|
||||
"pull": true
|
||||
},
|
||||
"has_issues": true,
|
||||
"internal_tracker": {
|
||||
"enable_time_tracker": true,
|
||||
"allow_only_contributors_to_track_time": true,
|
||||
"enable_issue_dependencies": true
|
||||
},
|
||||
"has_wiki": false,
|
||||
"has_pull_requests": true,
|
||||
"has_projects": true,
|
||||
"ignore_whitespace_conflicts": false,
|
||||
"allow_merge_commits": true,
|
||||
"allow_rebase": true,
|
||||
"allow_rebase_explicit": true,
|
||||
"allow_squash_merge": true,
|
||||
"default_merge_style": "squash",
|
||||
"avatar_url": "",
|
||||
"internal": false,
|
||||
"mirror_interval": ""
|
||||
},
|
||||
"sender": {"id":1,"login":"anbraten","full_name":"Anbraten","email":"anbraten@noreply.xxx","avatar_url":"https://git.xxx/user/avatar/anbraten/-1","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2018-03-21T10:04:48Z","restricted":false,"active":false,"prohibit_login":false,"location":"World","website":"https://xxx","description":"","visibility":"public","followers_count":1,"following_count":1,"starred_repos_count":1,"username":"anbraten"}
|
||||
}
|
||||
`
|
||||
|
|
|
@ -510,6 +510,15 @@ func (c *Gitea) Hook(ctx context.Context, r *http.Request) (*model.Repo, *model.
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
if pipeline != nil && pipeline.Event == model.EventRelease && pipeline.Commit == "" {
|
||||
tagName := strings.Split(pipeline.Ref, "/")[2]
|
||||
sha, err := c.getTagCommitSHA(ctx, repo, tagName)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pipeline.Commit = sha
|
||||
}
|
||||
|
||||
if pipeline != nil && (pipeline.Event == model.EventPull || pipeline.Event == model.EventPullClosed) && len(pipeline.ChangedFiles) == 0 {
|
||||
index, err := strconv.ParseInt(strings.Split(pipeline.Ref, "/")[2], 10, 64)
|
||||
if err != nil {
|
||||
|
@ -655,6 +664,36 @@ func (c *Gitea) getChangedFilesForPR(ctx context.Context, repo *model.Repo, inde
|
|||
})
|
||||
}
|
||||
|
||||
func (c *Gitea) getTagCommitSHA(ctx context.Context, repo *model.Repo, tagName string) (string, error) {
|
||||
_store, ok := store.TryFromContext(ctx)
|
||||
if !ok {
|
||||
log.Error().Msg("could not get store from context")
|
||||
return "", nil
|
||||
}
|
||||
|
||||
repo, err := _store.GetRepoNameFallback(repo.ForgeRemoteID, repo.FullName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
user, err := _store.GetUser(repo.UserID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
client, err := c.newClientToken(ctx, user.Token)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
tag, _, err := client.GetTag(repo.Owner, repo.Name, tagName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return tag.Commit.SHA, nil
|
||||
}
|
||||
|
||||
func (c *Gitea) perPage(ctx context.Context) int {
|
||||
if c.pageSize == 0 {
|
||||
client, err := c.newClientToken(ctx, "")
|
||||
|
|
|
@ -175,6 +175,25 @@ func pipelineFromPullRequest(hook *pullRequestHook) *model.Pipeline {
|
|||
return pipeline
|
||||
}
|
||||
|
||||
func pipelineFromRelease(hook *releaseHook) *model.Pipeline {
|
||||
avatar := expandAvatar(
|
||||
hook.Repo.HTMLURL,
|
||||
fixMalformedAvatar(hook.Sender.AvatarURL),
|
||||
)
|
||||
|
||||
return &model.Pipeline{
|
||||
Event: model.EventRelease,
|
||||
Ref: fmt.Sprintf("refs/tags/%s", hook.Release.TagName),
|
||||
ForgeURL: hook.Release.HTMLURL,
|
||||
Branch: hook.Release.Target,
|
||||
Message: fmt.Sprintf("created release %s", hook.Release.Title),
|
||||
Avatar: avatar,
|
||||
Author: hook.Sender.UserName,
|
||||
Sender: hook.Sender.UserName,
|
||||
IsPrerelease: hook.Release.IsPrerelease,
|
||||
}
|
||||
}
|
||||
|
||||
// helper function that parses a push hook from a read closer.
|
||||
func parsePush(r io.Reader) (*pushHook, error) {
|
||||
push := new(pushHook)
|
||||
|
@ -188,6 +207,12 @@ func parsePullRequest(r io.Reader) (*pullRequestHook, error) {
|
|||
return pr, err
|
||||
}
|
||||
|
||||
func parseRelease(r io.Reader) (*releaseHook, error) {
|
||||
pr := new(releaseHook)
|
||||
err := json.NewDecoder(r).Decode(pr)
|
||||
return pr, err
|
||||
}
|
||||
|
||||
// fixMalformedAvatar is a helper function that fixes an avatar url if malformed
|
||||
// (currently a known bug with gitea)
|
||||
func fixMalformedAvatar(url string) string {
|
||||
|
|
|
@ -31,6 +31,7 @@ const (
|
|||
hookPush = "push"
|
||||
hookCreated = "create"
|
||||
hookPullRequest = "pull_request"
|
||||
hookRelease = "release"
|
||||
|
||||
actionOpen = "opened"
|
||||
actionSync = "synchronized"
|
||||
|
@ -40,7 +41,7 @@ const (
|
|||
refTag = "tag"
|
||||
)
|
||||
|
||||
// parseHook parses a Gitea hook from an http.Request request and returns
|
||||
// parseHook parses a Gitea hook from an http.Request and returns
|
||||
// Repo and Pipeline detail. If a hook type is unsupported nil values are returned.
|
||||
func parseHook(r *http.Request) (*model.Repo, *model.Pipeline, error) {
|
||||
hookType := r.Header.Get(hookEvent)
|
||||
|
@ -51,6 +52,8 @@ func parseHook(r *http.Request) (*model.Repo, *model.Pipeline, error) {
|
|||
return parseCreatedHook(r.Body)
|
||||
case hookPullRequest:
|
||||
return parsePullRequestHook(r.Body)
|
||||
case hookRelease:
|
||||
return parseReleaseHook(r.Body)
|
||||
}
|
||||
log.Debug().Msgf("unsupported hook type: '%s'", hookType)
|
||||
return nil, nil, &types.ErrIgnoreEvent{Event: hookType}
|
||||
|
@ -118,3 +121,20 @@ func parsePullRequestHook(payload io.Reader) (*model.Repo, *model.Pipeline, erro
|
|||
pipeline = pipelineFromPullRequest(pr)
|
||||
return repo, pipeline, err
|
||||
}
|
||||
|
||||
// parseReleaseHook parses a release hook and returns the Repo and Pipeline details.
|
||||
func parseReleaseHook(payload io.Reader) (*model.Repo, *model.Pipeline, error) {
|
||||
var (
|
||||
repo *model.Repo
|
||||
pipeline *model.Pipeline
|
||||
)
|
||||
|
||||
release, err := parseRelease(payload)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
repo = toRepo(release.Repo)
|
||||
pipeline = pipelineFromRelease(release)
|
||||
return repo, pipeline, err
|
||||
}
|
||||
|
|
|
@ -124,6 +124,17 @@ func Test_parser(t *testing.T) {
|
|||
g.Assert(err).IsNil()
|
||||
g.Assert(b.Event).Equal(model.EventPullClosed)
|
||||
})
|
||||
g.It("should handle release hook", func() {
|
||||
buf := bytes.NewBufferString(fixtures.HookRelease)
|
||||
req, _ := http.NewRequest("POST", "/hook", buf)
|
||||
req.Header = http.Header{}
|
||||
req.Header.Set(hookEvent, hookRelease)
|
||||
r, b, err := parseHook(req)
|
||||
g.Assert(err).IsNil()
|
||||
g.Assert(r).IsNotNil()
|
||||
g.Assert(b).IsNotNil()
|
||||
g.Assert(b.Event).Equal(model.EventRelease)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -43,3 +43,10 @@ type pullRequestHook struct {
|
|||
Repo *gitea.Repository `json:"repository"`
|
||||
Sender *gitea.User `json:"sender"`
|
||||
}
|
||||
|
||||
type releaseHook struct {
|
||||
Action string `json:"action"`
|
||||
Repo *gitea.Repository `json:"repository"`
|
||||
Sender *gitea.User `json:"sender"`
|
||||
Release *gitea.Release
|
||||
}
|
||||
|
|
|
@ -1391,3 +1391,178 @@ const HookPullRequestClosed = `
|
|||
}
|
||||
}
|
||||
`
|
||||
|
||||
const HookRelease = `
|
||||
{
|
||||
"action": "released",
|
||||
"release": {
|
||||
"url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/releases/2",
|
||||
"assets_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/releases/2/assets",
|
||||
"upload_url": "https://octocoders.github.io/api/uploads/repos/Codertocat/Hello-World/releases/2/assets{?name,label}",
|
||||
"html_url": "https://octocoders.github.io/Codertocat/Hello-World/releases/tag/0.0.1",
|
||||
"id": 2,
|
||||
"node_id": "MDc6UmVsZWFzZTI=",
|
||||
"tag_name": "0.0.1",
|
||||
"target_commitish": "master",
|
||||
"name": null,
|
||||
"draft": false,
|
||||
"author": {
|
||||
"login": "Codertocat",
|
||||
"id": 4,
|
||||
"node_id": "MDQ6VXNlcjQ=",
|
||||
"avatar_url": "https://octocoders.github.io/avatars/u/4?",
|
||||
"gravatar_id": "",
|
||||
"url": "https://octocoders.github.io/api/v3/users/Codertocat",
|
||||
"html_url": "https://octocoders.github.io/Codertocat",
|
||||
"followers_url": "https://octocoders.github.io/api/v3/users/Codertocat/followers",
|
||||
"following_url": "https://octocoders.github.io/api/v3/users/Codertocat/following{/other_user}",
|
||||
"gists_url": "https://octocoders.github.io/api/v3/users/Codertocat/gists{/gist_id}",
|
||||
"starred_url": "https://octocoders.github.io/api/v3/users/Codertocat/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://octocoders.github.io/api/v3/users/Codertocat/subscriptions",
|
||||
"organizations_url": "https://octocoders.github.io/api/v3/users/Codertocat/orgs",
|
||||
"repos_url": "https://octocoders.github.io/api/v3/users/Codertocat/repos",
|
||||
"events_url": "https://octocoders.github.io/api/v3/users/Codertocat/events{/privacy}",
|
||||
"received_events_url": "https://octocoders.github.io/api/v3/users/Codertocat/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false
|
||||
},
|
||||
"prerelease": false,
|
||||
"created_at": "2019-05-15T19:37:08Z",
|
||||
"published_at": "2019-05-15T19:38:20Z",
|
||||
"assets": [],
|
||||
"tarball_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/tarball/0.0.1",
|
||||
"zipball_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/zipball/0.0.1",
|
||||
"body": null
|
||||
},
|
||||
"repository": {
|
||||
"id": 118,
|
||||
"node_id": "MDEwOlJlcG9zaXRvcnkxMTg=",
|
||||
"name": "Hello-World",
|
||||
"full_name": "Codertocat/Hello-World",
|
||||
"private": false,
|
||||
"owner": {
|
||||
"login": "Codertocat",
|
||||
"id": 4,
|
||||
"node_id": "MDQ6VXNlcjQ=",
|
||||
"avatar_url": "https://octocoders.github.io/avatars/u/4?",
|
||||
"gravatar_id": "",
|
||||
"url": "https://octocoders.github.io/api/v3/users/Codertocat",
|
||||
"html_url": "https://octocoders.github.io/Codertocat",
|
||||
"followers_url": "https://octocoders.github.io/api/v3/users/Codertocat/followers",
|
||||
"following_url": "https://octocoders.github.io/api/v3/users/Codertocat/following{/other_user}",
|
||||
"gists_url": "https://octocoders.github.io/api/v3/users/Codertocat/gists{/gist_id}",
|
||||
"starred_url": "https://octocoders.github.io/api/v3/users/Codertocat/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://octocoders.github.io/api/v3/users/Codertocat/subscriptions",
|
||||
"organizations_url": "https://octocoders.github.io/api/v3/users/Codertocat/orgs",
|
||||
"repos_url": "https://octocoders.github.io/api/v3/users/Codertocat/repos",
|
||||
"events_url": "https://octocoders.github.io/api/v3/users/Codertocat/events{/privacy}",
|
||||
"received_events_url": "https://octocoders.github.io/api/v3/users/Codertocat/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false
|
||||
},
|
||||
"html_url": "https://octocoders.github.io/Codertocat/Hello-World",
|
||||
"description": null,
|
||||
"fork": false,
|
||||
"url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World",
|
||||
"forks_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/forks",
|
||||
"keys_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/keys{/key_id}",
|
||||
"collaborators_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/collaborators{/collaborator}",
|
||||
"teams_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/teams",
|
||||
"hooks_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/hooks",
|
||||
"issue_events_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/issues/events{/number}",
|
||||
"events_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/events",
|
||||
"assignees_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/assignees{/user}",
|
||||
"branches_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/branches{/branch}",
|
||||
"tags_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/tags",
|
||||
"blobs_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/git/blobs{/sha}",
|
||||
"git_tags_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/git/tags{/sha}",
|
||||
"git_refs_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/git/refs{/sha}",
|
||||
"trees_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/git/trees{/sha}",
|
||||
"statuses_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/statuses/{sha}",
|
||||
"languages_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/languages",
|
||||
"stargazers_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/stargazers",
|
||||
"contributors_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/contributors",
|
||||
"subscribers_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/subscribers",
|
||||
"subscription_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/subscription",
|
||||
"commits_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/commits{/sha}",
|
||||
"git_commits_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/git/commits{/sha}",
|
||||
"comments_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/comments{/number}",
|
||||
"issue_comment_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/issues/comments{/number}",
|
||||
"contents_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/contents/{+path}",
|
||||
"compare_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/compare/{base}...{head}",
|
||||
"merges_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/merges",
|
||||
"archive_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/{archive_format}{/ref}",
|
||||
"downloads_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/downloads",
|
||||
"issues_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/issues{/number}",
|
||||
"pulls_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/pulls{/number}",
|
||||
"milestones_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/milestones{/number}",
|
||||
"notifications_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/notifications{?since,all,participating}",
|
||||
"labels_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/labels{/name}",
|
||||
"releases_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/releases{/id}",
|
||||
"deployments_url": "https://octocoders.github.io/api/v3/repos/Codertocat/Hello-World/deployments",
|
||||
"created_at": "2019-05-15T19:37:07Z",
|
||||
"updated_at": "2019-05-15T19:38:15Z",
|
||||
"pushed_at": "2019-05-15T19:38:19Z",
|
||||
"git_url": "git://octocoders.github.io/Codertocat/Hello-World.git",
|
||||
"ssh_url": "git@octocoders.github.io:Codertocat/Hello-World.git",
|
||||
"clone_url": "https://octocoders.github.io/Codertocat/Hello-World.git",
|
||||
"svn_url": "https://octocoders.github.io/Codertocat/Hello-World",
|
||||
"homepage": null,
|
||||
"size": 0,
|
||||
"stargazers_count": 0,
|
||||
"watchers_count": 0,
|
||||
"language": "Ruby",
|
||||
"has_issues": true,
|
||||
"has_projects": true,
|
||||
"has_downloads": true,
|
||||
"has_wiki": true,
|
||||
"has_pages": true,
|
||||
"forks_count": 1,
|
||||
"mirror_url": null,
|
||||
"archived": false,
|
||||
"disabled": false,
|
||||
"open_issues_count": 2,
|
||||
"license": null,
|
||||
"forks": 1,
|
||||
"open_issues": 2,
|
||||
"watchers": 0,
|
||||
"default_branch": "master"
|
||||
},
|
||||
"enterprise": {
|
||||
"id": 1,
|
||||
"slug": "github",
|
||||
"name": "GitHub",
|
||||
"node_id": "MDg6QnVzaW5lc3Mx",
|
||||
"avatar_url": "https://octocoders.github.io/avatars/b/1?",
|
||||
"description": null,
|
||||
"website_url": null,
|
||||
"html_url": "https://octocoders.github.io/businesses/github",
|
||||
"created_at": "2019-05-14T19:31:12Z",
|
||||
"updated_at": "2019-05-14T19:31:12Z"
|
||||
},
|
||||
"sender": {
|
||||
"login": "Codertocat",
|
||||
"id": 4,
|
||||
"node_id": "MDQ6VXNlcjQ=",
|
||||
"avatar_url": "https://octocoders.github.io/avatars/u/4?",
|
||||
"gravatar_id": "",
|
||||
"url": "https://octocoders.github.io/api/v3/users/Codertocat",
|
||||
"html_url": "https://octocoders.github.io/Codertocat",
|
||||
"followers_url": "https://octocoders.github.io/api/v3/users/Codertocat/followers",
|
||||
"following_url": "https://octocoders.github.io/api/v3/users/Codertocat/following{/other_user}",
|
||||
"gists_url": "https://octocoders.github.io/api/v3/users/Codertocat/gists{/gist_id}",
|
||||
"starred_url": "https://octocoders.github.io/api/v3/users/Codertocat/starred{/owner}{/repo}",
|
||||
"subscriptions_url": "https://octocoders.github.io/api/v3/users/Codertocat/subscriptions",
|
||||
"organizations_url": "https://octocoders.github.io/api/v3/users/Codertocat/orgs",
|
||||
"repos_url": "https://octocoders.github.io/api/v3/users/Codertocat/repos",
|
||||
"events_url": "https://octocoders.github.io/api/v3/users/Codertocat/events{/privacy}",
|
||||
"received_events_url": "https://octocoders.github.io/api/v3/users/Codertocat/received_events",
|
||||
"type": "User",
|
||||
"site_admin": false
|
||||
},
|
||||
"installation": {
|
||||
"id": 5,
|
||||
"node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNQ=="
|
||||
}
|
||||
}
|
||||
`
|
||||
|
|
|
@ -582,6 +582,15 @@ func (c *client) Hook(ctx context.Context, r *http.Request) (*model.Repo, *model
|
|||
return nil, nil, err
|
||||
}
|
||||
|
||||
if pipeline != nil && pipeline.Event == model.EventRelease && pipeline.Commit == "" {
|
||||
tagName := strings.Split(pipeline.Ref, "/")[2]
|
||||
sha, err := c.getTagCommitSHA(ctx, repo, tagName)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pipeline.Commit = sha
|
||||
}
|
||||
|
||||
if pull != nil && len(pipeline.ChangedFiles) == 0 {
|
||||
pipeline, err = c.loadChangedFilesFromPullRequest(ctx, pull, repo, pipeline)
|
||||
if err != nil {
|
||||
|
@ -629,3 +638,49 @@ func (c *client) loadChangedFilesFromPullRequest(ctx context.Context, pull *gith
|
|||
|
||||
return pipeline, err
|
||||
}
|
||||
|
||||
func (c *client) getTagCommitSHA(ctx context.Context, repo *model.Repo, tagName string) (string, error) {
|
||||
_store, ok := store.TryFromContext(ctx)
|
||||
if !ok {
|
||||
log.Error().Msg("could not get store from context")
|
||||
return "", nil
|
||||
}
|
||||
|
||||
repo, err := _store.GetRepoNameFallback(repo.ForgeRemoteID, repo.FullName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
user, err := _store.GetUser(repo.UserID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
gh := c.newClientToken(ctx, user.Token)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
page := 1
|
||||
var tag *github.RepositoryTag
|
||||
for {
|
||||
tags, _, err := gh.Repositories.ListTags(ctx, repo.Owner, repo.Name, &github.ListOptions{Page: page})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, t := range tags {
|
||||
if t.GetName() == tagName {
|
||||
tag = t
|
||||
break
|
||||
}
|
||||
}
|
||||
if tag != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if tag == nil {
|
||||
return "", fmt.Errorf("could not find tag %s", tagName)
|
||||
}
|
||||
return tag.GetCommit().GetSHA(), nil
|
||||
}
|
||||
|
|
|
@ -32,9 +32,10 @@ import (
|
|||
const (
|
||||
hookField = "payload"
|
||||
|
||||
actionOpen = "opened"
|
||||
actionClose = "closed"
|
||||
actionSync = "synchronize"
|
||||
actionOpen = "opened"
|
||||
actionClose = "closed"
|
||||
actionSync = "synchronize"
|
||||
actionReleased = "released"
|
||||
|
||||
stateOpen = "open"
|
||||
stateClose = "closed"
|
||||
|
@ -68,6 +69,9 @@ func parseHook(r *http.Request, merge bool) (*github.PullRequest, *model.Repo, *
|
|||
return nil, repo, pipeline, nil
|
||||
case *github.PullRequestEvent:
|
||||
return parsePullHook(hook, merge)
|
||||
case *github.ReleaseEvent:
|
||||
repo, pipeline := parseReleaseHook(hook)
|
||||
return nil, repo, pipeline, nil
|
||||
default:
|
||||
return nil, nil, nil, &types.ErrIgnoreEvent{Event: github.Stringify(hook)}
|
||||
}
|
||||
|
@ -176,6 +180,33 @@ func parsePullHook(hook *github.PullRequestEvent, merge bool) (*github.PullReque
|
|||
return hook.GetPullRequest(), convertRepo(hook.GetRepo()), pipeline, nil
|
||||
}
|
||||
|
||||
// parseReleaseHook parses a release hook and returns the Repo and Pipeline
|
||||
// details.
|
||||
func parseReleaseHook(hook *github.ReleaseEvent) (*model.Repo, *model.Pipeline) {
|
||||
if hook.GetAction() != actionReleased {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
name := hook.GetRelease().GetName()
|
||||
if name == "" {
|
||||
name = hook.GetRelease().GetTagName()
|
||||
}
|
||||
|
||||
pipeline := &model.Pipeline{
|
||||
Event: model.EventRelease,
|
||||
ForgeURL: hook.GetRelease().GetHTMLURL(),
|
||||
Ref: fmt.Sprintf("refs/tags/%s", hook.GetRelease().GetTagName()),
|
||||
Branch: hook.GetRelease().GetTargetCommitish(),
|
||||
Message: fmt.Sprintf("created release %s", name),
|
||||
Author: hook.GetRelease().GetAuthor().GetLogin(),
|
||||
Avatar: hook.GetRelease().GetAuthor().GetAvatarURL(),
|
||||
Sender: hook.GetSender().GetLogin(),
|
||||
IsPrerelease: hook.GetRelease().GetPrerelease(),
|
||||
}
|
||||
|
||||
return convertRepo(hook.GetRepo()), pipeline
|
||||
}
|
||||
|
||||
func getChangedFilesFromCommits(commits []*github.HeadCommit) []string {
|
||||
// assume a capacity of 4 changed files per commit
|
||||
files := make([]string, 0, len(commits)*4)
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"bytes"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/franela/goblin"
|
||||
|
@ -30,10 +31,11 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
hookEvent = "X-GitHub-Event"
|
||||
hookDeploy = "deployment"
|
||||
hookPush = "push"
|
||||
hookPull = "pull_request"
|
||||
hookEvent = "X-GitHub-Event"
|
||||
hookDeploy = "deployment"
|
||||
hookPush = "push"
|
||||
hookPull = "pull_request"
|
||||
hookRelease = "release"
|
||||
)
|
||||
|
||||
func testHookRequest(payload []byte, event string) *http.Request {
|
||||
|
@ -119,5 +121,19 @@ func Test_parser(t *testing.T) {
|
|||
g.Assert(b.Event).Equal(model.EventDeploy)
|
||||
})
|
||||
})
|
||||
|
||||
g.Describe("given a release hook", func() {
|
||||
g.It("should extract repository and build details", func() {
|
||||
req := testHookRequest([]byte(fixtures.HookRelease), hookRelease)
|
||||
p, r, b, err := parseHook(req, false)
|
||||
g.Assert(err).IsNil()
|
||||
g.Assert(r).IsNotNil()
|
||||
g.Assert(b).IsNotNil()
|
||||
g.Assert(p).IsNil()
|
||||
g.Assert(b.Event).Equal(model.EventRelease)
|
||||
g.Assert(len(strings.Split(b.Ref, "/")) == 3).IsTrue()
|
||||
g.Assert(strings.HasPrefix(b.Ref, "refs/tags/")).IsTrue()
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -240,6 +240,46 @@ func convertTagHook(hook *gitlab.TagEvent) (*model.Repo, *model.Pipeline, error)
|
|||
return repo, pipeline, nil
|
||||
}
|
||||
|
||||
func convertReleaseHook(hook *gitlab.ReleaseEvent) (*model.Repo, *model.Pipeline, error) {
|
||||
repo := &model.Repo{}
|
||||
|
||||
var err error
|
||||
if repo.Owner, repo.Name, err = extractFromPath(hook.Project.PathWithNamespace); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
repo.ForgeRemoteID = model.ForgeRemoteID(fmt.Sprint(hook.Project.ID))
|
||||
repo.Avatar = ""
|
||||
if hook.Project.AvatarURL != nil {
|
||||
repo.Avatar = *hook.Project.AvatarURL
|
||||
}
|
||||
repo.ForgeURL = hook.Project.WebURL
|
||||
repo.Clone = hook.Project.GitHTTPURL
|
||||
repo.CloneSSH = hook.Project.GitSSHURL
|
||||
repo.FullName = hook.Project.PathWithNamespace
|
||||
repo.Branch = hook.Project.DefaultBranch
|
||||
repo.IsSCMPrivate = hook.Project.VisibilityLevel > 10
|
||||
|
||||
pipeline := &model.Pipeline{
|
||||
Event: model.EventRelease,
|
||||
Commit: hook.Commit.ID,
|
||||
ForgeURL: hook.URL,
|
||||
Message: fmt.Sprintf("created release %s", hook.Name),
|
||||
Sender: hook.Commit.Author.Name,
|
||||
Author: hook.Commit.Author.Name,
|
||||
Email: hook.Commit.Author.Email,
|
||||
|
||||
// Tag name here is the ref. We should add the refs/tags, so
|
||||
// it is known it's a tag (git-plugin looks for it)
|
||||
Ref: "refs/tags/" + hook.Tag,
|
||||
}
|
||||
if len(pipeline.Email) != 0 {
|
||||
pipeline.Avatar = getUserAvatar(pipeline.Email)
|
||||
}
|
||||
|
||||
return repo, pipeline, nil
|
||||
}
|
||||
|
||||
func getUserAvatar(email string) string {
|
||||
hasher := md5.New()
|
||||
hasher.Write([]byte(email))
|
||||
|
|
|
@ -625,6 +625,8 @@ func (g *GitLab) Hook(ctx context.Context, req *http.Request) (*model.Repo, *mod
|
|||
return convertPushHook(event)
|
||||
case *gitlab.TagEvent:
|
||||
return convertTagHook(event)
|
||||
case *gitlab.ReleaseEvent:
|
||||
return convertReleaseHook(event)
|
||||
default:
|
||||
return nil, nil, &forge_types.ErrIgnoreEvent{Event: string(eventType)}
|
||||
}
|
||||
|
|
|
@ -235,6 +235,23 @@ func Test_GitLab(t *testing.T) {
|
|||
assert.Len(t, pipeline.ChangedFiles, 0) // see L217
|
||||
}
|
||||
})
|
||||
|
||||
g.It("Should parse release request hook", func() {
|
||||
req, _ := http.NewRequest(
|
||||
testdata.ServiceHookMethod,
|
||||
testdata.ServiceHookURL.String(),
|
||||
bytes.NewReader(testdata.WebhookReleaseBody),
|
||||
)
|
||||
req.Header = testdata.ReleaseHookHeaders
|
||||
|
||||
hookRepo, build, err := client.Hook(ctx, req)
|
||||
assert.NoError(t, err)
|
||||
if assert.NotNil(t, hookRepo) && assert.NotNil(t, build) {
|
||||
assert.Equal(t, "refs/tags/0.0.2", build.Ref)
|
||||
assert.Equal(t, "ci", hookRepo.Name)
|
||||
assert.Equal(t, "created release Awesome version 0.0.2", build.Message)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
71
server/forge/gitlab/testdata/hooks.go
vendored
71
server/forge/gitlab/testdata/hooks.go
vendored
|
@ -29,6 +29,11 @@ var (
|
|||
"User-Agent": []string{"GitLab/14.3.0"},
|
||||
"X-Gitlab-Event": []string{"Service Hook"},
|
||||
}
|
||||
ReleaseHookHeaders = http.Header{
|
||||
"Content-Type": []string{"application/json"},
|
||||
"User-Agent": []string{"GitLab/14.3.0"},
|
||||
"X-Gitlab-Event": []string{"Release Hook"},
|
||||
}
|
||||
)
|
||||
|
||||
// HookPush is payload of a push event
|
||||
|
@ -599,3 +604,69 @@ var HookPullRequestMerged = []byte(`
|
|||
}
|
||||
}
|
||||
`)
|
||||
|
||||
var WebhookReleaseBody = []byte(`
|
||||
{
|
||||
"id": 4268085,
|
||||
"created_at": "2022-02-09 20:19:09 UTC",
|
||||
"description": "new version desc",
|
||||
"name": "Awesome version 0.0.2",
|
||||
"released_at": "2022-02-09 20:19:09 UTC",
|
||||
"tag": "0.0.2",
|
||||
"object_kind": "release",
|
||||
"project": {
|
||||
"id": 32521798,
|
||||
"name": "ci",
|
||||
"description": "",
|
||||
"web_url": "https://gitlab.com/anbratens-test/ci",
|
||||
"avatar_url": null,
|
||||
"git_ssh_url": "git@gitlab.com:anbratens-test/ci.git",
|
||||
"git_http_url": "https://gitlab.com/anbratens-test/ci.git",
|
||||
"namespace": "anbratens-test",
|
||||
"visibility_level": 0,
|
||||
"path_with_namespace": "anbratens-test/ci",
|
||||
"default_branch": "main",
|
||||
"ci_config_path": "",
|
||||
"homepage": "https://gitlab.com/anbratens-test/ci",
|
||||
"url": "git@gitlab.com:anbratens-test/ci.git",
|
||||
"ssh_url": "git@gitlab.com:anbratens-test/ci.git",
|
||||
"http_url": "https://gitlab.com/anbratens-test/ci.git"
|
||||
},
|
||||
"url": "https://gitlab.com/anbratens-test/ci/-/releases/0.0.2",
|
||||
"action": "create",
|
||||
"assets": {
|
||||
"count": 4,
|
||||
"links": [
|
||||
],
|
||||
"sources": [
|
||||
{
|
||||
"format": "zip",
|
||||
"url": "https://gitlab.com/anbratens-test/ci/-/archive/0.0.2/ci-0.0.2.zip"
|
||||
},
|
||||
{
|
||||
"format": "tar.gz",
|
||||
"url": "https://gitlab.com/anbratens-test/ci/-/archive/0.0.2/ci-0.0.2.tar.gz"
|
||||
},
|
||||
{
|
||||
"format": "tar.bz2",
|
||||
"url": "https://gitlab.com/anbratens-test/ci/-/archive/0.0.2/ci-0.0.2.tar.bz2"
|
||||
},
|
||||
{
|
||||
"format": "tar",
|
||||
"url": "https://gitlab.com/anbratens-test/ci/-/archive/0.0.2/ci-0.0.2.tar"
|
||||
}
|
||||
]
|
||||
},
|
||||
"commit": {
|
||||
"id": "0b8c02955ba445ea70d22824d9589678852e2b93",
|
||||
"message": "Initial commit",
|
||||
"title": "Initial commit",
|
||||
"timestamp": "2022-01-03T10:39:51+00:00",
|
||||
"url": "https://gitlab.com/anbratens-test/ci/-/commit/0b8c02955ba445ea70d22824d9589678852e2b93",
|
||||
"author": {
|
||||
"name": "Anbraten",
|
||||
"email": "2251488-anbraten@users.noreply.gitlab.com"
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
|
|
@ -27,6 +27,7 @@ const (
|
|||
EventPull WebhookEvent = "pull_request"
|
||||
EventPullClosed WebhookEvent = "pull_request_closed"
|
||||
EventTag WebhookEvent = "tag"
|
||||
EventRelease WebhookEvent = "release"
|
||||
EventDeploy WebhookEvent = "deployment"
|
||||
EventCron WebhookEvent = "cron"
|
||||
EventManual WebhookEvent = "manual"
|
||||
|
@ -40,9 +41,9 @@ func (wel WebhookEventList) Less(i, j int) bool { return wel[i] < wel[j] }
|
|||
|
||||
var ErrInvalidWebhookEvent = errors.New("invalid webhook event")
|
||||
|
||||
func ValidateWebhookEvent(s WebhookEvent) error {
|
||||
func (s WebhookEvent) Validate() error {
|
||||
switch s {
|
||||
case EventPush, EventPull, EventTag, EventDeploy, EventCron, EventManual:
|
||||
case EventPush, EventPull, EventPullClosed, EventTag, EventRelease, EventDeploy, EventCron, EventManual:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("%w: %s", ErrInvalidWebhookEvent, s)
|
||||
|
|
|
@ -50,6 +50,7 @@ type Pipeline struct {
|
|||
ChangedFiles []string `json:"changed_files,omitempty" xorm:"LONGTEXT 'changed_files'"`
|
||||
AdditionalVariables map[string]string `json:"variables,omitempty" xorm:"json 'additional_variables'"`
|
||||
PullRequestLabels []string `json:"pr_labels,omitempty" xorm:"json 'pr_labels'"`
|
||||
IsPrerelease bool `json:"is_prerelease,omitempty" xorm:"is_prerelease"`
|
||||
} // @name Pipeline
|
||||
|
||||
// TableName return database table name for xorm
|
||||
|
|
|
@ -116,7 +116,7 @@ var validDockerImageString = regexp.MustCompile(
|
|||
// Validate validates the required fields and formats.
|
||||
func (s *Secret) Validate() error {
|
||||
for _, event := range s.Events {
|
||||
if err := ValidateWebhookEvent(event); err != nil {
|
||||
if err := event.Validate(); err != nil {
|
||||
return errors.Join(err, ErrSecretEventInvalid)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,11 @@ func Create(ctx context.Context, _store store.Store, repo *model.Repo, pipeline
|
|||
|
||||
skipMatch := skipPipelineRegex.FindString(pipeline.Message)
|
||||
if len(skipMatch) > 0 {
|
||||
log.Debug().Str("repo", repo.FullName).Msgf("ignoring pipeline as skip-ci was found in the commit (%s) message '%s'", pipeline.Commit, pipeline.Message)
|
||||
ref := pipeline.Commit
|
||||
if len(ref) == 0 {
|
||||
ref = pipeline.Ref
|
||||
}
|
||||
log.Debug().Str("repo", repo.FullName).Msgf("ignoring pipeline as skip-ci was found in the commit (%s) message '%s'", ref, pipeline.Message)
|
||||
return nil, ErrFiltered
|
||||
}
|
||||
|
||||
|
|
|
@ -129,6 +129,7 @@ func metadataPipelineFromModelPipeline(pipeline *model.Pipeline, includeParent b
|
|||
},
|
||||
ChangedFiles: pipeline.ChangedFiles,
|
||||
PullRequestLabels: pipeline.PullRequestLabels,
|
||||
IsPrerelease: pipeline.IsPrerelease,
|
||||
},
|
||||
Cron: cron,
|
||||
}
|
||||
|
|
|
@ -267,7 +267,8 @@
|
|||
"pr": "Pull Request",
|
||||
"deploy": "Deploy",
|
||||
"cron": "Cron",
|
||||
"manual": "Manual"
|
||||
"manual": "Manual",
|
||||
"release": "Release"
|
||||
},
|
||||
"status": {
|
||||
"status": "Status: {status}",
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<Icon v-if="pipeline.event === 'pull_request'" name="pull-request" />
|
||||
<Icon v-else-if="pipeline.event === 'pull_request_closed'" name="pull-request-closed" />
|
||||
<Icon v-else-if="pipeline.event === 'deployment'" name="deployment" />
|
||||
<Icon v-else-if="pipeline.event === 'tag'" name="tag" />
|
||||
<Icon v-else-if="pipeline.event === 'tag' || pipeline.event === 'release'" name="tag" />
|
||||
<Icon v-else-if="pipeline.event === 'cron'" name="push" />
|
||||
<Icon v-else-if="pipeline.event === 'manual'" name="manual-pipeline" />
|
||||
<Icon v-else name="push" />
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<span class="truncate">{{ prettyRef }}</span>
|
||||
</router-link>
|
||||
<div v-else class="flex space-x-1 items-center min-w-0">
|
||||
<Icon v-if="pipeline.event === 'tag'" name="tag" />
|
||||
<Icon v-if="pipeline.event === 'tag' || pipeline.event === 'release'" name="tag" />
|
||||
|
||||
<span class="truncate">{{ prettyRef }}</span>
|
||||
</div>
|
||||
|
|
|
@ -102,6 +102,7 @@ function removeImage(image: string) {
|
|||
const secretEventsOptions: CheckboxOption[] = [
|
||||
{ value: WebhookEvents.Push, text: i18n.t('repo.pipeline.event.push') },
|
||||
{ value: WebhookEvents.Tag, text: i18n.t('repo.pipeline.event.tag') },
|
||||
{ value: WebhookEvents.Release, text: i18n.t('repo.pipeline.event.release') },
|
||||
{
|
||||
value: WebhookEvents.PullRequest,
|
||||
text: i18n.t('repo.pipeline.event.pr'),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
export enum WebhookEvents {
|
||||
Push = 'push',
|
||||
Tag = 'tag',
|
||||
Release = 'release',
|
||||
PullRequest = 'pull_request',
|
||||
PullRequestClosed = 'pull_request_closed',
|
||||
Deploy = 'deployment',
|
||||
|
|
|
@ -20,6 +20,7 @@ const (
|
|||
EventPull = "pull_request"
|
||||
EventPullClosed = "pull_request_closed"
|
||||
EventTag = "tag"
|
||||
EventRelease = "release"
|
||||
EventDeploy = "deployment"
|
||||
EventCron = "cron"
|
||||
EventManual = "manual"
|
||||
|
|
Loading…
Reference in a new issue