Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Teamcity webhook #18668

Closed
wants to merge 31 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c33926d
Create templates and translation strings.
strangedreamsNY Feb 8, 2022
1585424
Create TeamCityHook form model.
strangedreamsNY Feb 8, 2022
90890b8
Add translations
strangedreamsNY Feb 8, 2022
626c5d3
Add Meta and HookHandler. No interface matching since TeamCity doesn'…
strangedreamsNY Feb 8, 2022
e26ea44
Wire in TeamCity Webhook New/Edit post handlers.
strangedreamsNY Feb 8, 2022
faa0f98
Add Routes
strangedreamsNY Feb 8, 2022
a04e2b8
Update Teamcity.png, remove hidden whitespace.
strangedreamsNY Feb 8, 2022
f7a5427
Create templates and translation strings.
strangedreamsNY Feb 8, 2022
b4f1d8a
Create TeamCityHook form model.
strangedreamsNY Feb 8, 2022
af787b4
Add translations
strangedreamsNY Feb 8, 2022
6f685b7
Add Meta and HookHandler. No interface matching since TeamCity doesn'…
strangedreamsNY Feb 8, 2022
0c00340
Wire in TeamCity Webhook New/Edit post handlers.
strangedreamsNY Feb 8, 2022
e5fd009
Add Routes
strangedreamsNY Feb 8, 2022
634db8f
Update Teamcity.png, remove hidden whitespace.
strangedreamsNY Feb 8, 2022
5948c25
Merge remote-tracking branch 'origin/teamcity_webhook' into teamcity_…
strangedreamsNY Feb 8, 2022
ffea42e
Rebase onto latest. Resolve merge conflicts.
strangedreamsNY Feb 8, 2022
ec32633
Revert "Add translations"
strangedreamsNY Feb 8, 2022
86435f9
Add TeamCityHookForm.
strangedreamsNY Feb 8, 2022
cc51e42
Add Repo Webhooks for TeamCity with New and Edit handlers.
strangedreamsNY Feb 8, 2022
47805cb
Add TeamCity New/Edit Post webhooks to routes.
strangedreamsNY Feb 8, 2022
cd5bbce
Fix TeamCity hook signatures and templates. Use new references.
strangedreamsNY Feb 8, 2022
199510e
Added BearerToken property to HookTask
strangedreamsNY Feb 8, 2022
d0b1a3d
Replace Teamcity png logo with svg version
strangedreamsNY Feb 8, 2022
25f83a9
Add unit tests for Teamcity meta and payload.
strangedreamsNY Feb 8, 2022
7580432
Fix linting issues.
strangedreamsNY Feb 9, 2022
33e6466
Rename properties/variables to use URL and ID instead of "Url" and "Id"
strangedreamsNY Feb 9, 2022
d76ee61
Add teamcity hook to docs for swagger gen.
strangedreamsNY Feb 9, 2022
03f671a
Revert "update the comparison documents (#18669)"
strangedreamsNY Feb 9, 2022
cc9af8d
Revert "Restart zero worker if there is still work to do (#18658)"
strangedreamsNY Feb 9, 2022
b3f8e4b
Remove duplicate entries from rebase.
strangedreamsNY Feb 9, 2022
0b7a62e
Merge branch 'main' into teamcity_webhook
zeripath Feb 9, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions docs/content/doc/features/comparison.en-us.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ _Symbols used in table:_
| Repository Tokens with write rights | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Built-in Container Registry | [✘](https://github.com/go-gitea/gitea/issues/2316) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
| External git mirroring | ✓ | ✓ | ✘ | ✘ | ✓ | ✓ | ✓ |
| WebAuthn (2FA) | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ? |
| FIDO U2F (2FA) | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | |
| Built-in CI/CD | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ |
| Subgroups: groups within groups | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✓ |

Expand All @@ -66,7 +66,6 @@ _Symbols used in table:_
| Granular user roles (Code, Issues, Wiki etc) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
| Verified Committer | ⁄ | ✘ | ? | ✓ | ✓ | ✓ | ✘ |
| GPG Signed Commits | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
| SSH Signed Commits | ✓ | ✘ | ✘ | ✘ | ✘ | ? | ? |
| Reject unsigned commits | [✓](https://github.com/go-gitea/gitea/pull/9708) | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Repository Activity page | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Branch manager | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
Expand Down
3 changes: 1 addition & 2 deletions docs/content/doc/features/comparison.zh-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ _表格中的符号含义:_
| 仓库写权限令牌 | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ |
| 内置容器 Registry | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
| 外部 Git 镜像 | ✓ | ✓ | ✘ | ✘ | ✓ | ✓ | ✓ |
| WebAuthn (2FA) | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ? |
| FIDO U2F (2FA) | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ |
| 内置 CI/CD | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
| 子组织:组织内的组织 | ✘ | ✘ | ✘ | ✓ | ✓ | ✘ | ✓ |

Expand All @@ -64,7 +64,6 @@ _表格中的符号含义:_
| 细粒度用户角色 (例如 Code, Issues, Wiki) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ |
| 提交人的身份验证 | ✘ | ✘ | ? | ✓ | ✓ | ✓ | ✘ |
| GPG 签名的提交 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
| SSH 签名的提交 | ✓ | ✘ | ✘ | ✘ | ✘ | ? | ? |
| 拒绝未用通过验证的提交 | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ |
| 仓库活跃度页面 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 分支管理 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ |
Expand Down
3 changes: 3 additions & 0 deletions models/webhook/hooktask.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ type HookTask struct {
RequestInfo *HookRequest `xorm:"-"`
ResponseContent string `xorm:"TEXT"`
ResponseInfo *HookResponse `xorm:"-"`

// Used for Auth Headers.
BearerToken string
}

func init() {
Expand Down
1 change: 1 addition & 0 deletions models/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ const (
DINGTALK HookType = "dingtalk"
TELEGRAM HookType = "telegram"
MSTEAMS HookType = "msteams"
TEAMCITY HookType = "teamcity"
FEISHU HookType = "feishu"
MATRIX HookType = "matrix"
WECHATWORK HookType = "wechatwork"
Expand Down
3 changes: 0 additions & 3 deletions modules/queue/workerpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,6 @@ func (p *WorkerPool) hasNoWorkerScaling() bool {
return p.numberOfWorkers == 0 && (p.boostTimeout == 0 || p.boostWorkers == 0 || p.maxNumberOfWorkers == 0)
}

// zeroBoost will add a temporary boost worker for a no worker queue
// p.lock must be locked at the start of this function BUT it will be unlocked by the end of this function
// (This is because addWorkers has to be called whilst unlocked)
func (p *WorkerPool) zeroBoost() {
ctx, cancel := context.WithTimeout(p.baseCtx, p.boostTimeout)
mq := GetManager().GetManagedQueue(p.qid)
Expand Down
2 changes: 1 addition & 1 deletion modules/setting/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func newWebhookService() {
Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5)
Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool()
Webhook.AllowedHostList = sec.Key("ALLOWED_HOST_LIST").MustString("")
Webhook.Types = []string{"gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "feishu", "matrix", "wechatwork", "packagist"}
Webhook.Types = []string{"gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "teamcity", "feishu", "matrix", "wechatwork", "packagist"}
Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10)
Webhook.ProxyURL = sec.Key("PROXY_URL").MustString("")
if Webhook.ProxyURL != "" {
Expand Down
2 changes: 1 addition & 1 deletion modules/structs/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type CreateHookOptionConfig map[string]string
// CreateHookOption options when create a hook
type CreateHookOption struct {
// required: true
// enum: dingtalk,discord,gitea,gogs,msteams,slack,telegram,feishu,wechatwork,packagist
// enum: dingtalk,discord,gitea,gogs,msteams,teamcity,slack,telegram,feishu,wechatwork,packagist
Type string `json:"type" binding:"Required"`
// required: true
Config CreateHookOptionConfig `json:"config" binding:"Required"`
Expand Down
3 changes: 3 additions & 0 deletions options/locale/locale_bg-BG.ini
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,9 @@ settings.hook_type=Тип на куката
settings.slack_token=API ключ
settings.slack_domain=Домейн
settings.slack_channel=Канал
settings.teamcity_host_url = Host URL
settings.teamcity_vcs_root_id = VCS Root ID
settings.teamcity_auth_token = Authentication Token
settings.deploy_keys=Ключове за внедряване
settings.add_deploy_key=Добави ключ за внедряване
settings.title=Заглавие
Expand Down
4 changes: 4 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1943,6 +1943,9 @@ settings.hook_type = Hook Type
settings.slack_token = Token
settings.slack_domain = Domain
settings.slack_channel = Channel
settings.teamcity_host_url = Host URL
settings.teamcity_vcs_root_id = VCS Root ID
settings.teamcity_auth_token = Authentication Token
settings.add_web_hook_desc = Integrate <a target="_blank" rel="noreferrer" href="%s">%s</a> into your repository.
settings.web_hook_name_gitea = Gitea
settings.web_hook_name_gogs = Gogs
Expand All @@ -1952,6 +1955,7 @@ settings.web_hook_name_dingtalk = DingTalk
settings.web_hook_name_telegram = Telegram
settings.web_hook_name_matrix = Matrix
settings.web_hook_name_msteams = Microsoft Teams
settings.web_hook_name_teamcity = TeamCity
settings.web_hook_name_feishu_or_larksuite = Feishu / Lark Suite
settings.web_hook_name_feishu = Feishu
settings.web_hook_name_larksuite = Lark Suite
Expand Down
64 changes: 64 additions & 0 deletions public/img/teamcity.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
126 changes: 126 additions & 0 deletions routers/web/repo/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,6 +535,66 @@ func MSTeamsHooksNewPost(ctx *context.Context) {
ctx.Redirect(orCtx.Link)
}

// TeamCityHooksNewPost response for creating TeamCity hook
func TeamCityHooksNewPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.NewTeamCityHookForm)
ctx.Data["Title"] = ctx.Tr("repo.settings.add_webhook")
ctx.Data["PageIsSettingHooks"] = true
ctx.Data["PageIsSettingHooksNew"] = true
ctx.Data["Webhook"] = webhook.Webhook{HookEvent: &webhook.HookEvent{}}
ctx.Data["HookType"] = webhook.TEAMCITY

orCtx, err := getOrgRepoCtx(ctx)
if err != nil {
ctx.ServerError("getOrgRepoCtx", err)
}
ctx.Data["BaseLink"] = orCtx.Link

if ctx.HasError() {
ctx.HTML(200, orCtx.NewTemplate)
return
}

meta, err := json.Marshal(&webhook_service.TeamCityMeta{
HostURL: form.HostURL,
AuthToken: form.AuthToken,
VcsRootID: form.VcsRootID,
})
if err != nil {
ctx.ServerError("Marshal", err)
return
}

payloadURL, err := buildTeamCityURL(form)
if err != nil {
ctx.ServerError("buildTeamCityURL", err)
return
}

w := &webhook.Webhook{
RepoID: orCtx.RepoID,
URL: payloadURL,
ContentType: webhook.ContentTypeForm,
HookEvent: ParseHookEvent(form.WebhookForm),
IsActive: form.Active,
Type: webhook.TEAMCITY,
HTTPMethod: http.MethodPost,
Meta: string(meta),
OrgID: orCtx.OrgID,
IsSystemWebhook: orCtx.IsSystemWebhook,
}
if err := w.UpdateEvent(); err != nil {
ctx.ServerError("UpdateEvent", err)
return
} else if err := webhook.CreateWebhook(db.DefaultContext, w); err != nil {
ctx.ServerError("CreateWebhook", err)
return
}

ctx.Flash.Success(ctx.Tr("repo.settings.add_hook_success"))
ctx.Redirect(orCtx.Link)
}

// SlackHooksNewPost response for creating slack hook
func SlackHooksNewPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.NewSlackHookForm)
Expand Down Expand Up @@ -770,6 +830,8 @@ func checkWebhook(ctx *context.Context) (*orgRepoCtx, *webhook.Webhook) {
ctx.Data["DiscordHook"] = webhook_service.GetDiscordHook(w)
case webhook.TELEGRAM:
ctx.Data["TelegramHook"] = webhook_service.GetTelegramHook(w)
case webhook.TEAMCITY:
ctx.Data["TeamCityHook"] = webhook_service.GetTeamCityHook(w)
case webhook.MATRIX:
ctx.Data["MatrixHook"] = webhook_service.GetMatrixHook(w)
case webhook.PACKAGIST:
Expand Down Expand Up @@ -1126,6 +1188,70 @@ func MSTeamsHooksEditPost(ctx *context.Context) {
ctx.Redirect(fmt.Sprintf("%s/%d", orCtx.Link, w.ID))
}

// TeamCityHooksEditPost response for editing teamcity hook
func TeamCityHooksEditPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.NewTeamCityHookForm)

ctx.Data["Title"] = ctx.Tr("repo.settings")
ctx.Data["PageIsSettingHooks"] = true
ctx.Data["PageIsSettingHooksEdit"] = true

orCtx, w := checkWebhook(ctx)

if ctx.Written() {
return
}

ctx.Data["Webhook"] = w

if ctx.HasError() {
ctx.HTML(200, orCtx.NewTemplate)
return
}

meta, err := json.Marshal(&webhook_service.TeamCityMeta{
HostURL: form.HostURL,
AuthToken: form.AuthToken,
VcsRootID: form.VcsRootID,
})
if err != nil {
ctx.ServerError("Marshal", err)
return
}

w.URL, err = buildTeamCityURL(form)
if err != nil {
ctx.ServerError("buildTeamCityURL", err)
return
}

w.HTTPMethod = http.MethodPost
w.Meta = string(meta)
w.HookEvent = ParseHookEvent(form.WebhookForm)
w.IsActive = form.Active

if err := w.UpdateEvent(); err != nil {
ctx.ServerError("UpdateEvent", err)
return
} else if err := webhook.UpdateWebhook(w); err != nil {
ctx.ServerError("UpdateWebhook", err)
return
}

ctx.Flash.Success(ctx.Tr("repo.settings.update_hook_success"))
ctx.Redirect(fmt.Sprintf("%s/%d", orCtx.Link, w.ID))
}

// buildTeamCityURL returns the correct REST API url for a TeamCity POST request.
func buildTeamCityURL(meta *forms.NewTeamCityHookForm) (string, error) {
tcURL, err := url.Parse(meta.HostURL)
if err != nil {
return "", err
}

return fmt.Sprintf("%s/app/rest/vcs-root-instances/commitHookNotification?locator=vcsRoot:%s", tcURL, meta.VcsRootID), nil
}

// FeishuHooksEditPost response for editing feishu hook
func FeishuHooksEditPost(ctx *context.Context) {
form := web.GetForm(ctx).(*forms.NewFeishuHookForm)
Expand Down
Loading