Update to cron v3, ability to show next issues creation timestamps and little refactor.
This commit is contained in:
		
							
								
								
									
										5
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								Makefile
									
									
									
									
									
								
							| @@ -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
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								go.mod
									
									
									
									
									
								
							| @@ -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
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								go.sum
									
									
									
									
									
								
							| @@ -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= | ||||||
|   | |||||||
| @@ -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. | ||||||
|   | |||||||
| @@ -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
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								main.go
									
									
									
									
									
								
							| @@ -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) | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user