Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ func main() {
log.Printf("current: %v requested: %v", currentTime, requestedTime)
log.Printf("difference: %v configured: %v", numberOfDays, config.BufferWindowDays)

// found a case where action is needed
if uint8(numberOfDays) == config.BufferWindowDays {
// found a case where action is needed; both sides are ints now so
// the comparison is straightforward and cannot wrap around.
if numberOfDays == config.BufferWindowDays {
// do as scheduled on this date
projectInstance := client.GetProject(project)
errInfo := projectInstance.CreateIssue(schedule)
Expand Down
26 changes: 25 additions & 1 deletion internal/pkg/configs/configuration.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package configs

import (
"fmt"
"github-issue-schedule/internal/pkg/utils"
"io/ioutil"
"log"
Expand All @@ -10,7 +11,12 @@ import (

// Configuration to run the program
type Configuration struct {
BufferWindowDays uint8 `yaml:"buffer_window_days"`
// BufferWindowDays indicates how many days in advance a reminder
// issue should be created. Use a signed integer so configs can
// express reasonable values without worrying about overflow when
// comparing against days-calculated-from-the-clock. Negative values
// are invalid and the reader enforces this.
BufferWindowDays int `yaml:"buffer_window_days"`
Projects []Project `yaml:"projects"`
}

Expand Down Expand Up @@ -44,5 +50,23 @@ func ReadConfiguration() Configuration {
if err != nil {
log.Fatalf("Error while parsing the config file %v, Err: %v", configFile, err)
}

if err := config.validate(); err != nil {
log.Fatalf("invalid configuration: %v", err)
}

return config
}

// validate checks that fields in Configuration contain reasonable
// values. callers may use this directly in tests; ReadConfiguration
// itself fatals on any error.
func (c *Configuration) validate() error {
if c.BufferWindowDays < 0 {
return fmt.Errorf("buffer_window_days must be non-negative")
}
if c.BufferWindowDays > 100000 {
return fmt.Errorf("buffer_window_days is unreasonably large (%d)", c.BufferWindowDays)
}
return nil
}
30 changes: 30 additions & 0 deletions internal/pkg/configs/configuration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package configs

import (
"testing"
)

func TestConfigurationValidate(t *testing.T) {
cases := []struct {
desc string
conf Configuration
broken bool
}{
{"negative", Configuration{BufferWindowDays: -1}, true},
{"too large", Configuration{BufferWindowDays: 100001}, true},
{"zero", Configuration{BufferWindowDays: 0}, false},
{"normal", Configuration{BufferWindowDays: 7}, false},
}

for _, c := range cases {
t.Run(c.desc, func(t *testing.T) {
err := c.conf.validate()
if c.broken && err == nil {
t.Fatalf("expected error for config %+v", c.conf)
}
if !c.broken && err != nil {
t.Fatalf("did not expect error: %v", err)
}
})
}
}