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:
yp05327 2023-05-04 08:53:43 +09:00 committed by GitHub
parent 4a722c9a45
commit dbb3736785
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 27 deletions

View File

@ -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"
@ -47,8 +48,7 @@ type HookTask struct {
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) {
t.UUID = gouuid.New().String()
if t.Payloader != nil {
data, err := t.Payloader.JSONPayload() data, err := t.Payloader.JSONPayload()
if err != nil { if err != nil {
return nil, err return nil, err
} }
t.UUID = gouuid.New().String()
t.PayloadContent = string(data) 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

View File

@ -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)

View 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)
}

View File

@ -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 {

View File

@ -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>