diff --git a/updater/group.go b/updater/group.go index 0e0ffce..d874d39 100644 --- a/updater/group.go +++ b/updater/group.go @@ -3,7 +3,9 @@ package updater import ( "fmt" "regexp" + "strconv" "strings" + "time" "github.com/dependabot/gomodules-extracted/cmd/go/_internal_/semver" ) @@ -17,19 +19,14 @@ type Group struct { // Parameters that apply to members: // Range is a comma separated list of allowed semver ranges - Range string `yaml:"range"` - Frequency Frequency `yaml:"frequency"` + Range string `yaml:"range"` + CoolDown string `yaml:"cooldown"` + PreScript string `yaml:"pre-script"` + PostScript string `yaml:"post-script"` compiledPattern *regexp.Regexp } -type Frequency string - -const ( - FrequencyDaily Frequency = "daily" - FrequencyWeekly Frequency = "weekly" -) - func (g *Group) Validate() error { if g.Name == "" { return fmt.Errorf("groups must specify name") @@ -37,10 +34,8 @@ func (g *Group) Validate() error { if g.Pattern == "" { return fmt.Errorf("groups must specify pattern") } - switch g.Frequency { - case "", FrequencyDaily, FrequencyWeekly: - default: - return fmt.Errorf("frequency must be: [%s,%s]", FrequencyDaily, FrequencyWeekly) + if !durPattern.MatchString(g.CoolDown) { + return fmt.Errorf("invalid cooldown, expected ISO8601 duration: %q", g.CoolDown) } if strings.HasPrefix(g.Pattern, "/") && strings.HasSuffix(g.Pattern, "/") { @@ -55,7 +50,7 @@ func (g *Group) Validate() error { return nil } -func (g Group) InRange(v string) bool { +func (g *Group) InRange(v string) bool { for _, rangeCond := range strings.Split(g.Range, ",") { rangeCond = strings.TrimSpace(rangeCond) switch { @@ -87,3 +82,42 @@ func cleanRange(rangeCond string, prefixLen int) string { } return s } + +var durPattern = regexp.MustCompile(`P?(((?P\d+)Y)?((?P\d+)M)?((?P\d+)D)|(?P\d+)W)?`) + +const ( + oneYear = 8766 * time.Hour + oneMonth = 730*time.Hour + 30*time.Minute + oneWeek = 7 * 24 * time.Hour + oneDay = 24 * time.Hour +) + +func (g *Group) CoolDownDuration() time.Duration { + m := durPattern.FindStringSubmatch(g.CoolDown) + + var ret time.Duration + for i, name := range durPattern.SubexpNames() { + part := m[i] + if i == 0 || name == "" || part == "" { + continue + } + + val, err := strconv.Atoi(part) + if err != nil { + return 0 + } + valDur := time.Duration(val) + switch name { + case "year": + ret += valDur * oneYear + case "month": + ret += valDur * oneMonth + case "week": + ret += valDur * oneWeek + case "day": + ret += valDur * oneDay + } + } + + return ret +} diff --git a/updater/group_test.go b/updater/group_test.go index de4fff7..9c97583 100644 --- a/updater/group_test.go +++ b/updater/group_test.go @@ -3,11 +3,32 @@ package updater_test import ( "fmt" "testing" + "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/thepwagner/action-update/updater" ) +func TestGroup_CoolDownDuration(t *testing.T) { + g := updater.Group{Name: "test", Pattern: "test"} + + cases := map[string]time.Duration{ + "P1D": 24 * time.Hour, + "1D": 24 * time.Hour, + "1W": 7 * 24 * time.Hour, + } + + for in, expected := range cases { + t.Run(in, func(t *testing.T) { + g.CoolDown = in + err := g.Validate() + require.NoError(t, err) + assert.Equal(t, expected, g.CoolDownDuration()) + }) + } +} + func TestGroup_InRange(t *testing.T) { cases := map[string]struct { included []string @@ -44,14 +65,15 @@ func TestGroup_InRange(t *testing.T) { for r, tc := range cases { t.Run(r, func(t *testing.T) { + u := &updater.Group{Range: r} for _, v := range tc.included { t.Run(fmt.Sprintf("includes %s", v), func(t *testing.T) { - assert.True(t, updater.Group{Range: r}.InRange(v)) + assert.True(t, u.InRange(v)) }) } for _, v := range tc.excluded { t.Run(fmt.Sprintf("excludes %q", v), func(t *testing.T) { - assert.False(t, updater.Group{Range: r}.InRange(v)) + assert.False(t, u.InRange(v)) }) } }) diff --git a/updater/groups_test.go b/updater/groups_test.go index ed8efbe..1bb3fda 100644 --- a/updater/groups_test.go +++ b/updater/groups_test.go @@ -25,10 +25,9 @@ func TestParseGroups(t *testing.T) { frequency: weekly range: ">=v1.4.0, =v1.4.0, =v1.4.0,