From a925623e4aa0c1fa111ef725efed5d517630044b Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Tue, 13 May 2025 17:09:39 +0200 Subject: [PATCH 1/5] Add milestone to metadata Draft1 --- cli/exec/flags.go | 5 ++ cli/exec/metadata.go | 1 + pipeline/frontend/metadata/environment.go | 1 + pipeline/frontend/metadata/types.go | 19 ++++--- server/forge/forgejo/helper.go | 12 +++- server/forge/gitea/helper.go | 12 +++- server/forge/github/parse.go | 5 +- server/forge/gitlab/convert.go | 16 +++--- server/forge/gitlab/gitlab.go | 16 ++++-- server/model/pipeline.go | 67 ++++++++++++----------- server/pipeline/stepbuilder/metadata.go | 7 ++- 11 files changed, 98 insertions(+), 63 deletions(-) diff --git a/cli/exec/flags.go b/cli/exec/flags.go index b3368a92341..39d8b51408d 100644 --- a/cli/exec/flags.go +++ b/cli/exec/flags.go @@ -285,6 +285,11 @@ var flags = []cli.Flag{ Name: "commit-pull-labels", Usage: "Set the metadata environment variable \"CI_COMMIT_PULL_REQUEST_LABELS\".", }, + &cli.StringFlag{ + Sources: cli.EnvVars("CI_COMMIT_PULL_REQUEST_MILESTONE"), + Name: "commit-pull-milestone", + Usage: "Set the metadata environment variable \"CI_COMMIT_PULL_REQUEST_MILESTONE\".", + }, &cli.BoolFlag{ Sources: cli.EnvVars("CI_COMMIT_PRERELEASE"), Name: "commit-release-is-pre", diff --git a/cli/exec/metadata.go b/cli/exec/metadata.go index b757ae80312..934a81d9d83 100644 --- a/cli/exec/metadata.go +++ b/cli/exec/metadata.go @@ -109,6 +109,7 @@ func metadataFromContext(_ context.Context, c *cli.Command, axis matrix.Axis, w metadataFileAndOverrideOrDefault(c, "commit-author-avatar", func(s string) { m.Curr.Commit.Author.Avatar = s }, c.String) metadataFileAndOverrideOrDefault(c, "commit-pull-labels", func(sl []string) { m.Curr.Commit.PullRequestLabels = sl }, c.StringSlice) + metadataFileAndOverrideOrDefault(c, "commit-pull-milestone", func(s string) { m.Curr.Commit.PullRequestMilestone = s }, c.String) metadataFileAndOverrideOrDefault(c, "commit-release-is-pre", func(b bool) { m.Curr.Commit.IsPrerelease = b }, c.Bool) // Previous Pipeline diff --git a/pipeline/frontend/metadata/environment.go b/pipeline/frontend/metadata/environment.go index d95ac8762b3..357d6a2da0e 100644 --- a/pipeline/frontend/metadata/environment.go +++ b/pipeline/frontend/metadata/environment.go @@ -106,6 +106,7 @@ func (m *Metadata) Environ() map[string]string { setNonEmptyEnvVar(params, "CI_COMMIT_TARGET_BRANCH", targetBranch) setNonEmptyEnvVar(params, "CI_COMMIT_PULL_REQUEST", pullRegexp.FindString(pipeline.Commit.Ref)) setNonEmptyEnvVar(params, "CI_COMMIT_PULL_REQUEST_LABELS", strings.Join(pipeline.Commit.PullRequestLabels, ",")) + setNonEmptyEnvVar(params, "CI_COMMIT_PULL_REQUEST_MILESTONE", pipeline.Commit.PullRequestMilestone) } // Only export changed files if maxChangedFiles is not exceeded diff --git a/pipeline/frontend/metadata/types.go b/pipeline/frontend/metadata/types.go index 7b1084f65b7..c9bf601b1a7 100644 --- a/pipeline/frontend/metadata/types.go +++ b/pipeline/frontend/metadata/types.go @@ -59,15 +59,16 @@ type ( // Commit defines runtime metadata for a commit. Commit struct { - Sha string `json:"sha,omitempty"` - Ref string `json:"ref,omitempty"` - Refspec string `json:"refspec,omitempty"` - Branch string `json:"branch,omitempty"` - Message string `json:"message,omitempty"` - Author Author `json:"author,omitempty"` - ChangedFiles []string `json:"changed_files,omitempty"` - PullRequestLabels []string `json:"labels,omitempty"` - IsPrerelease bool `json:"is_prerelease,omitempty"` + Sha string `json:"sha,omitempty"` + Ref string `json:"ref,omitempty"` + Refspec string `json:"refspec,omitempty"` + Branch string `json:"branch,omitempty"` + Message string `json:"message,omitempty"` + Author Author `json:"author,omitempty"` + ChangedFiles []string `json:"changed_files,omitempty"` + PullRequestLabels []string `json:"labels,omitempty"` + PullRequestMilestone string `json:"milestone,omitempty"` + IsPrerelease bool `json:"is_prerelease,omitempty"` } // Author defines runtime metadata for a commit author. diff --git a/server/forge/forgejo/helper.go b/server/forge/forgejo/helper.go index 9e7f243cd6c..c10fe68eb5f 100644 --- a/server/forge/forgejo/helper.go +++ b/server/forge/forgejo/helper.go @@ -169,13 +169,21 @@ func pipelineFromPullRequest(hook *pullRequestHook) *model.Pipeline { hook.PullRequest.Head.Ref, hook.PullRequest.Base.Ref, ), - PullRequestLabels: convertLabels(hook.PullRequest.Labels), - FromFork: hook.PullRequest.Head.RepoID != hook.PullRequest.Base.RepoID, + PullRequestLabels: convertLabels(hook.PullRequest.Labels), + PullRequestMilestone: convertMilestone(hook.PullRequest.Milestone), + FromFork: hook.PullRequest.Head.RepoID != hook.PullRequest.Base.RepoID, } return pipeline } +func convertMilestone(mile *gitea.Milestone) string { + if mile == nil || mile.ID == 0 { + return "" + } + return mile.Title +} + func pipelineFromRelease(hook *releaseHook) *model.Pipeline { avatar := expandAvatar( hook.Repo.HTMLURL, diff --git a/server/forge/gitea/helper.go b/server/forge/gitea/helper.go index 9420d5fffc5..9ecb23fd69d 100644 --- a/server/forge/gitea/helper.go +++ b/server/forge/gitea/helper.go @@ -170,13 +170,21 @@ func pipelineFromPullRequest(hook *pullRequestHook) *model.Pipeline { hook.PullRequest.Head.Ref, hook.PullRequest.Base.Ref, ), - PullRequestLabels: convertLabels(hook.PullRequest.Labels), - FromFork: hook.PullRequest.Head.RepoID != hook.PullRequest.Base.RepoID, + PullRequestLabels: convertLabels(hook.PullRequest.Labels), + PullRequestMilestone: convertMilestone(hook.PullRequest.Milestone), + FromFork: hook.PullRequest.Head.RepoID != hook.PullRequest.Base.RepoID, } return pipeline } +func convertMilestone(mile *gitea.Milestone) string { + if mile == nil || mile.ID == 0 { + return "" + } + return mile.Title +} + func pipelineFromRelease(hook *releaseHook) *model.Pipeline { avatar := expandAvatar( hook.Repo.HTMLURL, diff --git a/server/forge/github/parse.go b/server/forge/github/parse.go index 8e1913b50c0..6762f742778 100644 --- a/server/forge/github/parse.go +++ b/server/forge/github/parse.go @@ -174,8 +174,9 @@ func parsePullHook(hook *github.PullRequestEvent, merge bool) (*github.PullReque hook.GetPullRequest().GetHead().GetRef(), hook.GetPullRequest().GetBase().GetRef(), ), - PullRequestLabels: convertLabels(hook.GetPullRequest().Labels), - FromFork: fromFork, + PullRequestLabels: convertLabels(hook.GetPullRequest().Labels), + PullRequestMilestone: hook.GetPullRequest().GetMilestone().GetTitle(), + FromFork: fromFork, } if merge { pipeline.Ref = fmt.Sprintf(mergeRefs, hook.GetPullRequest().GetNumber()) diff --git a/server/forge/gitlab/convert.go b/server/forge/gitlab/convert.go index fc1af692972..78e179f8d58 100644 --- a/server/forge/gitlab/convert.go +++ b/server/forge/gitlab/convert.go @@ -63,9 +63,9 @@ func (g *GitLab) convertGitLabRepo(_repo *gitlab.Project, projectMember *gitlab. return repo, nil } -func convertMergeRequestHook(hook *gitlab.MergeEvent, req *http.Request) (int, *model.Repo, *model.Pipeline, error) { - repo := &model.Repo{} - pipeline := &model.Pipeline{} +func convertMergeRequestHook(hook *gitlab.MergeEvent, req *http.Request) (mergeIID int, milestoneID int, repo *model.Repo, pipeline *model.Pipeline, err error) { + repo = &model.Repo{} + pipeline = &model.Pipeline{} target := hook.ObjectAttributes.Target source := hook.ObjectAttributes.Source @@ -73,17 +73,17 @@ func convertMergeRequestHook(hook *gitlab.MergeEvent, req *http.Request) (int, * switch { case target == nil && source == nil: - return 0, nil, nil, fmt.Errorf("target and source keys expected in merge request hook") + return 0, 0, nil, nil, fmt.Errorf("target and source keys expected in merge request hook") case target == nil: - return 0, nil, nil, fmt.Errorf("target key expected in merge request hook") + return 0, 0, nil, nil, fmt.Errorf("target key expected in merge request hook") case source == nil: - return 0, nil, nil, fmt.Errorf("source key expected in merge request hook") + return 0, 0, nil, nil, fmt.Errorf("source key expected in merge request hook") } if target.PathWithNamespace != "" { var err error if repo.Owner, repo.Name, err = extractFromPath(target.PathWithNamespace); err != nil { - return 0, nil, nil, err + return 0, 0, nil, nil, err } repo.FullName = target.PathWithNamespace } else { @@ -140,7 +140,7 @@ func convertMergeRequestHook(hook *gitlab.MergeEvent, req *http.Request) (int, * pipeline.PullRequestLabels = convertLabels(hook.Labels) pipeline.FromFork = target.PathWithNamespace != source.PathWithNamespace - return obj.IID, repo, pipeline, nil + return obj.IID, hook.ObjectAttributes.MilestoneID, repo, pipeline, nil } func convertPushHook(hook *gitlab.PushEvent) (*model.Repo, *model.Pipeline, error) { diff --git a/server/forge/gitlab/gitlab.go b/server/forge/gitlab/gitlab.go index b3f31dc80d4..1d66702ff3b 100644 --- a/server/forge/gitlab/gitlab.go +++ b/server/forge/gitlab/gitlab.go @@ -28,7 +28,7 @@ import ( "time" "github.com/rs/zerolog/log" - "gitlab.com/gitlab-org/api/client-go" + gitlab "gitlab.com/gitlab-org/api/client-go" "golang.org/x/oauth2" "go.woodpecker-ci.org/woodpecker/v3/server" @@ -646,12 +646,12 @@ func (g *GitLab) Hook(ctx context.Context, req *http.Request) (*model.Repo, *mod if event.ObjectAttributes.OldRev == "" && event.ObjectAttributes.Action != "open" && event.ObjectAttributes.Action != "close" && event.ObjectAttributes.Action != "merge" { return nil, nil, &forge_types.ErrIgnoreEvent{Event: string(eventType), Reason: "no code changes"} } - mergeIID, repo, pipeline, err := convertMergeRequestHook(event, req) + mergeIID, milestoneID, repo, pipeline, err := convertMergeRequestHook(event, req) if err != nil { return nil, nil, err } - if pipeline, err = g.loadChangedFilesFromMergeRequest(ctx, repo, pipeline, mergeIID); err != nil { + if pipeline, err = g.loadMetadataFromMergeRequest(ctx, repo, pipeline, mergeIID, milestoneID); err != nil { return nil, nil, err } @@ -776,7 +776,7 @@ func (g *GitLab) Org(ctx context.Context, u *model.User, owner string) (*model.O }, nil } -func (g *GitLab) loadChangedFilesFromMergeRequest(ctx context.Context, tmpRepo *model.Repo, pipeline *model.Pipeline, mergeIID int) (*model.Pipeline, error) { +func (g *GitLab) loadMetadataFromMergeRequest(ctx context.Context, tmpRepo *model.Repo, pipeline *model.Pipeline, mergeIID, milestoneID int) (*model.Pipeline, error) { _store, ok := store.TryFromContext(ctx) if !ok { log.Error().Msg("could not get store from context") @@ -814,5 +814,13 @@ func (g *GitLab) loadChangedFilesFromMergeRequest(ctx context.Context, tmpRepo * } pipeline.ChangedFiles = utils.DeduplicateStrings(files) + if milestoneID != 0 { + milestone, _, err := client.Milestones.GetMilestone(_repo.ID, milestoneID) + if err != nil { + return nil, err + } + pipeline.PullRequestMilestone = milestone.Title + } + return pipeline, nil } diff --git a/server/model/pipeline.go b/server/model/pipeline.go index b74e8184ac6..6930843f54e 100644 --- a/server/model/pipeline.go +++ b/server/model/pipeline.go @@ -20,39 +20,40 @@ import ( ) type Pipeline struct { - ID int64 `json:"id" xorm:"pk autoincr 'id'"` - RepoID int64 `json:"-" xorm:"UNIQUE(s) INDEX 'repo_id'"` - Number int64 `json:"number" xorm:"UNIQUE(s) 'number'"` - Author string `json:"author" xorm:"INDEX 'author'"` - Parent int64 `json:"parent" xorm:"parent"` - Event WebhookEvent `json:"event" xorm:"event"` - Status StatusValue `json:"status" xorm:"INDEX 'status'"` - Errors []*types.PipelineError `json:"errors" xorm:"json 'errors'"` - Created int64 `json:"created" xorm:"'created' NOT NULL DEFAULT 0 created"` - Updated int64 `json:"updated" xorm:"'updated' NOT NULL DEFAULT 0 updated"` - Started int64 `json:"started" xorm:"started"` - Finished int64 `json:"finished" xorm:"finished"` - DeployTo string `json:"deploy_to" xorm:"deploy"` - DeployTask string `json:"deploy_task" xorm:"deploy_task"` - Commit string `json:"commit" xorm:"commit"` - Branch string `json:"branch" xorm:"branch"` - Ref string `json:"ref" xorm:"ref"` - Refspec string `json:"refspec" xorm:"refspec"` - Title string `json:"title" xorm:"title"` - Message string `json:"message" xorm:"TEXT 'message'"` - Timestamp int64 `json:"timestamp" xorm:"'timestamp'"` - Sender string `json:"sender" xorm:"sender"` // uses reported user for webhooks and name of cron for cron pipelines - Avatar string `json:"author_avatar" xorm:"varchar(500) avatar"` - Email string `json:"author_email" xorm:"varchar(500) email"` - ForgeURL string `json:"forge_url" xorm:"forge_url"` - Reviewer string `json:"reviewed_by" xorm:"reviewer"` - Reviewed int64 `json:"reviewed" xorm:"reviewed"` - Workflows []*Workflow `json:"workflows,omitempty" xorm:"-"` - 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"` - FromFork bool `json:"from_fork,omitempty" xorm:"from_fork"` + ID int64 `json:"id" xorm:"pk autoincr 'id'"` + RepoID int64 `json:"-" xorm:"UNIQUE(s) INDEX 'repo_id'"` + Number int64 `json:"number" xorm:"UNIQUE(s) 'number'"` + Author string `json:"author" xorm:"INDEX 'author'"` + Parent int64 `json:"parent" xorm:"parent"` + Event WebhookEvent `json:"event" xorm:"event"` + Status StatusValue `json:"status" xorm:"INDEX 'status'"` + Errors []*types.PipelineError `json:"errors" xorm:"json 'errors'"` + Created int64 `json:"created" xorm:"'created' NOT NULL DEFAULT 0 created"` + Updated int64 `json:"updated" xorm:"'updated' NOT NULL DEFAULT 0 updated"` + Started int64 `json:"started" xorm:"started"` + Finished int64 `json:"finished" xorm:"finished"` + DeployTo string `json:"deploy_to" xorm:"deploy"` + DeployTask string `json:"deploy_task" xorm:"deploy_task"` + Commit string `json:"commit" xorm:"commit"` + Branch string `json:"branch" xorm:"branch"` + Ref string `json:"ref" xorm:"ref"` + Refspec string `json:"refspec" xorm:"refspec"` + Title string `json:"title" xorm:"title"` + Message string `json:"message" xorm:"TEXT 'message'"` + Timestamp int64 `json:"timestamp" xorm:"'timestamp'"` + Sender string `json:"sender" xorm:"sender"` // uses reported user for webhooks and name of cron for cron pipelines + Avatar string `json:"author_avatar" xorm:"varchar(500) avatar"` + Email string `json:"author_email" xorm:"varchar(500) email"` + ForgeURL string `json:"forge_url" xorm:"forge_url"` + Reviewer string `json:"reviewed_by" xorm:"reviewer"` + Reviewed int64 `json:"reviewed" xorm:"reviewed"` + Workflows []*Workflow `json:"workflows,omitempty" xorm:"-"` + 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'"` + PullRequestMilestone string `json:"pr_milestone,omitempty" xorm:"pr_milestone"` + IsPrerelease bool `json:"is_prerelease,omitempty" xorm:"is_prerelease"` + FromFork bool `json:"from_fork,omitempty" xorm:"from_fork"` } // @name Pipeline // TableName return database table name for xorm. diff --git a/server/pipeline/stepbuilder/metadata.go b/server/pipeline/stepbuilder/metadata.go index 8ceb0dbcd00..2d133a12c36 100644 --- a/server/pipeline/stepbuilder/metadata.go +++ b/server/pipeline/stepbuilder/metadata.go @@ -132,9 +132,10 @@ func metadataPipelineFromModelPipeline(pipeline *model.Pipeline, includeParent b Email: pipeline.Email, Avatar: pipeline.Avatar, }, - ChangedFiles: pipeline.ChangedFiles, - PullRequestLabels: pipeline.PullRequestLabels, - IsPrerelease: pipeline.IsPrerelease, + ChangedFiles: pipeline.ChangedFiles, + PullRequestLabels: pipeline.PullRequestLabels, + PullRequestMilestone: pipeline.PullRequestMilestone, + IsPrerelease: pipeline.IsPrerelease, }, Cron: cron, } From 828585fc1acd892f2af0e841f5f44528a870ffe1 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Wed, 14 May 2025 00:53:30 +0200 Subject: [PATCH 2/5] fix --- cmd/server/openapi/docs.go | 6 ++++++ server/forge/forgejo/helper.go | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cmd/server/openapi/docs.go b/cmd/server/openapi/docs.go index cbe3ed13dfa..2b11b7e6188 100644 --- a/cmd/server/openapi/docs.go +++ b/cmd/server/openapi/docs.go @@ -4946,6 +4946,9 @@ const docTemplate = `{ "type": "string" } }, + "pr_milestone": { + "type": "string" + }, "ref": { "type": "string" }, @@ -5542,6 +5545,9 @@ const docTemplate = `{ "message": { "type": "string" }, + "milestone": { + "type": "string" + }, "ref": { "type": "string" }, diff --git a/server/forge/forgejo/helper.go b/server/forge/forgejo/helper.go index c10fe68eb5f..ec90beb869e 100644 --- a/server/forge/forgejo/helper.go +++ b/server/forge/forgejo/helper.go @@ -177,7 +177,7 @@ func pipelineFromPullRequest(hook *pullRequestHook) *model.Pipeline { return pipeline } -func convertMilestone(mile *gitea.Milestone) string { +func convertMilestone(mile *forgejo.Milestone) string { if mile == nil || mile.ID == 0 { return "" } From c61b0276967777d41d8a42702d110c66d4d06b62 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Wed, 14 May 2025 00:56:31 +0200 Subject: [PATCH 3/5] update docs --- docs/docs/20-usage/50-environment.md | 177 ++++++++++++++------------- 1 file changed, 89 insertions(+), 88 deletions(-) diff --git a/docs/docs/20-usage/50-environment.md b/docs/docs/20-usage/50-environment.md index 746cb7634dd..60428864eab 100644 --- a/docs/docs/20-usage/50-environment.md +++ b/docs/docs/20-usage/50-environment.md @@ -48,94 +48,95 @@ Please note that the environment section is not able to expand environment varia This is the reference list of all environment variables available to your pipeline containers. These are injected into your pipeline step and plugins containers, at runtime. -| NAME | Description | Example | -| -------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | -| `CI` | CI environment name | `woodpecker` | -| | **Repository** | | -| `CI_REPO` | repository full name `/` | `john-doe/my-repo` | -| `CI_REPO_OWNER` | repository owner | `john-doe` | -| `CI_REPO_NAME` | repository name | `my-repo` | -| `CI_REPO_REMOTE_ID` | repository remote ID, is the UID it has in the forge | `82` | -| `CI_REPO_URL` | repository web URL | `https://git.example.com/john-doe/my-repo` | -| `CI_REPO_CLONE_URL` | repository clone URL | `https://git.example.com/john-doe/my-repo.git` | -| `CI_REPO_CLONE_SSH_URL` | repository SSH clone URL | `git@git.example.com:john-doe/my-repo.git` | -| `CI_REPO_DEFAULT_BRANCH` | repository default branch | `main` | -| `CI_REPO_PRIVATE` | repository is private | `true` | -| `CI_REPO_TRUSTED_NETWORK` | repository has trusted network access | `false` | -| `CI_REPO_TRUSTED_VOLUMES` | repository has trusted volumes access | `false` | -| `CI_REPO_TRUSTED_SECURITY` | repository has trusted security access | `false` | -| | **Current Commit** | | -| `CI_COMMIT_SHA` | commit SHA | `eba09b46064473a1d345da7abf28b477468e8dbd` | -| `CI_COMMIT_REF` | commit ref | `refs/heads/main` | -| `CI_COMMIT_REFSPEC` | commit ref spec | `issue-branch:main` | -| `CI_COMMIT_BRANCH` | commit branch (equals target branch for pull requests) | `main` | -| `CI_COMMIT_SOURCE_BRANCH` | commit source branch (set only for `pull_request` and `pull_request_closed` events) | `issue-branch` | -| `CI_COMMIT_TARGET_BRANCH` | commit target branch (set only for `pull_request` and `pull_request_closed` events) | `main` | -| `CI_COMMIT_TAG` | commit tag name (empty if event is not `tag`) | `v1.10.3` | -| `CI_COMMIT_PULL_REQUEST` | commit pull request number (set only for `pull_request` and `pull_request_closed` events) | `1` | -| `CI_COMMIT_PULL_REQUEST_LABELS` | labels assigned to pull request (set only for `pull_request` and `pull_request_closed` events) | `server` | -| `CI_COMMIT_MESSAGE` | commit message | `Initial commit` | -| `CI_COMMIT_AUTHOR` | commit author username | `john-doe` | -| `CI_COMMIT_AUTHOR_EMAIL` | commit author email address | `john-doe@example.com` | -| `CI_COMMIT_AUTHOR_AVATAR` | commit author avatar | `https://git.example.com/avatars/5dcbcadbce6f87f8abef` | -| `CI_COMMIT_PRERELEASE` | release is a pre-release (empty if event is not `release`) | `false` | -| | **Current pipeline** | | -| `CI_PIPELINE_NUMBER` | pipeline number | `8` | -| `CI_PIPELINE_PARENT` | number of parent pipeline | `0` | -| `CI_PIPELINE_EVENT` | pipeline event (see [`event`](../20-usage/20-workflow-syntax.md#event)) | `push`, `pull_request`, `pull_request_closed`, `tag`, `release`, `manual`, `cron` | -| `CI_PIPELINE_URL` | link to the web UI for the pipeline | `https://ci.example.com/repos/7/pipeline/8` | -| `CI_PIPELINE_FORGE_URL` | link to the forge's web UI for the commit(s) or tag that triggered the pipeline | `https://git.example.com/john-doe/my-repo/commit/eba09b46064473a1d345da7abf28b477468e8dbd` | -| `CI_PIPELINE_DEPLOY_TARGET` | pipeline deploy target for `deployment` events | `production` | -| `CI_PIPELINE_DEPLOY_TASK` | pipeline deploy task for `deployment` events | `migration` | -| `CI_PIPELINE_CREATED` | pipeline created UNIX timestamp | `1722617519` | -| `CI_PIPELINE_STARTED` | pipeline started UNIX timestamp | `1722617519` | -| `CI_PIPELINE_FILES` | changed files (empty if event is not `push` or `pull_request`), it is undefined if more than 500 files are touched | `[]`, `[".woodpecker.yml","README.md"]` | -| | **Current workflow** | | -| `CI_WORKFLOW_NAME` | workflow name | `release` | -| | **Current step** | | -| `CI_STEP_NAME` | step name | `build package` | -| `CI_STEP_NUMBER` | step number | `0` | -| `CI_STEP_STARTED` | step started UNIX timestamp | `1722617519` | -| `CI_STEP_URL` | URL to step in UI | `https://ci.example.com/repos/7/pipeline/8` | -| | **Previous commit** | | -| `CI_PREV_COMMIT_SHA` | previous commit SHA | `15784117e4e103f36cba75a9e29da48046eb82c4` | -| `CI_PREV_COMMIT_REF` | previous commit ref | `refs/heads/main` | -| `CI_PREV_COMMIT_REFSPEC` | previous commit ref spec | `issue-branch:main` | -| `CI_PREV_COMMIT_BRANCH` | previous commit branch | `main` | -| `CI_PREV_COMMIT_SOURCE_BRANCH` | previous commit source branch (set only for `pull_request` and `pull_request_closed` events) | `issue-branch` | -| `CI_PREV_COMMIT_TARGET_BRANCH` | previous commit target branch (set only for `pull_request` and `pull_request_closed` events) | `main` | -| `CI_PREV_COMMIT_URL` | previous commit link in forge | `https://git.example.com/john-doe/my-repo/commit/15784117e4e103f36cba75a9e29da48046eb82c4` | -| `CI_PREV_COMMIT_MESSAGE` | previous commit message | `test` | -| `CI_PREV_COMMIT_AUTHOR` | previous commit author username | `john-doe` | -| `CI_PREV_COMMIT_AUTHOR_EMAIL` | previous commit author email address | `john-doe@example.com` | -| `CI_PREV_COMMIT_AUTHOR_AVATAR` | previous commit author avatar | `https://git.example.com/avatars/12` | -| | **Previous pipeline** | | -| `CI_PREV_PIPELINE_NUMBER` | previous pipeline number | `7` | -| `CI_PREV_PIPELINE_PARENT` | previous pipeline number of parent pipeline | `0` | -| `CI_PREV_PIPELINE_EVENT` | previous pipeline event (see [`event`](../20-usage/20-workflow-syntax.md#event)) | `push`, `pull_request`, `pull_request_closed`, `tag`, `release`, `manual`, `cron` | -| `CI_PREV_PIPELINE_URL` | previous pipeline link in CI | `https://ci.example.com/repos/7/pipeline/7` | -| `CI_PREV_PIPELINE_FORGE_URL` | previous pipeline link to event in forge | `https://git.example.com/john-doe/my-repo/commit/15784117e4e103f36cba75a9e29da48046eb82c4` | -| `CI_PREV_PIPELINE_DEPLOY_TARGET` | previous pipeline deploy target for `deployment` events | `production` | -| `CI_PREV_PIPELINE_DEPLOY_TASK` | previous pipeline deploy task for `deployment` events | `migration` | -| `CI_PREV_PIPELINE_STATUS` | previous pipeline status | `success`, `failure` | -| `CI_PREV_PIPELINE_CREATED` | previous pipeline created UNIX timestamp | `1722610173` | -| `CI_PREV_PIPELINE_STARTED` | previous pipeline started UNIX timestamp | `1722610173` | -| `CI_PREV_PIPELINE_FINISHED` | previous pipeline finished UNIX timestamp | `1722610383` | -| |   | | -| `CI_WORKSPACE` | Path of the workspace where source code gets cloned to | `/woodpecker/src/git.example.com/john-doe/my-repo` | -| | **System** | | -| `CI_SYSTEM_NAME` | name of the CI system | `woodpecker` | -| `CI_SYSTEM_URL` | link to CI system | `https://ci.example.com` | -| `CI_SYSTEM_HOST` | hostname of CI server | `ci.example.com` | -| `CI_SYSTEM_VERSION` | version of the server | `2.7.0` | -| | **Forge** | | -| `CI_FORGE_TYPE` | name of forge | `bitbucket` , `bitbucket_dc` , `forgejo` , `gitea` , `github` , `gitlab` | -| `CI_FORGE_URL` | root URL of configured forge | `https://git.example.com` | -| | **Internal** - Please don't use! | | -| `CI_SCRIPT` | Internal script path. Used to call pipeline step commands. | | -| `CI_NETRC_USERNAME` | Credentials for private repos to be able to clone data. (Only available for specific images) | | -| `CI_NETRC_PASSWORD` | Credentials for private repos to be able to clone data. (Only available for specific images) | | -| `CI_NETRC_MACHINE` | Credentials for private repos to be able to clone data. (Only available for specific images) | | +| NAME | Description | Example | +| ---------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------ | +| `CI` | CI environment name | `woodpecker` | +| | **Repository** | | +| `CI_REPO` | repository full name `/` | `john-doe/my-repo` | +| `CI_REPO_OWNER` | repository owner | `john-doe` | +| `CI_REPO_NAME` | repository name | `my-repo` | +| `CI_REPO_REMOTE_ID` | repository remote ID, is the UID it has in the forge | `82` | +| `CI_REPO_URL` | repository web URL | `https://git.example.com/john-doe/my-repo` | +| `CI_REPO_CLONE_URL` | repository clone URL | `https://git.example.com/john-doe/my-repo.git` | +| `CI_REPO_CLONE_SSH_URL` | repository SSH clone URL | `git@git.example.com:john-doe/my-repo.git` | +| `CI_REPO_DEFAULT_BRANCH` | repository default branch | `main` | +| `CI_REPO_PRIVATE` | repository is private | `true` | +| `CI_REPO_TRUSTED_NETWORK` | repository has trusted network access | `false` | +| `CI_REPO_TRUSTED_VOLUMES` | repository has trusted volumes access | `false` | +| `CI_REPO_TRUSTED_SECURITY` | repository has trusted security access | `false` | +| | **Current Commit** | | +| `CI_COMMIT_SHA` | commit SHA | `eba09b46064473a1d345da7abf28b477468e8dbd` | +| `CI_COMMIT_REF` | commit ref | `refs/heads/main` | +| `CI_COMMIT_REFSPEC` | commit ref spec | `issue-branch:main` | +| `CI_COMMIT_BRANCH` | commit branch (equals target branch for pull requests) | `main` | +| `CI_COMMIT_SOURCE_BRANCH` | commit source branch (set only for `pull_request` and `pull_request_closed` events) | `issue-branch` | +| `CI_COMMIT_TARGET_BRANCH` | commit target branch (set only for `pull_request` and `pull_request_closed` events) | `main` | +| `CI_COMMIT_TAG` | commit tag name (empty if event is not `tag`) | `v1.10.3` | +| `CI_COMMIT_PULL_REQUEST` | commit pull request number (set only for `pull_request` and `pull_request_closed` events) | `1` | +| `CI_COMMIT_PULL_REQUEST_LABELS` | labels assigned to pull request (set only for `pull_request` and `pull_request_closed` events) | `server` | +| `CI_COMMIT_PULL_REQUEST_MILESTONE` | milestone assigned to pull request (set only for `pull_request` and `pull_request_closed` events) | `summer-sprint` | +| `CI_COMMIT_MESSAGE` | commit message | `Initial commit` | +| `CI_COMMIT_AUTHOR` | commit author username | `john-doe` | +| `CI_COMMIT_AUTHOR_EMAIL` | commit author email address | `john-doe@example.com` | +| `CI_COMMIT_AUTHOR_AVATAR` | commit author avatar | `https://git.example.com/avatars/5dcbcadbce6f87f8abef` | +| `CI_COMMIT_PRERELEASE` | release is a pre-release (empty if event is not `release`) | `false` | +| | **Current pipeline** | | +| `CI_PIPELINE_NUMBER` | pipeline number | `8` | +| `CI_PIPELINE_PARENT` | number of parent pipeline | `0` | +| `CI_PIPELINE_EVENT` | pipeline event (see [`event`](../20-usage/20-workflow-syntax.md#event)) | `push`, `pull_request`, `pull_request_closed`, `tag`, `release`, `manual`, `cron` | +| `CI_PIPELINE_URL` | link to the web UI for the pipeline | `https://ci.example.com/repos/7/pipeline/8` | +| `CI_PIPELINE_FORGE_URL` | link to the forge's web UI for the commit(s) or tag that triggered the pipeline | `https://git.example.com/john-doe/my-repo/commit/eba09b46064473a1d345da7abf28b477468e8dbd` | +| `CI_PIPELINE_DEPLOY_TARGET` | pipeline deploy target for `deployment` events | `production` | +| `CI_PIPELINE_DEPLOY_TASK` | pipeline deploy task for `deployment` events | `migration` | +| `CI_PIPELINE_CREATED` | pipeline created UNIX timestamp | `1722617519` | +| `CI_PIPELINE_STARTED` | pipeline started UNIX timestamp | `1722617519` | +| `CI_PIPELINE_FILES` | changed files (empty if event is not `push` or `pull_request`), it is undefined if more than 500 files are touched | `[]`, `[".woodpecker.yml","README.md"]` | +| | **Current workflow** | | +| `CI_WORKFLOW_NAME` | workflow name | `release` | +| | **Current step** | | +| `CI_STEP_NAME` | step name | `build package` | +| `CI_STEP_NUMBER` | step number | `0` | +| `CI_STEP_STARTED` | step started UNIX timestamp | `1722617519` | +| `CI_STEP_URL` | URL to step in UI | `https://ci.example.com/repos/7/pipeline/8` | +| | **Previous commit** | | +| `CI_PREV_COMMIT_SHA` | previous commit SHA | `15784117e4e103f36cba75a9e29da48046eb82c4` | +| `CI_PREV_COMMIT_REF` | previous commit ref | `refs/heads/main` | +| `CI_PREV_COMMIT_REFSPEC` | previous commit ref spec | `issue-branch:main` | +| `CI_PREV_COMMIT_BRANCH` | previous commit branch | `main` | +| `CI_PREV_COMMIT_SOURCE_BRANCH` | previous commit source branch (set only for `pull_request` and `pull_request_closed` events) | `issue-branch` | +| `CI_PREV_COMMIT_TARGET_BRANCH` | previous commit target branch (set only for `pull_request` and `pull_request_closed` events) | `main` | +| `CI_PREV_COMMIT_URL` | previous commit link in forge | `https://git.example.com/john-doe/my-repo/commit/15784117e4e103f36cba75a9e29da48046eb82c4` | +| `CI_PREV_COMMIT_MESSAGE` | previous commit message | `test` | +| `CI_PREV_COMMIT_AUTHOR` | previous commit author username | `john-doe` | +| `CI_PREV_COMMIT_AUTHOR_EMAIL` | previous commit author email address | `john-doe@example.com` | +| `CI_PREV_COMMIT_AUTHOR_AVATAR` | previous commit author avatar | `https://git.example.com/avatars/12` | +| | **Previous pipeline** | | +| `CI_PREV_PIPELINE_NUMBER` | previous pipeline number | `7` | +| `CI_PREV_PIPELINE_PARENT` | previous pipeline number of parent pipeline | `0` | +| `CI_PREV_PIPELINE_EVENT` | previous pipeline event (see [`event`](../20-usage/20-workflow-syntax.md#event)) | `push`, `pull_request`, `pull_request_closed`, `tag`, `release`, `manual`, `cron` | +| `CI_PREV_PIPELINE_URL` | previous pipeline link in CI | `https://ci.example.com/repos/7/pipeline/7` | +| `CI_PREV_PIPELINE_FORGE_URL` | previous pipeline link to event in forge | `https://git.example.com/john-doe/my-repo/commit/15784117e4e103f36cba75a9e29da48046eb82c4` | +| `CI_PREV_PIPELINE_DEPLOY_TARGET` | previous pipeline deploy target for `deployment` events | `production` | +| `CI_PREV_PIPELINE_DEPLOY_TASK` | previous pipeline deploy task for `deployment` events | `migration` | +| `CI_PREV_PIPELINE_STATUS` | previous pipeline status | `success`, `failure` | +| `CI_PREV_PIPELINE_CREATED` | previous pipeline created UNIX timestamp | `1722610173` | +| `CI_PREV_PIPELINE_STARTED` | previous pipeline started UNIX timestamp | `1722610173` | +| `CI_PREV_PIPELINE_FINISHED` | previous pipeline finished UNIX timestamp | `1722610383` | +| |   | | +| `CI_WORKSPACE` | Path of the workspace where source code gets cloned to | `/woodpecker/src/git.example.com/john-doe/my-repo` | +| | **System** | | +| `CI_SYSTEM_NAME` | name of the CI system | `woodpecker` | +| `CI_SYSTEM_URL` | link to CI system | `https://ci.example.com` | +| `CI_SYSTEM_HOST` | hostname of CI server | `ci.example.com` | +| `CI_SYSTEM_VERSION` | version of the server | `2.7.0` | +| | **Forge** | | +| `CI_FORGE_TYPE` | name of forge | `bitbucket` , `bitbucket_dc` , `forgejo` , `gitea` , `github` , `gitlab` | +| `CI_FORGE_URL` | root URL of configured forge | `https://git.example.com` | +| | **Internal** - Please don't use! | | +| `CI_SCRIPT` | Internal script path. Used to call pipeline step commands. | | +| `CI_NETRC_USERNAME` | Credentials for private repos to be able to clone data. (Only available for specific images) | | +| `CI_NETRC_PASSWORD` | Credentials for private repos to be able to clone data. (Only available for specific images) | | +| `CI_NETRC_MACHINE` | Credentials for private repos to be able to clone data. (Only available for specific images) | | ## Global environment variables From 234185044c0bd721feeecefb590f0c2d8cd6dd17 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Thu, 15 May 2025 15:09:26 +0200 Subject: [PATCH 4/5] address review --- server/forge/forgejo/helper.go | 6 +++--- server/forge/gitea/helper.go | 6 +++--- server/forge/gitlab/convert.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/server/forge/forgejo/helper.go b/server/forge/forgejo/helper.go index ec90beb869e..7b20e35d8cc 100644 --- a/server/forge/forgejo/helper.go +++ b/server/forge/forgejo/helper.go @@ -177,11 +177,11 @@ func pipelineFromPullRequest(hook *pullRequestHook) *model.Pipeline { return pipeline } -func convertMilestone(mile *forgejo.Milestone) string { - if mile == nil || mile.ID == 0 { +func convertMilestone(milestone *forgejo.Milestone) string { + if milestone == nil || milestone.ID == 0 { return "" } - return mile.Title + return milestone.Title } func pipelineFromRelease(hook *releaseHook) *model.Pipeline { diff --git a/server/forge/gitea/helper.go b/server/forge/gitea/helper.go index 9ecb23fd69d..5e310da8a36 100644 --- a/server/forge/gitea/helper.go +++ b/server/forge/gitea/helper.go @@ -178,11 +178,11 @@ func pipelineFromPullRequest(hook *pullRequestHook) *model.Pipeline { return pipeline } -func convertMilestone(mile *gitea.Milestone) string { - if mile == nil || mile.ID == 0 { +func convertMilestone(milestone *gitea.Milestone) string { + if milestone == nil || milestone.ID == 0 { return "" } - return mile.Title + return milestone.Title } func pipelineFromRelease(hook *releaseHook) *model.Pipeline { diff --git a/server/forge/gitlab/convert.go b/server/forge/gitlab/convert.go index 78e179f8d58..7a01bc1c3b9 100644 --- a/server/forge/gitlab/convert.go +++ b/server/forge/gitlab/convert.go @@ -63,7 +63,7 @@ func (g *GitLab) convertGitLabRepo(_repo *gitlab.Project, projectMember *gitlab. return repo, nil } -func convertMergeRequestHook(hook *gitlab.MergeEvent, req *http.Request) (mergeIID int, milestoneID int, repo *model.Repo, pipeline *model.Pipeline, err error) { +func convertMergeRequestHook(hook *gitlab.MergeEvent, req *http.Request) (mergeIID, milestoneID int, repo *model.Repo, pipeline *model.Pipeline, err error) { repo = &model.Repo{} pipeline = &model.Pipeline{} From 99516605e0b8bfe9411e24ae499c6051ba6321e5 Mon Sep 17 00:00:00 2001 From: "m.huber" Date: Mon, 19 May 2025 12:46:25 +0200 Subject: [PATCH 5/5] fix misspell --- server/forge/gitlab/convert.go | 2 +- server/forge/gitlab/gitlab.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/server/forge/gitlab/convert.go b/server/forge/gitlab/convert.go index 7a01bc1c3b9..d7262639220 100644 --- a/server/forge/gitlab/convert.go +++ b/server/forge/gitlab/convert.go @@ -63,7 +63,7 @@ func (g *GitLab) convertGitLabRepo(_repo *gitlab.Project, projectMember *gitlab. return repo, nil } -func convertMergeRequestHook(hook *gitlab.MergeEvent, req *http.Request) (mergeIID, milestoneID int, repo *model.Repo, pipeline *model.Pipeline, err error) { +func convertMergeRequestHook(hook *gitlab.MergeEvent, req *http.Request) (mergeID, milestoneID int, repo *model.Repo, pipeline *model.Pipeline, err error) { repo = &model.Repo{} pipeline = &model.Pipeline{} diff --git a/server/forge/gitlab/gitlab.go b/server/forge/gitlab/gitlab.go index 1d66702ff3b..37bd71f50a3 100644 --- a/server/forge/gitlab/gitlab.go +++ b/server/forge/gitlab/gitlab.go @@ -646,12 +646,12 @@ func (g *GitLab) Hook(ctx context.Context, req *http.Request) (*model.Repo, *mod if event.ObjectAttributes.OldRev == "" && event.ObjectAttributes.Action != "open" && event.ObjectAttributes.Action != "close" && event.ObjectAttributes.Action != "merge" { return nil, nil, &forge_types.ErrIgnoreEvent{Event: string(eventType), Reason: "no code changes"} } - mergeIID, milestoneID, repo, pipeline, err := convertMergeRequestHook(event, req) + mergeID, milestoneID, repo, pipeline, err := convertMergeRequestHook(event, req) if err != nil { return nil, nil, err } - if pipeline, err = g.loadMetadataFromMergeRequest(ctx, repo, pipeline, mergeIID, milestoneID); err != nil { + if pipeline, err = g.loadMetadataFromMergeRequest(ctx, repo, pipeline, mergeID, milestoneID); err != nil { return nil, nil, err } @@ -776,7 +776,7 @@ func (g *GitLab) Org(ctx context.Context, u *model.User, owner string) (*model.O }, nil } -func (g *GitLab) loadMetadataFromMergeRequest(ctx context.Context, tmpRepo *model.Repo, pipeline *model.Pipeline, mergeIID, milestoneID int) (*model.Pipeline, error) { +func (g *GitLab) loadMetadataFromMergeRequest(ctx context.Context, tmpRepo *model.Repo, pipeline *model.Pipeline, mergeID, milestoneID int) (*model.Pipeline, error) { _store, ok := store.TryFromContext(ctx) if !ok { log.Error().Msg("could not get store from context") @@ -803,7 +803,7 @@ func (g *GitLab) loadMetadataFromMergeRequest(ctx context.Context, tmpRepo *mode return nil, err } - changes, _, err := client.MergeRequests.ListMergeRequestDiffs(_repo.ID, mergeIID, &gitlab.ListMergeRequestDiffsOptions{}, gitlab.WithContext(ctx)) + changes, _, err := client.MergeRequests.ListMergeRequestDiffs(_repo.ID, mergeID, &gitlab.ListMergeRequestDiffsOptions{}, gitlab.WithContext(ctx)) if err != nil { return nil, err }