mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-12-20 20:07:03 +01:00
Fix incorrect webhook time and use relative-time to display it (#24477)
Fixes #24414 After click replay this webhook, it will display `now` ![image](https://user-images.githubusercontent.com/18380374/235559399-05a23927-13f5-442d-8f10-2c7cd24022a0.png) --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
parent
4a722c9a45
commit
dbb3736785
5 changed files with 57 additions and 27 deletions
|
@ -12,6 +12,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
webhook_module "code.gitea.io/gitea/modules/webhook"
|
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||||
|
|
||||||
gouuid "github.com/google/uuid"
|
gouuid "github.com/google/uuid"
|
||||||
|
@ -40,15 +41,14 @@ type HookResponse struct {
|
||||||
|
|
||||||
// HookTask represents a hook task.
|
// HookTask represents a hook task.
|
||||||
type HookTask struct {
|
type HookTask struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
HookID int64 `xorm:"index"`
|
HookID int64 `xorm:"index"`
|
||||||
UUID string `xorm:"unique"`
|
UUID string `xorm:"unique"`
|
||||||
api.Payloader `xorm:"-"`
|
api.Payloader `xorm:"-"`
|
||||||
PayloadContent string `xorm:"LONGTEXT"`
|
PayloadContent string `xorm:"LONGTEXT"`
|
||||||
EventType webhook_module.HookEventType
|
EventType webhook_module.HookEventType
|
||||||
IsDelivered bool
|
IsDelivered bool
|
||||||
Delivered int64
|
Delivered timeutil.TimeStampNano
|
||||||
DeliveredString string `xorm:"-"`
|
|
||||||
|
|
||||||
// History info.
|
// History info.
|
||||||
IsSucceed bool
|
IsSucceed bool
|
||||||
|
@ -75,8 +75,6 @@ func (t *HookTask) BeforeUpdate() {
|
||||||
|
|
||||||
// AfterLoad updates the webhook object upon setting a column
|
// AfterLoad updates the webhook object upon setting a column
|
||||||
func (t *HookTask) AfterLoad() {
|
func (t *HookTask) AfterLoad() {
|
||||||
t.DeliveredString = time.Unix(0, t.Delivered).Format("2006-01-02 15:04:05 MST")
|
|
||||||
|
|
||||||
if len(t.RequestContent) == 0 {
|
if len(t.RequestContent) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -115,12 +113,17 @@ func HookTasks(hookID int64, page int) ([]*HookTask, error) {
|
||||||
// CreateHookTask creates a new hook task,
|
// CreateHookTask creates a new hook task,
|
||||||
// it handles conversion from Payload to PayloadContent.
|
// it handles conversion from Payload to PayloadContent.
|
||||||
func CreateHookTask(ctx context.Context, t *HookTask) (*HookTask, error) {
|
func CreateHookTask(ctx context.Context, t *HookTask) (*HookTask, error) {
|
||||||
data, err := t.Payloader.JSONPayload()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
t.UUID = gouuid.New().String()
|
t.UUID = gouuid.New().String()
|
||||||
t.PayloadContent = string(data)
|
if t.Payloader != nil {
|
||||||
|
data, err := t.Payloader.JSONPayload()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
t.PayloadContent = string(data)
|
||||||
|
}
|
||||||
|
if t.Delivered == 0 {
|
||||||
|
t.Delivered = timeutil.TimeStampNanoNow()
|
||||||
|
}
|
||||||
return t, db.Insert(ctx, t)
|
return t, db.Insert(ctx, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,13 +164,11 @@ func ReplayHookTask(ctx context.Context, hookID int64, uuid string) (*HookTask,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newTask := &HookTask{
|
return CreateHookTask(ctx, &HookTask{
|
||||||
UUID: gouuid.New().String(),
|
|
||||||
HookID: task.HookID,
|
HookID: task.HookID,
|
||||||
PayloadContent: task.PayloadContent,
|
PayloadContent: task.PayloadContent,
|
||||||
EventType: task.EventType,
|
EventType: task.EventType,
|
||||||
}
|
})
|
||||||
return newTask, db.Insert(ctx, newTask)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindUndeliveredHookTaskIDs will find the next 100 undelivered hook tasks with ID greater than the provided lowerID
|
// FindUndeliveredHookTaskIDs will find the next 100 undelivered hook tasks with ID greater than the provided lowerID
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
webhook_module "code.gitea.io/gitea/modules/webhook"
|
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||||
|
|
||||||
|
@ -222,7 +223,6 @@ func TestUpdateHookTask(t *testing.T) {
|
||||||
|
|
||||||
hook := unittest.AssertExistsAndLoadBean(t, &HookTask{ID: 1})
|
hook := unittest.AssertExistsAndLoadBean(t, &HookTask{ID: 1})
|
||||||
hook.PayloadContent = "new payload content"
|
hook.PayloadContent = "new payload content"
|
||||||
hook.DeliveredString = "new delivered string"
|
|
||||||
hook.IsDelivered = true
|
hook.IsDelivered = true
|
||||||
unittest.AssertNotExistsBean(t, hook)
|
unittest.AssertNotExistsBean(t, hook)
|
||||||
assert.NoError(t, UpdateHookTask(hook))
|
assert.NoError(t, UpdateHookTask(hook))
|
||||||
|
@ -235,7 +235,7 @@ func TestCleanupHookTaskTable_PerWebhook_DeletesDelivered(t *testing.T) {
|
||||||
HookID: 3,
|
HookID: 3,
|
||||||
Payloader: &api.PushPayload{},
|
Payloader: &api.PushPayload{},
|
||||||
IsDelivered: true,
|
IsDelivered: true,
|
||||||
Delivered: time.Now().UnixNano(),
|
Delivered: timeutil.TimeStampNanoNow(),
|
||||||
}
|
}
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
||||||
|
@ -268,7 +268,7 @@ func TestCleanupHookTaskTable_PerWebhook_LeavesMostRecentTask(t *testing.T) {
|
||||||
HookID: 4,
|
HookID: 4,
|
||||||
Payloader: &api.PushPayload{},
|
Payloader: &api.PushPayload{},
|
||||||
IsDelivered: true,
|
IsDelivered: true,
|
||||||
Delivered: time.Now().UnixNano(),
|
Delivered: timeutil.TimeStampNanoNow(),
|
||||||
}
|
}
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
||||||
|
@ -285,7 +285,7 @@ func TestCleanupHookTaskTable_OlderThan_DeletesDelivered(t *testing.T) {
|
||||||
HookID: 3,
|
HookID: 3,
|
||||||
Payloader: &api.PushPayload{},
|
Payloader: &api.PushPayload{},
|
||||||
IsDelivered: true,
|
IsDelivered: true,
|
||||||
Delivered: time.Now().AddDate(0, 0, -8).UnixNano(),
|
Delivered: timeutil.TimeStampNano(time.Now().AddDate(0, 0, -8).UnixNano()),
|
||||||
}
|
}
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
||||||
|
@ -318,7 +318,7 @@ func TestCleanupHookTaskTable_OlderThan_LeavesTaskEarlierThanAgeToDelete(t *test
|
||||||
HookID: 4,
|
HookID: 4,
|
||||||
Payloader: &api.PushPayload{},
|
Payloader: &api.PushPayload{},
|
||||||
IsDelivered: true,
|
IsDelivered: true,
|
||||||
Delivered: time.Now().AddDate(0, 0, -6).UnixNano(),
|
Delivered: timeutil.TimeStampNano(time.Now().AddDate(0, 0, -6).UnixNano()),
|
||||||
}
|
}
|
||||||
unittest.AssertNotExistsBean(t, hookTask)
|
unittest.AssertNotExistsBean(t, hookTask)
|
||||||
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
_, err := CreateHookTask(db.DefaultContext, hookTask)
|
||||||
|
|
28
modules/timeutil/timestampnano.go
Normal file
28
modules/timeutil/timestampnano.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package timeutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TimeStampNano is for nano time in database, do not use it unless there is a real requirement.
|
||||||
|
type TimeStampNano int64
|
||||||
|
|
||||||
|
// TimeStampNanoNow returns now nano int64
|
||||||
|
func TimeStampNanoNow() TimeStampNano {
|
||||||
|
return TimeStampNano(time.Now().UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsTime convert timestamp as time.Time in Local locale
|
||||||
|
func (tsn TimeStampNano) AsTime() (tm time.Time) {
|
||||||
|
return tsn.AsTimeInLocation(setting.DefaultUILocation)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AsTimeInLocation convert timestamp as time.Time in Local locale
|
||||||
|
func (tsn TimeStampNano) AsTimeInLocation(loc *time.Location) time.Time {
|
||||||
|
return time.Unix(0, int64(tsn)).In(loc)
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/proxy"
|
"code.gitea.io/gitea/modules/proxy"
|
||||||
"code.gitea.io/gitea/modules/queue"
|
"code.gitea.io/gitea/modules/queue"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
webhook_module "code.gitea.io/gitea/modules/webhook"
|
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||||
|
|
||||||
"github.com/gobwas/glob"
|
"github.com/gobwas/glob"
|
||||||
|
@ -175,7 +176,7 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
|
||||||
|
|
||||||
// All code from this point will update the hook task
|
// All code from this point will update the hook task
|
||||||
defer func() {
|
defer func() {
|
||||||
t.Delivered = time.Now().UnixNano()
|
t.Delivered = timeutil.TimeStampNanoNow()
|
||||||
if t.IsSucceed {
|
if t.IsSucceed {
|
||||||
log.Trace("Hook delivered: %s", t.UUID)
|
log.Trace("Hook delivered: %s", t.UUID)
|
||||||
} else if !w.IsActive {
|
} else if !w.IsActive {
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<a class="ui primary sha label toggle button show-panel" data-panel="#info-{{.ID}}">{{.UUID}}</a>
|
<a class="ui primary sha label toggle button show-panel" data-panel="#info-{{.ID}}">{{.UUID}}</a>
|
||||||
<div class="ui right">
|
<div class="ui right">
|
||||||
<span class="text grey time">
|
<span class="text grey time">
|
||||||
{{.DeliveredString}}
|
{{TimeSince .Delivered.AsTime $.locale}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue