Update to cron v3, ability to show next issues creation timestamps and little refactor.

This commit is contained in:
Stanislav Nikitin 2021-09-29 07:35:31 +05:00
parent 5c4a169040
commit 7bc47cf428
Signed by: pztrn
GPG Key ID: 1E944A0F0568B550
6 changed files with 82 additions and 23 deletions

View File

@ -12,6 +12,11 @@ run:
GPT_CONFIG=$(CONFIG) ./periodicator GPT_CONFIG=$(CONFIG) ./periodicator
rm periodicator rm periodicator
run-show-next-creation-ts:
go build -ldflags $(LINKER_FLAGS) -o periodicator .
GPT_CONFIG=$(CONFIG) ./periodicator -show-next-creation-ts
rm periodicator
run-version: run-version:
go build -ldflags $(LINKER_FLAGS) -o periodicator . go build -ldflags $(LINKER_FLAGS) -o periodicator .
GPT_CONFIG=$(CONFIG) ./periodicator -version GPT_CONFIG=$(CONFIG) ./periodicator -version

3
go.mod
View File

@ -3,12 +3,13 @@ module go.dev.pztrn.name/periodicator
go 1.17 go 1.17
require ( require (
github.com/robfig/cron v1.2.0 github.com/robfig/cron/v3 v3.0.1
github.com/xanzy/go-gitlab v0.51.1 github.com/xanzy/go-gitlab v0.51.1
gopkg.in/yaml.v2 v2.2.2 gopkg.in/yaml.v2 v2.2.2
) )
require ( require (
github.com/adhocore/gronx v0.2.5 // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect

6
go.sum
View File

@ -33,6 +33,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/adhocore/gronx v0.2.5 h1:trVgNYPle0IcsGDt0XGz78zN8Soek0YrcQtQ+Cs+jko=
github.com/adhocore/gronx v0.2.5/go.mod h1:7oUY1WAU8rEJWmAxXR2DN0JaO4gi9khSgKjiRypqteg=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
@ -125,8 +127,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=

View File

@ -4,7 +4,7 @@ import (
"log" "log"
"time" "time"
"github.com/robfig/cron" "github.com/robfig/cron/v3"
g "github.com/xanzy/go-gitlab" g "github.com/xanzy/go-gitlab"
"go.dev.pztrn.name/periodicator/internal/gitlab" "go.dev.pztrn.name/periodicator/internal/gitlab"
) )
@ -39,6 +39,37 @@ func (b *BaseTask) checkIfOpenedTaskExists(issues []*g.Issue) bool {
return foundAndNotClosed return foundAndNotClosed
} }
func (b *BaseTask) getIssues() ([]*g.Issue, error) {
// nolint:wrapcheck
return b.client.GetIssuesByTitle(b.projectID, b.title)
}
func (b *BaseTask) getLastCreationTimestamp(issues []*g.Issue) time.Time {
lastTaskCreationTS := b.executionStartTimestamp
for _, issue := range issues {
if issue.ClosedAt != nil && issue.CreatedAt.After(lastTaskCreationTS) {
lastTaskCreationTS = *issue.CreatedAt
}
}
return lastTaskCreationTS
}
func (b *BaseTask) getNextCreationTimestamp(lastTaskCreationTS time.Time) time.Time {
// Set up cron job parser.
cp := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)
schedule, err := cp.Parse(b.cron)
if err != nil {
b.log("Failed to parse cron string: " + err.Error())
return lastTaskCreationTS
}
return schedule.Next(lastTaskCreationTS)
}
func (b *BaseTask) log(message string) { func (b *BaseTask) log(message string) {
log.Println("Task '" + b.title + "': " + message) log.Println("Task '" + b.title + "': " + message)
} }
@ -46,7 +77,7 @@ func (b *BaseTask) log(message string) {
// Run executes task procedure. // Run executes task procedure.
func (b *BaseTask) Run() { func (b *BaseTask) Run() {
// Get similar tasks. // Get similar tasks.
issues, err := b.client.GetIssuesByTitle(b.projectID, b.title) issues, err := b.getIssues()
if err != nil { if err != nil {
b.log("Error while getting issues from Gitlab: " + err.Error()) b.log("Error while getting issues from Gitlab: " + err.Error())
@ -65,29 +96,16 @@ func (b *BaseTask) Run() {
b.log("No still opened tasks found, checking if we should create new one...") b.log("No still opened tasks found, checking if we should create new one...")
// Get latest task creation timestamp from Gitlab. // Get latest task creation timestamp from Gitlab.
lastTaskCreationTS := b.executionStartTimestamp lastTaskCreationTS := b.getLastCreationTimestamp(issues)
for _, issue := range issues {
if issue.ClosedAt != nil && issue.CreatedAt.After(lastTaskCreationTS) {
lastTaskCreationTS = *issue.CreatedAt
}
}
b.log("Last task creation timestamp: " + lastTaskCreationTS.String()) b.log("Last task creation timestamp: " + lastTaskCreationTS.String())
// Set up cron job parser. // Figure out next task creation and deadline timestamps.
cp := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow) nextCreationTS := b.getNextCreationTimestamp(lastTaskCreationTS)
if nextCreationTS.Equal(lastTaskCreationTS) {
schedule, err := cp.Parse(b.cron)
if err != nil {
b.log("Failed to parse cron string: " + err.Error())
return return
} }
// Figure out next task creation and deadline timestamps.
nextCreationTS := schedule.Next(lastTaskCreationTS)
// Check if task should be created and create if so. // Check if task should be created and create if so.
if nextCreationTS.Before(time.Now()) { if nextCreationTS.Before(time.Now()) {
// Deadlines should be calculated until first one will appear AFTER today. // Deadlines should be calculated until first one will appear AFTER today.

View File

@ -4,6 +4,31 @@ import (
"go.dev.pztrn.name/periodicator/internal/gitlab" "go.dev.pztrn.name/periodicator/internal/gitlab"
) )
// PrintCreationTSes prints tasks creation timestamps.
func PrintCreationTSes(client *gitlab.Client, tasks []Config) {
for _, task := range tasks {
t := &BaseTask{
client: client,
projectID: task.ProjectID,
title: task.Title,
body: task.Body,
tags: task.Tags,
executionStartTimestamp: task.ExecutionStart.GetTimestamp(),
cron: task.Cron,
dueIn: task.DueIn,
}
// Get similar tasks.
// ToDo: refactor?
issues, err := t.getIssues()
if err != nil {
panic("Error while getting issues from Gitlab: " + err.Error())
}
t.log(t.getNextCreationTimestamp(t.getLastCreationTimestamp(issues)).String())
}
}
// Process processes passed tasks. // Process processes passed tasks.
func Process(client *gitlab.Client, tasks []Config) { func Process(client *gitlab.Client, tasks []Config) {
for _, task := range tasks { for _, task := range tasks {

10
main.go
View File

@ -11,7 +11,10 @@ import (
"go.dev.pztrn.name/periodicator/internal/tasks" "go.dev.pztrn.name/periodicator/internal/tasks"
) )
var showVersion = flag.Bool("version", false, "Show version information and exit") var (
showNextCreationTS = flag.Bool("show-next-creation-ts", false, "Show tasks next creation timestamps")
showVersion = flag.Bool("version", false, "Show version information and exit")
)
func main() { func main() {
flag.Parse() flag.Parse()
@ -28,5 +31,10 @@ func main() {
c := gitlab.NewGitlabClient(&cfg.Gitlab) c := gitlab.NewGitlabClient(&cfg.Gitlab)
if *showNextCreationTS {
tasks.PrintCreationTSes(c, cfg.Tasks)
os.Exit(0)
}
tasks.Process(c, cfg.Tasks) tasks.Process(c, cfg.Tasks)
} }