mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-27 04:43:59 +01:00
3fdaabcdcf
Fix #31657. According to the [doc](https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#onschedule) of GitHub Actions, The timezone for cron should be UTC, not the local timezone. And Gitea Actions doesn't have any reasons to change this, so I think it's a bug. However, Gitea Actions has extended the syntax, as it supports descriptors like `@weekly` and `@every 5m`, and supports specifying the timezone like `TZ=UTC 0 10 * * *`. So we can make it use UTC only when the timezone is not specified, to be compatible with GitHub Actions, and also respect the user's specified. It does break the feature because the times to run tasks would be changed, and it may confuse users. So I don't think we should backport this. ## ⚠️ BREAKING ⚠️ If the server's local time zone is not UTC, a scheduled task would run at a different time after upgrading Gitea to this version. (cherry picked from commit 21a73ae642b15982a911837775c9583deb47220c)
73 lines
2 KiB
Go
73 lines
2 KiB
Go
// Copyright 2023 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package actions
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"time"
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
repo_model "code.gitea.io/gitea/models/repo"
|
|
"code.gitea.io/gitea/modules/timeutil"
|
|
|
|
"github.com/robfig/cron/v3"
|
|
)
|
|
|
|
// ActionScheduleSpec represents a schedule spec of a workflow file
|
|
type ActionScheduleSpec struct {
|
|
ID int64
|
|
RepoID int64 `xorm:"index"`
|
|
Repo *repo_model.Repository `xorm:"-"`
|
|
ScheduleID int64 `xorm:"index"`
|
|
Schedule *ActionSchedule `xorm:"-"`
|
|
|
|
// Next time the job will run, or the zero time if Cron has not been
|
|
// started or this entry's schedule is unsatisfiable
|
|
Next timeutil.TimeStamp `xorm:"index"`
|
|
// Prev is the last time this job was run, or the zero time if never.
|
|
Prev timeutil.TimeStamp
|
|
Spec string
|
|
|
|
Created timeutil.TimeStamp `xorm:"created"`
|
|
Updated timeutil.TimeStamp `xorm:"updated"`
|
|
}
|
|
|
|
// Parse parses the spec and returns a cron.Schedule
|
|
// Unlike the default cron parser, Parse uses UTC timezone as the default if none is specified.
|
|
func (s *ActionScheduleSpec) Parse() (cron.Schedule, error) {
|
|
parser := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow | cron.Descriptor)
|
|
schedule, err := parser.Parse(s.Spec)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// If the spec has specified a timezone, use it
|
|
if strings.HasPrefix(s.Spec, "TZ=") || strings.HasPrefix(s.Spec, "CRON_TZ=") {
|
|
return schedule, nil
|
|
}
|
|
|
|
specSchedule, ok := schedule.(*cron.SpecSchedule)
|
|
// If it's not a spec schedule, like "@every 5m", timezone is not relevant
|
|
if !ok {
|
|
return schedule, nil
|
|
}
|
|
|
|
// Set the timezone to UTC
|
|
specSchedule.Location = time.UTC
|
|
return specSchedule, nil
|
|
}
|
|
|
|
func init() {
|
|
db.RegisterModel(new(ActionScheduleSpec))
|
|
}
|
|
|
|
func UpdateScheduleSpec(ctx context.Context, spec *ActionScheduleSpec, cols ...string) error {
|
|
sess := db.GetEngine(ctx).ID(spec.ID)
|
|
if len(cols) > 0 {
|
|
sess.Cols(cols...)
|
|
}
|
|
_, err := sess.Update(spec)
|
|
return err
|
|
}
|