From fff0aa9ec5420201d85dabbbd69dbc6ceadbbd71 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Thu, 13 Jun 2024 13:20:32 +0200 Subject: [PATCH 1/2] Migrate to maintained cron lib and remove seconds --- docs/docs/20-usage/45-cron.md | 10 +--- docs/docs/91-migrations.md | 1 + go.mod | 2 +- go.sum | 4 +- server/cron/cron.go | 6 +-- server/model/cron.go | 4 +- .../migration/031_cron_without_sec.go | 48 +++++++++++++++++++ server/store/datastore/migration/migration.go | 1 + web/src/components/repo/settings/CronTab.vue | 2 +- 9 files changed, 61 insertions(+), 17 deletions(-) create mode 100644 server/store/datastore/migration/031_cron_without_sec.go diff --git a/docs/docs/20-usage/45-cron.md b/docs/docs/20-usage/45-cron.md index bbf23bdf04..605e42d596 100644 --- a/docs/docs/20-usage/45-cron.md +++ b/docs/docs/20-usage/45-cron.md @@ -23,12 +23,6 @@ To configure cron jobs you need at least push access to the repository. ![cron settings](./cron-settings.png) - The supported schedule syntax can be found at . If you need general understanding of the cron syntax is a good place to start and experiment. + The supported schedule syntax can be found at . If you need general understanding of the cron syntax is a good place to start and experiment. - Examples: `@every 5m`, `@daily`, `0 30 * * * *` ... - - :::info - Woodpeckers cron syntax starts with seconds instead of minutes as used by most linux cron schedulers. - - Example: "At minute 30 every hour" would be `0 30 * * * *` instead of `30 * * * *` - ::: + Examples: `@every 5m`, `@daily`, `30 * * * *` ... diff --git a/docs/docs/91-migrations.md b/docs/docs/91-migrations.md index 841dee3d04..d2fb2599a2 100644 --- a/docs/docs/91-migrations.md +++ b/docs/docs/91-migrations.md @@ -6,6 +6,7 @@ Some versions need some changes to the server configuration or the pipeline conf ## 3.0.0 - Update all webhooks by pressing the "Repair all" button in the admin settings as the webhook token claims have changed +- Crons now use standard Linux syntax without seconds --> diff --git a/go.mod b/go.mod index c5fe5c9764..07d0807deb 100644 --- a/go.mod +++ b/go.mod @@ -26,6 +26,7 @@ require ( github.com/expr-lang/expr v1.16.7 github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf github.com/fsnotify/fsnotify v1.7.0 + github.com/gdgvda/cron v0.2.0 github.com/gin-gonic/gin v1.10.0 github.com/go-ap/httpsig v0.0.0-20221203064646-3647b4d88fdf github.com/go-sql-driver/mysql v1.8.1 @@ -48,7 +49,6 @@ require ( github.com/oklog/ulid/v2 v2.1.0 github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.19.1 - github.com/robfig/cron v1.2.0 github.com/rs/zerolog v1.33.0 github.com/stretchr/testify v1.9.0 github.com/swaggo/files v1.0.1 diff --git a/go.sum b/go.sum index 98eb541969..2925fb1377 100644 --- a/go.sum +++ b/go.sum @@ -122,6 +122,8 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/gdgvda/cron v0.2.0 h1:oX8qdLZq4tC5StnCsZsTNs2BIzaRjcjmPZ4o+BArKX4= +github.com/gdgvda/cron v0.2.0/go.mod h1:VEwidZXB255kESB5DcUGRWTYZS8KkOBYD1YBn8Wiyx8= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= @@ -407,8 +409,6 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.6 h1:Sovz9sDSwbOz9tgUy8JpT+KgCkPYJEN/oYzlJiYTNLg= github.com/rivo/uniseg v0.4.6/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= -github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= diff --git a/server/cron/cron.go b/server/cron/cron.go index a1dcddd296..93ff42c264 100644 --- a/server/cron/cron.go +++ b/server/cron/cron.go @@ -19,7 +19,7 @@ import ( "fmt" "time" - "github.com/robfig/cron" + "github.com/gdgvda/cron" "github.com/rs/zerolog/log" "go.woodpecker-ci.org/woodpecker/v2/server" @@ -31,7 +31,7 @@ import ( const ( // Specifies the interval woodpecker checks for new crons to exec. - checkTime = 10 * time.Second + checkTime = time.Minute // Specifies the batch size of crons to retrieve per check from database. checkItems = 10 @@ -71,7 +71,7 @@ func CalcNewNext(schedule string, now time.Time) (time.Time, error) { // TODO: allow the users / the admin to set a specific timezone - c, err := cron.Parse(schedule) + c, err := cron.ParseStandard(schedule) if err != nil { return time.Time{}, fmt.Errorf("cron parse schedule: %w", err) } diff --git a/server/model/cron.go b/server/model/cron.go index 6fa213724a..5dd831ac99 100644 --- a/server/model/cron.go +++ b/server/model/cron.go @@ -17,7 +17,7 @@ package model import ( "fmt" - "github.com/robfig/cron" + "github.com/gdgvda/cron" ) type Cron struct { @@ -46,7 +46,7 @@ func (c *Cron) Validate() error { return fmt.Errorf("schedule is required") } - _, err := cron.Parse(c.Schedule) + _, err := cron.ParseStandard(c.Schedule) if err != nil { return fmt.Errorf("can't parse schedule: %w", err) } diff --git a/server/store/datastore/migration/031_cron_without_sec.go b/server/store/datastore/migration/031_cron_without_sec.go new file mode 100644 index 0000000000..b2dfe60697 --- /dev/null +++ b/server/store/datastore/migration/031_cron_without_sec.go @@ -0,0 +1,48 @@ +// Copyright 2024 Woodpecker Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package migration + +import ( + "fmt" + "strings" + + "src.techknowlogick.com/xormigrate" + "xorm.io/xorm" + + "go.woodpecker-ci.org/woodpecker/v2/server/model" +) + +var cronWithoutSec = xormigrate.Migration{ + ID: "cron-without-sec", + MigrateSession: func(sess *xorm.Session) error { + if err := sess.Sync(new(model.Cron)); err != nil { + return fmt.Errorf("sync new models failed: %w", err) + } + + var crons []*model.Cron + if err := sess.Find(&crons); err != nil { + return err + } + + for _, c := range crons { + c.Schedule = strings.SplitN(c.Schedule, " ", 2)[1] + if _, err := sess.Update(c); err != nil { + return err + } + } + + return nil + }, +} diff --git a/server/store/datastore/migration/migration.go b/server/store/datastore/migration/migration.go index ac21feb1c8..9218a8fb2d 100644 --- a/server/store/datastore/migration/migration.go +++ b/server/store/datastore/migration/migration.go @@ -60,6 +60,7 @@ var migrationTasks = []*xormigrate.Migration{ &renameLinkToURL, &cleanRegistryPipeline, &setForgeID, + &cronWithoutSec, } var allBeans = []any{ diff --git a/web/src/components/repo/settings/CronTab.vue b/web/src/components/repo/settings/CronTab.vue index 4e2e5ca8f8..d6050f6ed6 100644 --- a/web/src/components/repo/settings/CronTab.vue +++ b/web/src/components/repo/settings/CronTab.vue @@ -58,7 +58,7 @@ Date: Fri, 14 Jun 2024 09:46:16 +0200 Subject: [PATCH 2/2] fix @ prefixes --- server/store/datastore/migration/031_cron_without_sec.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server/store/datastore/migration/031_cron_without_sec.go b/server/store/datastore/migration/031_cron_without_sec.go index b2dfe60697..a170401b30 100644 --- a/server/store/datastore/migration/031_cron_without_sec.go +++ b/server/store/datastore/migration/031_cron_without_sec.go @@ -37,7 +37,12 @@ var cronWithoutSec = xormigrate.Migration{ } for _, c := range crons { - c.Schedule = strings.SplitN(c.Schedule, " ", 2)[1] + if strings.HasPrefix(strings.TrimSpace(c.Schedule), "@") { + // something like "@daily" + continue + } + + c.Schedule = strings.SplitN(strings.TrimSpace(c.Schedule), " ", 2)[1] if _, err := sess.Update(c); err != nil { return err }