mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-11-25 11:16:11 +01:00
Merge pull request 'webhook: improve UX for sourcehut and matrix' (#3156) from oliverpool/forgejo:webhook_sourcehut_polish into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3156 Reviewed-by: Earl Warren <earl-warren@noreply.codeberg.org>
This commit is contained in:
commit
e4aa7bd511
|
@ -361,6 +361,15 @@ func (w Webhook) HeaderAuthorization() (string, error) {
|
||||||
return secret.DecryptSecret(setting.SecretKey, w.HeaderAuthorizationEncrypted)
|
return secret.DecryptSecret(setting.SecretKey, w.HeaderAuthorizationEncrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HeaderAuthorizationTrimPrefix returns the decrypted Authorization with a specified prefix trimmed.
|
||||||
|
func (w Webhook) HeaderAuthorizationTrimPrefix(prefix string) (string, error) {
|
||||||
|
s, err := w.HeaderAuthorization()
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.TrimPrefix(s, prefix), nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetHeaderAuthorization encrypts and sets the Authorization header.
|
// SetHeaderAuthorization encrypts and sets the Authorization header.
|
||||||
func (w *Webhook) SetHeaderAuthorization(cleartext string) error {
|
func (w *Webhook) SetHeaderAuthorization(cleartext string) error {
|
||||||
if cleartext == "" {
|
if cleartext == "" {
|
||||||
|
|
|
@ -561,6 +561,7 @@ TeamName = Team name
|
||||||
AuthName = Authorization name
|
AuthName = Authorization name
|
||||||
AdminEmail = Admin email
|
AdminEmail = Admin email
|
||||||
To = Branch name
|
To = Branch name
|
||||||
|
AccessToken = Access token
|
||||||
|
|
||||||
NewBranchName = New branch name
|
NewBranchName = New branch name
|
||||||
CommitSummary = Commit summary
|
CommitSummary = Commit summary
|
||||||
|
@ -2378,6 +2379,7 @@ settings.slack_token = Token
|
||||||
settings.slack_domain = Domain
|
settings.slack_domain = Domain
|
||||||
settings.slack_channel = Channel
|
settings.slack_channel = Channel
|
||||||
settings.add_web_hook_desc = Integrate <a target="_blank" rel="noreferrer" href="%s">%s</a> into your repository.
|
settings.add_web_hook_desc = Integrate <a target="_blank" rel="noreferrer" href="%s">%s</a> into your repository.
|
||||||
|
settings.graphql_url = GraphQL URL
|
||||||
settings.web_hook_name_gitea = Gitea
|
settings.web_hook_name_gitea = Gitea
|
||||||
settings.web_hook_name_forgejo = Forgejo
|
settings.web_hook_name_forgejo = Forgejo
|
||||||
settings.web_hook_name_gogs = Gogs
|
settings.web_hook_name_gogs = Gogs
|
||||||
|
@ -2397,10 +2399,10 @@ settings.packagist_api_token = API token
|
||||||
settings.packagist_package_url = Packagist package URL
|
settings.packagist_package_url = Packagist package URL
|
||||||
settings.web_hook_name_sourcehut_builds = SourceHut Builds
|
settings.web_hook_name_sourcehut_builds = SourceHut Builds
|
||||||
settings.sourcehut_builds.manifest_path = Build manifest path
|
settings.sourcehut_builds.manifest_path = Build manifest path
|
||||||
settings.sourcehut_builds.graphql_url = GraphQL URL (e.g. https://builds.sr.ht/query)
|
|
||||||
settings.sourcehut_builds.visibility = Job visibility
|
settings.sourcehut_builds.visibility = Job visibility
|
||||||
settings.sourcehut_builds.secrets = Secrets
|
settings.sourcehut_builds.secrets = Secrets
|
||||||
settings.sourcehut_builds.secrets_helper = Give the job access to the build secrets (requires the SECRETS:RO grant)
|
settings.sourcehut_builds.secrets_helper = Give the job access to the build secrets (requires the SECRETS:RO grant)
|
||||||
|
settings.sourcehut_builds.access_token_helper = Access token that has JOBS:RW grant. Generate a <a target="_blank" rel="noopener noreferrer" href="%s">builds.sr.ht token</a> or a <a target="_blank" rel="noopener noreferrer" href="%s">builds.sr.ht token with secrets access</a> on meta.sr.ht.
|
||||||
settings.deploy_keys = Deploy keys
|
settings.deploy_keys = Deploy keys
|
||||||
settings.add_deploy_key = Add deploy key
|
settings.add_deploy_key = Add deploy key
|
||||||
settings.deploy_key_desc = Deploy keys have read-only pull access to the repository.
|
settings.deploy_key_desc = Deploy keys have read-only pull access to the repository.
|
||||||
|
@ -2507,6 +2509,8 @@ settings.thread_id = Thread ID
|
||||||
settings.matrix.homeserver_url = Homeserver URL
|
settings.matrix.homeserver_url = Homeserver URL
|
||||||
settings.matrix.room_id = Room ID
|
settings.matrix.room_id = Room ID
|
||||||
settings.matrix.message_type = Message type
|
settings.matrix.message_type = Message type
|
||||||
|
settings.matrix.access_token_helper = It is recommended to setup a dedicated Matrix account for this. The access token can be retrieved from the Element web client (in a private/incognito tab) > User menu (top left) > All settings > Help & About > Advanced > Access Token (right below the Homeserver URL). Close the private/incognito tab (logging out would invalidate the token).
|
||||||
|
settings.matrix.room_id_helper = The Room ID can be retrieved from the Element web client > Room Settings > Advanced > Internal room ID. Example: %s.
|
||||||
settings.archive.button = Archive repo
|
settings.archive.button = Archive repo
|
||||||
settings.archive.header = Archive this repo
|
settings.archive.header = Archive this repo
|
||||||
settings.archive.text = Archiving the repo will make it entirely read-only. It will be hidden from the dashboard. Nobody (not even you!) will be able to make new commits, or open any issues or pull requests.
|
settings.archive.text = Archiving the repo will make it entirely read-only. It will be hidden from the dashboard. Nobody (not even you!) will be able to make new commits, or open any issues or pull requests.
|
||||||
|
|
|
@ -78,7 +78,13 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
|
||||||
}
|
}
|
||||||
if authorization != "" {
|
if authorization != "" {
|
||||||
req.Header.Set("Authorization", authorization)
|
req.Header.Set("Authorization", authorization)
|
||||||
t.RequestInfo.Headers["Authorization"] = "******"
|
redacted := "******"
|
||||||
|
if strings.HasPrefix(authorization, "Bearer ") {
|
||||||
|
redacted = "Bearer " + redacted
|
||||||
|
} else if strings.HasPrefix(authorization, "Basic ") {
|
||||||
|
redacted = "Basic " + redacted
|
||||||
|
}
|
||||||
|
t.RequestInfo.Headers["Authorization"] = redacted
|
||||||
}
|
}
|
||||||
|
|
||||||
t.ResponseInfo = &webhook_model.HookResponse{
|
t.ResponseInfo = &webhook_model.HookResponse{
|
||||||
|
|
|
@ -132,7 +132,7 @@ func TestWebhookDeliverAuthorizationHeader(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.True(t, hookTask.IsSucceed)
|
assert.True(t, hookTask.IsSucceed)
|
||||||
assert.Equal(t, "******", hookTask.RequestInfo.Headers["Authorization"])
|
assert.Equal(t, "Bearer ******", hookTask.RequestInfo.Headers["Authorization"])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWebhookDeliverHookTask(t *testing.T) {
|
func TestWebhookDeliverHookTask(t *testing.T) {
|
||||||
|
@ -152,7 +152,6 @@ func TestWebhookDeliverHookTask(t *testing.T) {
|
||||||
|
|
||||||
case "/webhook/6db5dc1e282529a8c162c7fe93dd2667494eeb51":
|
case "/webhook/6db5dc1e282529a8c162c7fe93dd2667494eeb51":
|
||||||
// Version 2
|
// Version 2
|
||||||
assert.Equal(t, "push", r.Header.Get("X-GitHub-Event"))
|
|
||||||
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
|
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
|
@ -42,16 +42,15 @@ func (matrixHandler) UnmarshalForm(bind func(any)) forms.WebhookForm {
|
||||||
HomeserverURL string `binding:"Required;ValidUrl"`
|
HomeserverURL string `binding:"Required;ValidUrl"`
|
||||||
RoomID string `binding:"Required"`
|
RoomID string `binding:"Required"`
|
||||||
MessageType int
|
MessageType int
|
||||||
|
AccessToken string `binding:"Required"`
|
||||||
// enforce requirement of authorization_header
|
|
||||||
// (value will still be set in the embedded WebhookCoreForm)
|
|
||||||
AuthorizationHeader string `binding:"Required"`
|
|
||||||
}
|
}
|
||||||
bind(&form)
|
bind(&form)
|
||||||
|
form.AuthorizationHeader = "Bearer " + strings.TrimSpace(form.AccessToken)
|
||||||
|
|
||||||
|
// https://spec.matrix.org/v1.10/client-server-api/#sending-events-to-a-room
|
||||||
return forms.WebhookForm{
|
return forms.WebhookForm{
|
||||||
WebhookCoreForm: form.WebhookCoreForm,
|
WebhookCoreForm: form.WebhookCoreForm,
|
||||||
URL: fmt.Sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message", form.HomeserverURL, url.PathEscape(form.RoomID)),
|
URL: fmt.Sprintf("%s/_matrix/client/v3/rooms/%s/send/m.room.message", form.HomeserverURL, url.PathEscape(form.RoomID)),
|
||||||
ContentType: webhook_model.ContentTypeJSON,
|
ContentType: webhook_model.ContentTypeJSON,
|
||||||
Secret: "",
|
Secret: "",
|
||||||
HTTPMethod: http.MethodPut,
|
HTTPMethod: http.MethodPut,
|
||||||
|
@ -91,7 +90,7 @@ func (matrixHandler) NewRequest(ctx context.Context, w *webhook_model.Webhook, t
|
||||||
}
|
}
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
|
||||||
return req, body, shared.AddDefaultHeaders(req, []byte(w.Secret), t, body) // likely useless, but has always been sent historially
|
return req, body, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const matrixPayloadSizeLimit = 1024 * 64
|
const matrixPayloadSizeLimit = 1024 * 64
|
||||||
|
|
|
@ -201,7 +201,7 @@ func TestMatrixJSONPayload(t *testing.T) {
|
||||||
RepoID: 3,
|
RepoID: 3,
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
Type: webhook_module.MATRIX,
|
Type: webhook_module.MATRIX,
|
||||||
URL: "https://matrix.example.com/_matrix/client/r0/rooms/ROOM_ID/send/m.room.message",
|
URL: "https://matrix.example.com/_matrix/client/v3/rooms/ROOM_ID/send/m.room.message",
|
||||||
Meta: `{"message_type":0}`, // text
|
Meta: `{"message_type":0}`, // text
|
||||||
}
|
}
|
||||||
task := &webhook_model.HookTask{
|
task := &webhook_model.HookTask{
|
||||||
|
@ -217,8 +217,7 @@ func TestMatrixJSONPayload(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, "PUT", req.Method)
|
assert.Equal(t, "PUT", req.Method)
|
||||||
assert.Equal(t, "/_matrix/client/r0/rooms/ROOM_ID/send/m.room.message/6db5dc1e282529a8c162c7fe93dd2667494eeb51", req.URL.Path)
|
assert.Equal(t, "/_matrix/client/v3/rooms/ROOM_ID/send/m.room.message/6db5dc1e282529a8c162c7fe93dd2667494eeb51", req.URL.Path)
|
||||||
assert.Equal(t, "sha256=", req.Header.Get("X-Hub-Signature-256"))
|
|
||||||
assert.Equal(t, "application/json", req.Header.Get("Content-Type"))
|
assert.Equal(t, "application/json", req.Header.Get("Content-Type"))
|
||||||
var body MatrixPayload
|
var body MatrixPayload
|
||||||
err = json.NewDecoder(req.Body).Decode(&body)
|
err = json.NewDecoder(req.Body).Decode(&body)
|
||||||
|
|
|
@ -49,6 +49,7 @@ type buildsForm struct {
|
||||||
ManifestPath string `binding:"Required"`
|
ManifestPath string `binding:"Required"`
|
||||||
Visibility string `binding:"Required;In(PUBLIC,UNLISTED,PRIVATE)"`
|
Visibility string `binding:"Required;In(PUBLIC,UNLISTED,PRIVATE)"`
|
||||||
Secrets bool
|
Secrets bool
|
||||||
|
AccessToken string `binding:"Required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ binding.Validator = &buildsForm{}
|
var _ binding.Validator = &buildsForm{}
|
||||||
|
@ -63,13 +64,7 @@ func (f *buildsForm) Validate(req *http.Request, errs binding.Errors) binding.Er
|
||||||
Message: ctx.Locale.TrString("repo.settings.add_webhook.invalid_path"),
|
Message: ctx.Locale.TrString("repo.settings.add_webhook.invalid_path"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if !strings.HasPrefix(f.AuthorizationHeader, "Bearer ") {
|
f.AuthorizationHeader = "Bearer " + strings.TrimSpace(f.AccessToken)
|
||||||
errs = append(errs, binding.Error{
|
|
||||||
FieldNames: []string{"AuthorizationHeader"},
|
|
||||||
Classification: "",
|
|
||||||
Message: ctx.Locale.TrString("form.required_prefix", "Bearer "),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,5 +5,5 @@
|
||||||
<label for="payload_url">{{ctx.Locale.Tr "repo.settings.payload_url"}}</label>
|
<label for="payload_url">{{ctx.Locale.Tr "repo.settings.payload_url"}}</label>
|
||||||
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
|
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -13,5 +13,5 @@
|
||||||
<label for="icon_url">{{ctx.Locale.Tr "repo.settings.discord_icon_url"}}</label>
|
<label for="icon_url">{{ctx.Locale.Tr "repo.settings.discord_icon_url"}}</label>
|
||||||
<input id="icon_url" name="icon_url" value="{{.HookMetadata.IconURL}}" placeholder="https://example.com/assets/img/logo.svg">
|
<input id="icon_url" name="icon_url" value="{{.HookMetadata.IconURL}}" placeholder="https://example.com/assets/img/logo.svg">
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -6,5 +6,5 @@
|
||||||
<label for="payload_url">{{ctx.Locale.Tr "repo.settings.payload_url"}}</label>
|
<label for="payload_url">{{ctx.Locale.Tr "repo.settings.payload_url"}}</label>
|
||||||
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
|
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -34,5 +34,5 @@
|
||||||
<label for="secret">{{ctx.Locale.Tr "repo.settings.secret"}}</label>
|
<label for="secret">{{ctx.Locale.Tr "repo.settings.secret"}}</label>
|
||||||
<input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off">
|
<input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -34,5 +34,5 @@
|
||||||
<label for="secret">{{ctx.Locale.Tr "repo.settings.secret"}}</label>
|
<label for="secret">{{ctx.Locale.Tr "repo.settings.secret"}}</label>
|
||||||
<input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off">
|
<input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -22,5 +22,5 @@
|
||||||
<label for="secret">{{ctx.Locale.Tr "repo.settings.secret"}}</label>
|
<label for="secret">{{ctx.Locale.Tr "repo.settings.secret"}}</label>
|
||||||
<input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off">
|
<input id="secret" name="secret" type="password" value="{{.Webhook.Secret}}" autocomplete="off">
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -5,9 +5,16 @@
|
||||||
<label for="homeserver_url">{{ctx.Locale.Tr "repo.settings.matrix.homeserver_url"}}</label>
|
<label for="homeserver_url">{{ctx.Locale.Tr "repo.settings.matrix.homeserver_url"}}</label>
|
||||||
<input id="homeserver_url" name="homeserver_url" type="url" value="{{.HookMetadata.HomeserverURL}}" autofocus required>
|
<input id="homeserver_url" name="homeserver_url" type="url" value="{{.HookMetadata.HomeserverURL}}" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Access Token -->
|
||||||
|
<div class="field required {{if .Err_AccessToken}}error{{end}}">
|
||||||
|
<label for="access_token">{{ctx.Locale.Tr "form.AccessToken"}}</label>
|
||||||
|
<input id="access_token" name="access_token" type="password" value="{{.Webhook.HeaderAuthorizationTrimPrefix "Bearer "}}" required>
|
||||||
|
<span class="help">{{ctx.Locale.Tr "repo.settings.matrix.access_token_helper"}}</span>
|
||||||
|
</div>
|
||||||
<div class="required field {{if .Err_Room}}error{{end}}">
|
<div class="required field {{if .Err_Room}}error{{end}}">
|
||||||
<label for="room_id">{{ctx.Locale.Tr "repo.settings.matrix.room_id"}}</label>
|
<label for="room_id">{{ctx.Locale.Tr "repo.settings.matrix.room_id"}}</label>
|
||||||
<input id="room_id" name="room_id" type="text" value="{{.HookMetadata.Room}}" required>
|
<input id="room_id" name="room_id" type="text" value="{{.HookMetadata.Room}}" placeholder="!opaque_id:domain" pattern="^!.+:.+$" maxlength="255" required>
|
||||||
|
<span class="help">{{ctx.Locale.Tr "repo.settings.matrix.room_id_helper" ("<code>!opaque_id:example.org</code>"|SafeHTML)}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>{{ctx.Locale.Tr "repo.settings.matrix.message_type"}}</label>
|
<label>{{ctx.Locale.Tr "repo.settings.matrix.message_type"}}</label>
|
||||||
|
@ -21,5 +28,5 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -5,5 +5,5 @@
|
||||||
<label for="payload_url">{{ctx.Locale.Tr "repo.settings.payload_url"}}</label>
|
<label for="payload_url">{{ctx.Locale.Tr "repo.settings.payload_url"}}</label>
|
||||||
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
|
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -13,5 +13,5 @@
|
||||||
<label for="package_url">{{ctx.Locale.Tr "repo.settings.packagist_package_url"}}</label>
|
<label for="package_url">{{ctx.Locale.Tr "repo.settings.packagist_package_url"}}</label>
|
||||||
<input id="package_url" name="package_url" value="{{.HookMetadata.PackageURL}}" placeholder="https://packagist.org/packages/laravel/framework" required>
|
<input id="package_url" name="package_url" value="{{.HookMetadata.PackageURL}}" placeholder="https://packagist.org/packages/laravel/framework" required>
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -22,5 +22,5 @@
|
||||||
<label for="color">{{ctx.Locale.Tr "repo.settings.slack_color"}}</label>
|
<label for="color">{{ctx.Locale.Tr "repo.settings.slack_color"}}</label>
|
||||||
<input id="color" name="color" value="{{.HookMetadata.Color}}" placeholder="#dd4b39, good, warning, danger">
|
<input id="color" name="color" value="{{.HookMetadata.Color}}" placeholder="#dd4b39, good, warning, danger">
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
<form class="ui form" action="{{.BaseLink}}/{{or .Webhook.ID "sourcehut_builds/new"}}" method="post">
|
<form class="ui form" action="{{.BaseLink}}/{{or .Webhook.ID "sourcehut_builds/new"}}" method="post">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<div class="required field {{if .Err_PayloadURL}}error{{end}}">
|
<div class="required field {{if .Err_PayloadURL}}error{{end}}">
|
||||||
<label for="payload_url">{{ctx.Locale.Tr "repo.settings.sourcehut_builds.graphql_url"}}</label>
|
<label for="payload_url">{{ctx.Locale.Tr "repo.settings.graphql_url"}}</label>
|
||||||
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
|
<input id="payload_url" name="payload_url" type="url" value="{{or .Webhook.URL "https://builds.sr.ht/query"}}" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
<div class="required field {{if .Err_ManifestPath}}error{{end}}">
|
<div class="required field {{if .Err_ManifestPath}}error{{end}}">
|
||||||
<label for="manifest_path">{{ctx.Locale.Tr "repo.settings.sourcehut_builds.manifest_path"}}</label>
|
<label for="manifest_path">{{ctx.Locale.Tr "repo.settings.sourcehut_builds.manifest_path"}}</label>
|
||||||
<input id="manifest_path" name="manifest_path" type="text" value="{{.HookMetadata.ManifestPath}}" required>
|
<input id="manifest_path" name="manifest_path" type="text" value="{{or .HookMetadata.ManifestPath ".build.yml"}}" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>{{ctx.Locale.Tr "repo.settings.sourcehut_builds.visibility"}}</label>
|
<label>{{ctx.Locale.Tr "repo.settings.sourcehut_builds.visibility"}}</label>
|
||||||
|
@ -29,5 +29,11 @@
|
||||||
<span class="help">{{ctx.Locale.Tr "repo.settings.sourcehut_builds.secrets_helper"}}</span>
|
<span class="help">{{ctx.Locale.Tr "repo.settings.sourcehut_builds.secrets_helper"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
<!-- Access Token -->
|
||||||
|
<div class="field required {{if .Err_AccessToken}}error{{end}}">
|
||||||
|
<label for="access_token">{{ctx.Locale.Tr "form.AccessToken"}}</label>
|
||||||
|
<input id="access_token" name="access_token" type="password" value="{{.Webhook.HeaderAuthorizationTrimPrefix "Bearer "}}" required>
|
||||||
|
<span class="help">{{ctx.Locale.Tr "repo.settings.sourcehut_builds.access_token_helper" "https://meta.sr.ht/oauth2/personal-token?grants=builds.sr.ht/JOBS:RW" "https://meta.sr.ht/oauth2/personal-token?grants=builds.sr.ht/JOBS:RW+builds.sr.ht/SECRETS:RO"}}</span>
|
||||||
|
</div>
|
||||||
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -13,5 +13,5 @@
|
||||||
<label for="thread_id">{{ctx.Locale.Tr "repo.settings.thread_id"}}</label>
|
<label for="thread_id">{{ctx.Locale.Tr "repo.settings.thread_id"}}</label>
|
||||||
<input id="thread_id" name="thread_id" type="text" value="{{.HookMetadata.ThreadID}}">
|
<input id="thread_id" name="thread_id" type="text" value="{{.HookMetadata.ThreadID}}">
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -5,5 +5,5 @@
|
||||||
<label for="payload_url">{{ctx.Locale.Tr "repo.settings.payload_url"}}</label>
|
<label for="payload_url">{{ctx.Locale.Tr "repo.settings.payload_url"}}</label>
|
||||||
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
|
<input id="payload_url" name="payload_url" type="url" value="{{.Webhook.URL}}" autofocus required>
|
||||||
</div>
|
</div>
|
||||||
{{template "repo/settings/webhook/settings" .}}
|
{{template "webhook/shared-settings" .}}
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -258,14 +258,15 @@
|
||||||
<span class="help">{{ctx.Locale.Tr "repo.settings.branch_filter_desc"}}</span>
|
<span class="help">{{ctx.Locale.Tr "repo.settings.branch_filter_desc"}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Authorization Header -->
|
{{$skipAuthorizationHeader := or (eq .HookType "sourcehut_builds") (eq .HookType "matrix")}}
|
||||||
<div class="field{{if eq .HookType "matrix"}} required{{end}} {{if .Err_AuthorizationHeader}}error{{end}}">
|
{{if not $skipAuthorizationHeader}}
|
||||||
<label for="authorization_header">{{ctx.Locale.Tr "repo.settings.authorization_header"}}</label>
|
<!-- Authorization Header -->
|
||||||
<input id="authorization_header" name="authorization_header" type="text" value="{{.Webhook.HeaderAuthorization}}"{{if eq .HookType "matrix"}} placeholder="Bearer $access_token" required{{end}}>
|
<div class="field {{if .Err_AuthorizationHeader}}error{{end}}">
|
||||||
{{if ne .HookType "matrix"}}{{/* Matrix doesn't make the authorization optional but it is implied by the help string, should be changed.*/}}
|
<label for="authorization_header">{{ctx.Locale.Tr "repo.settings.authorization_header"}}</label>
|
||||||
|
<input id="authorization_header" name="authorization_header" type="text" value="{{.Webhook.HeaderAuthorization}}">
|
||||||
<span class="help">{{ctx.Locale.Tr "repo.settings.authorization_header_desc" ("<code>Bearer token123456</code>, <code>Basic YWxhZGRpbjpvcGVuc2VzYW1l</code>" | SafeHTML)}}</span>
|
<span class="help">{{ctx.Locale.Tr "repo.settings.authorization_header_desc" ("<code>Bearer token123456</code>, <code>Basic YWxhZGRpbjpvcGVuc2VzYW1l</code>" | SafeHTML)}}</span>
|
||||||
{{end}}
|
</div>
|
||||||
</div>
|
{{end}}
|
||||||
|
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
|
|
|
@ -227,19 +227,19 @@ func TestWebhookForms(t *testing.T) {
|
||||||
}))
|
}))
|
||||||
|
|
||||||
t.Run("matrix/required", testWebhookForms("matrix", session, map[string]string{
|
t.Run("matrix/required", testWebhookForms("matrix", session, map[string]string{
|
||||||
"homeserver_url": "https://matrix.example.com",
|
"homeserver_url": "https://matrix.example.com",
|
||||||
"room_id": "123",
|
"access_token": "123456",
|
||||||
"authorization_header": "Bearer 123456",
|
"room_id": "123",
|
||||||
}, map[string]string{
|
}, map[string]string{
|
||||||
"authorization_header": "",
|
"access_token": "",
|
||||||
}))
|
}))
|
||||||
t.Run("matrix/optional", testWebhookForms("matrix", session, map[string]string{
|
t.Run("matrix/optional", testWebhookForms("matrix", session, map[string]string{
|
||||||
"homeserver_url": "https://matrix.example.com",
|
"homeserver_url": "https://matrix.example.com",
|
||||||
|
"access_token": "123456",
|
||||||
"room_id": "123",
|
"room_id": "123",
|
||||||
"message_type": "1", // m.text
|
"message_type": "1", // m.text
|
||||||
|
|
||||||
"branch_filter": "matrix/*",
|
"branch_filter": "matrix/*",
|
||||||
"authorization_header": "Bearer 123456",
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
t.Run("wechatwork/required", testWebhookForms("wechatwork", session, map[string]string{
|
t.Run("wechatwork/required", testWebhookForms("wechatwork", session, map[string]string{
|
||||||
|
@ -267,14 +267,12 @@ func TestWebhookForms(t *testing.T) {
|
||||||
}))
|
}))
|
||||||
|
|
||||||
t.Run("sourcehut_builds/required", testWebhookForms("sourcehut_builds", session, map[string]string{
|
t.Run("sourcehut_builds/required", testWebhookForms("sourcehut_builds", session, map[string]string{
|
||||||
"payload_url": "https://sourcehut_builds.example.com",
|
"payload_url": "https://sourcehut_builds.example.com",
|
||||||
"manifest_path": ".build.yml",
|
"manifest_path": ".build.yml",
|
||||||
"visibility": "PRIVATE",
|
"visibility": "PRIVATE",
|
||||||
"authorization_header": "Bearer 123456",
|
"access_token": "123456",
|
||||||
}, map[string]string{
|
}, map[string]string{
|
||||||
"authorization_header": "",
|
"access_token": "",
|
||||||
}, map[string]string{
|
|
||||||
"authorization_header": "token ",
|
|
||||||
}, map[string]string{
|
}, map[string]string{
|
||||||
"manifest_path": "",
|
"manifest_path": "",
|
||||||
}, map[string]string{
|
}, map[string]string{
|
||||||
|
@ -289,9 +287,9 @@ func TestWebhookForms(t *testing.T) {
|
||||||
"manifest_path": ".build.yml",
|
"manifest_path": ".build.yml",
|
||||||
"visibility": "PRIVATE",
|
"visibility": "PRIVATE",
|
||||||
"secrets": "on",
|
"secrets": "on",
|
||||||
|
"access_token": "123456",
|
||||||
|
|
||||||
"branch_filter": "srht/*",
|
"branch_filter": "srht/*",
|
||||||
"authorization_header": "Bearer 123456",
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue