Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
7fa3553da6
|
|||
14581dbe83
|
|||
3053c62fa8
|
|||
880ad68663
|
|||
91f4676118
|
|||
e315c37bb6
|
|||
c4ff0acc8a
|
|||
cedbc80a6e
|
|||
c8411ff6e8
|
|||
7bc47cf428
|
|||
5c4a169040
|
|||
0018c79b89
|
24
.drone.yml
Normal file
24
.drone.yml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: build
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: lint
|
||||||
|
image: code.pztrn.name/containers/mirror/golangci/golangci-lint:v1.46.2
|
||||||
|
environment:
|
||||||
|
CGO_ENABLED: 0
|
||||||
|
commands:
|
||||||
|
- golangci-lint run
|
||||||
|
|
||||||
|
- name: docker
|
||||||
|
image: code.pztrn.name/containers/mirror/plugins/docker:20.13.0
|
||||||
|
when:
|
||||||
|
branch: ["master"]
|
||||||
|
settings:
|
||||||
|
registry: code.pztrn.name
|
||||||
|
username: drone
|
||||||
|
password:
|
||||||
|
from_secret: drone_secret
|
||||||
|
repo: code.pztrn.name/apps/periodicator
|
||||||
|
auto_tag: true
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
*DS_Store*
|
*DS_Store*
|
||||||
.idea
|
.idea
|
||||||
|
.vscode
|
||||||
config.yaml
|
config.yaml
|
||||||
release
|
release
|
||||||
|
@@ -38,7 +38,7 @@ build_master_image:
|
|||||||
- apk add --no-cache git bash
|
- apk add --no-cache git bash
|
||||||
- scripts/get_version.sh generate
|
- scripts/get_version.sh generate
|
||||||
- docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
|
- docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
|
||||||
- docker build --pull -t ${REGISTRY_IMAGE_LATEST} --build-arg CI_COMMIT_TAG=${CI_COMMIT_TAG} --build-arg CI_COMMIT_REF_NAME=${CI_COMMIT_REF_NAME} --build-arg CI_COMMIT_SHA=${CI_COMMIT_SHA} --build-arg CI_PROJECT_NAME=${CI_PROJECT_NAME} .
|
- docker build --pull -t ${REGISTRY_IMAGE_LATEST} .
|
||||||
- docker push ${REGISTRY_IMAGE_LATEST}
|
- docker push ${REGISTRY_IMAGE_LATEST}
|
||||||
|
|
||||||
build_tag_image:
|
build_tag_image:
|
||||||
@@ -52,5 +52,7 @@ build_tag_image:
|
|||||||
- apk add --no-cache git bash
|
- apk add --no-cache git bash
|
||||||
- scripts/get_version.sh generate
|
- scripts/get_version.sh generate
|
||||||
- docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
|
- docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
|
||||||
- docker build -t ${REGISTRY_IMAGE_TAGGED} --build-arg CI_COMMIT_TAG=${CI_COMMIT_TAG} --build-arg CI_COMMIT_REF_NAME=${CI_COMMIT_REF_NAME} --build-arg CI_COMMIT_SHA=${CI_COMMIT_SHA} --build-arg CI_PROJECT_NAME=${CI_PROJECT_NAME} .
|
- docker build -t ${REGISTRY_IMAGE_TAGGED} .
|
||||||
|
- docker build -t ${REGISTRY_IMAGE_LATEST} .
|
||||||
- docker push ${REGISTRY_IMAGE_TAGGED}
|
- docker push ${REGISTRY_IMAGE_TAGGED}
|
||||||
|
- docker push ${REGISTRY_IMAGE_LATEST}
|
||||||
|
@@ -16,6 +16,8 @@ linters:
|
|||||||
- testpackage
|
- testpackage
|
||||||
# Crashes a lot.
|
# Crashes a lot.
|
||||||
- gci
|
- gci
|
||||||
|
# Deprecated.
|
||||||
|
- exhaustivestruct
|
||||||
linters-settings:
|
linters-settings:
|
||||||
lll:
|
lll:
|
||||||
line-length: 128
|
line-length: 128
|
||||||
|
16
CHANGELOG.md
16
CHANGELOG.md
@@ -6,6 +6,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [0.2.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- License information. We're on MIT.
|
||||||
|
- Ability to show next issue/task creation timestamp using ``-show-next-creation-ts`` flag.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- "latest" Docker tag is now always latest, even when building images for tags.
|
||||||
|
- Update github.com/robfig/cron to v3.
|
||||||
|
|
||||||
## [0.1.0] - 2021-09-29
|
## [0.1.0] - 2021-09-29
|
||||||
|
|
||||||
- Initial release with ability to create issues on Gitlab (both hosted and self-hosted).
|
- Initial release with ability to create issues on Gitlab (both hosted and self-hosted).
|
||||||
|
|
||||||
|
[Unreleased]: https://gitlab.pztrn.name/pztrn/periodicator/-/compare/v0.1.0...master
|
||||||
|
[0.2.0]: https://gitlab.pztrn.name/pztrn/periodicator/-/compare/v0.1.0...v0.2.0
|
||||||
|
[0.1.0]: https://gitlab.pztrn.name/pztrn/periodicator/-/releases/v0.1.0
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.17.1-alpine AS build
|
FROM code.pztrn.name/containers/mirror/golang:1.18.3-alpine AS build
|
||||||
|
|
||||||
WORKDIR /go/src/go.dev.pztrn.name/periodicator
|
WORKDIR /go/src/go.dev.pztrn.name/periodicator
|
||||||
COPY . .
|
COPY . .
|
||||||
@@ -6,7 +6,7 @@ COPY . .
|
|||||||
ENV CGO_ENABLED=0
|
ENV CGO_ENABLED=0
|
||||||
RUN apk add make && make build
|
RUN apk add make && make build
|
||||||
|
|
||||||
FROM alpine:latest
|
FROM code.pztrn.name/containers/mirror/alpine:3.16.0
|
||||||
LABEL maintainer="Stanislav N. <pztrn@pztrn.name>"
|
LABEL maintainer="Stanislav N. <pztrn@pztrn.name>"
|
||||||
|
|
||||||
COPY --from=build /go/src/go.dev.pztrn.name/periodicator/periodicator /usr/local/bin/periodicator
|
COPY --from=build /go/src/go.dev.pztrn.name/periodicator/periodicator /usr/local/bin/periodicator
|
||||||
|
7
LICENSE
Normal file
7
LICENSE
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Copyright 2021, Stanislav N. aka pztrn and Periodicator developers.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
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
|
||||||
|
@@ -17,7 +17,7 @@ Head over releases page, grab your binary and configure your system to start bin
|
|||||||
Compose a configuration file (read below) and add this to your cron:
|
Compose a configuration file (read below) and add this to your cron:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
docker run --rm -v ./config.yaml:/periodicator.yaml registry.gitlab.pztrn.name/pztrn/periodicator:latest
|
docker run --rm -v ./config.yaml:/periodicator.yaml pztrn/periodicator:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuring
|
## Configuring
|
||||||
|
2
go.mod
2
go.mod
@@ -3,7 +3,7 @@ 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
|
||||||
)
|
)
|
||||||
|
4
go.sum
4
go.sum
@@ -125,8 +125,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=
|
||||||
|
@@ -45,12 +45,12 @@ func Parse() *Config {
|
|||||||
panic("Failed to read configuration file data: " + readErr.Error())
|
panic("Failed to read configuration file data: " + readErr.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// nolint:exhaustivestruct
|
// nolint:exhaustruct
|
||||||
c := &Config{}
|
cfg := &Config{}
|
||||||
|
|
||||||
if err := yaml.Unmarshal(data, c); err != nil {
|
if err := yaml.Unmarshal(data, cfg); err != nil {
|
||||||
panic("Failed to unmarshal YAML data: " + err.Error())
|
panic("Failed to unmarshal YAML data: " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return c
|
return cfg
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,7 @@ type Client struct {
|
|||||||
|
|
||||||
// NewGitlabClient creates new Gitlab's client controlling structure.
|
// NewGitlabClient creates new Gitlab's client controlling structure.
|
||||||
func NewGitlabClient(cfg *Config) *Client {
|
func NewGitlabClient(cfg *Config) *Client {
|
||||||
// nolint:exhaustivestruct
|
// nolint:exhaustruct
|
||||||
c := &Client{
|
c := &Client{
|
||||||
config: cfg,
|
config: cfg,
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ func (c *Client) GetClient() *gitlab.Client {
|
|||||||
// GetIssuesByTitle returns list of issues that matches passed title in specific
|
// GetIssuesByTitle returns list of issues that matches passed title in specific
|
||||||
// project.
|
// project.
|
||||||
func (c *Client) GetIssuesByTitle(projectID int, title string) ([]*gitlab.Issue, error) {
|
func (c *Client) GetIssuesByTitle(projectID int, title string) ([]*gitlab.Issue, error) {
|
||||||
// nolint:exhaustivestruct
|
// nolint:exhaustruct
|
||||||
issues, resp, err := c.client.Issues.ListProjectIssues(projectID, &gitlab.ListProjectIssuesOptions{
|
issues, resp, err := c.client.Issues.ListProjectIssues(projectID, &gitlab.ListProjectIssuesOptions{
|
||||||
ListOptions: gitlab.ListOptions{
|
ListOptions: gitlab.ListOptions{
|
||||||
PerPage: 1000,
|
PerPage: 1000,
|
||||||
|
@@ -4,22 +4,20 @@ 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"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BaseTask is a base task structure.
|
// BaseTask is a base task structure.
|
||||||
type BaseTask struct {
|
type BaseTask struct {
|
||||||
client *gitlab.Client
|
|
||||||
|
|
||||||
projectID int
|
|
||||||
title string
|
|
||||||
body string
|
|
||||||
tags []string
|
|
||||||
|
|
||||||
executionStartTimestamp time.Time
|
executionStartTimestamp time.Time
|
||||||
|
client *gitlab.Client
|
||||||
|
title string
|
||||||
|
body string
|
||||||
cron string
|
cron string
|
||||||
|
tags []string
|
||||||
|
projectID int
|
||||||
dueIn time.Duration
|
dueIn time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +37,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 +75,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 +94,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.
|
||||||
@@ -107,7 +123,7 @@ func (b *BaseTask) Run() {
|
|||||||
|
|
||||||
b.log("Found no opened tasks and task should be created, doing so. Task deadline: " + nextDeadlineTS.String())
|
b.log("Found no opened tasks and task should be created, doing so. Task deadline: " + nextDeadlineTS.String())
|
||||||
|
|
||||||
// nolint:exhaustivestruct
|
// nolint:exhaustruct
|
||||||
err := b.client.CreateIssue(b.projectID, &g.CreateIssueOptions{
|
err := b.client.CreateIssue(b.projectID, &g.CreateIssueOptions{
|
||||||
Title: &b.title,
|
Title: &b.title,
|
||||||
Description: &b.body,
|
Description: &b.body,
|
||||||
|
@@ -5,12 +5,12 @@ import "time"
|
|||||||
// Config is a task's configuration as should be defined in configuration file.
|
// Config is a task's configuration as should be defined in configuration file.
|
||||||
// nolint:tagliatelle
|
// nolint:tagliatelle
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ProjectID int `yaml:"project_id"`
|
ExecutionStart TaskStartTime `yaml:"execution_start"`
|
||||||
Title string `yaml:"title"`
|
Title string `yaml:"title"`
|
||||||
Body string `yaml:"body"`
|
Body string `yaml:"body"`
|
||||||
Tags []string `yaml:"tags"`
|
|
||||||
ExecutionStart TaskStartTime `yaml:"execution_start"`
|
|
||||||
Cron string `yaml:"cron"`
|
Cron string `yaml:"cron"`
|
||||||
|
Tags []string `yaml:"tags"`
|
||||||
|
ProjectID int `yaml:"project_id"`
|
||||||
DueIn time.Duration `yaml:"due_in"`
|
DueIn time.Duration `yaml:"due_in"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,14 +30,14 @@ func (tts *TaskStartTime) UnmarshalYAML(unmarshal func(interface{}) error) error
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
t, err := time.Parse("2006-01-02 15:04:05", timeData)
|
timeField, err := time.Parse("2006-01-02 15:04:05", timeData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// ToDo: fix it!
|
// ToDo: fix it!
|
||||||
// nolint:wrapcheck
|
// nolint:wrapcheck
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
tts.ts = t
|
tts.ts = timeField
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -4,10 +4,10 @@ import (
|
|||||||
"go.dev.pztrn.name/periodicator/internal/gitlab"
|
"go.dev.pztrn.name/periodicator/internal/gitlab"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Process processes passed tasks.
|
// PrintCreationTSes prints tasks creation timestamps.
|
||||||
func Process(client *gitlab.Client, tasks []Config) {
|
func PrintCreationTSes(client *gitlab.Client, tasks []Config) {
|
||||||
for _, task := range tasks {
|
for _, task := range tasks {
|
||||||
t := &BaseTask{
|
taskData := &BaseTask{
|
||||||
client: client,
|
client: client,
|
||||||
projectID: task.ProjectID,
|
projectID: task.ProjectID,
|
||||||
title: task.Title,
|
title: task.Title,
|
||||||
@@ -18,6 +18,31 @@ func Process(client *gitlab.Client, tasks []Config) {
|
|||||||
dueIn: task.DueIn,
|
dueIn: task.DueIn,
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run()
|
// Get similar tasks.
|
||||||
|
// ToDo: refactor?
|
||||||
|
issues, err := taskData.getIssues()
|
||||||
|
if err != nil {
|
||||||
|
panic("Error while getting issues from Gitlab: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
taskData.log(taskData.getNextCreationTimestamp(taskData.getLastCreationTimestamp(issues)).String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process processes passed tasks.
|
||||||
|
func Process(client *gitlab.Client, tasks []Config) {
|
||||||
|
for _, task := range tasks {
|
||||||
|
taskData := &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,
|
||||||
|
}
|
||||||
|
|
||||||
|
taskData.Run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
main.go
14
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()
|
||||||
@@ -26,7 +29,12 @@ func main() {
|
|||||||
|
|
||||||
cfg := config.Parse()
|
cfg := config.Parse()
|
||||||
|
|
||||||
c := gitlab.NewGitlabClient(&cfg.Gitlab)
|
gitlabClient := gitlab.NewGitlabClient(&cfg.Gitlab)
|
||||||
|
|
||||||
tasks.Process(c, cfg.Tasks)
|
if *showNextCreationTS {
|
||||||
|
tasks.PrintCreationTSes(gitlabClient, cfg.Tasks)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.Process(gitlabClient, cfg.Tasks)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user