From cd24841c9e60b52c5691310b9723e4ac75803208 Mon Sep 17 00:00:00 2001 From: Galo Navarro Date: Mon, 2 Sep 2024 17:37:22 +0200 Subject: [PATCH] Support last-modified Signed-off-by: Galo Navarro --- .github/labeler.yml | 12 ++++++++ README.md | 32 +++++++++++++++++++ pkg/condition_age.go | 25 --------------- pkg/condition_last_modified.go | 34 +++++++++++++++++++++ pkg/labeler.go | 2 ++ pkg/util.go | 30 ++++++++++++++++++ pkg/{condition_age_test.go => util_test.go} | 0 7 files changed, 110 insertions(+), 25 deletions(-) create mode 100644 pkg/condition_last_modified.go create mode 100644 pkg/util.go rename pkg/{condition_age_test.go => util_test.go} (100%) diff --git a/.github/labeler.yml b/.github/labeler.yml index f4ed978..7f641c4 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,6 +1,18 @@ version: 1 labels: + # Type: Recent changes + - label: "@type/new" + last-modified: 1d + + # Type: Old changes + - label: "@type/old" + last-modified: 30d + + # Type: Build-related changes + - label: "@type/recently-changed" + last-modified: 1d + # Type: Build-related changes - label: "@type/build" title: '^build(?:\(.+\))?\!?:' diff --git a/README.md b/README.md index 9ba325c..ad1107b 100644 --- a/README.md +++ b/README.md @@ -309,6 +309,9 @@ alphabetical order. Some important considerations: This condition is satisfied when the age of the PR or Issue are larger than the given one. The age is calculated from the creation date. +If you're looking to evaluate on the modification date of the issue or PR, +check on + This condition is best used when with a schedule trigger. Example: @@ -407,6 +410,35 @@ regular expressions (Regex). Special characters need to be escaped with double backslashes. This is because the backslash in Go strings is an escape character and therefore must be escaped itself to appear as a literal in the regex. +### Last Modified (PRs and Issues) + +This condition is satisfied when the modification date of the PR or Issue is +larger than the given one. + +If you're looking to evaluate on the creation date of the issue or PR, +check on + +This condition is best used when with a schedule trigger. + +Example: + +```yaml +last-modified: 1d +``` + +Will label PRs that were last modified one or more days ago. + +The syntax for values is based on a number, followed by a suffix: + +* s: seconds +* m: minutes +* h: hours +* d: days +* w: weeks +* y: years + +For example, `2d` means 2 days, `4w` means 4 weeks, and so on. + ### Mergeable status (PRs only) This condition is satisfied when the [mergeable diff --git a/pkg/condition_age.go b/pkg/condition_age.go index b27de0b..be04a36 100644 --- a/pkg/condition_age.go +++ b/pkg/condition_age.go @@ -2,8 +2,6 @@ package labeler import ( "fmt" - "strconv" - "strings" "time" ) @@ -36,26 +34,3 @@ func AgeCondition(l *Labeler) Condition { }, } } - -func parseExtendedDuration(s string) (time.Duration, error) { - multiplier := time.Hour * 24 // default to days - - if strings.HasSuffix(s, "w") { - multiplier = time.Hour * 24 * 7 // weeks - s = strings.TrimSuffix(s, "w") - } else if strings.HasSuffix(s, "y") { - multiplier = time.Hour * 24 * 365 // years - s = strings.TrimSuffix(s, "y") - } else if strings.HasSuffix(s, "d") { - s = strings.TrimSuffix(s, "d") // days - } else { - return time.ParseDuration(s) // default to time.ParseDuration for hours, minutes, seconds - } - - value, err := strconv.Atoi(s) - if err != nil { - return 0, err - } - - return time.Duration(value) * multiplier, nil -} diff --git a/pkg/condition_last_modified.go b/pkg/condition_last_modified.go new file mode 100644 index 0000000..4deedff --- /dev/null +++ b/pkg/condition_last_modified.go @@ -0,0 +1,34 @@ +package labeler + +import ( + "fmt" + "time" +) + +func LastModifiedCondition(l *Labeler) Condition { + return Condition{ + GetName: func() string { + return "Last modification of issue/PR" + }, + CanEvaluate: func(target *Target) bool { + return target.ghIssue != nil || target.ghPR != nil + }, + Evaluate: func(target *Target, matcher LabelMatcher) (bool, error) { + // Parse the age from the configuration + threshold, err := parseExtendedDuration(matcher.LastModified) + if err != nil { + return false, fmt.Errorf("failed to parse last-modified parameter in configuration: %v", err) + } + + // Determine the last modification time of the issue or PR + var lastModified time.Time + if target.ghIssue != nil { + lastModified = target.ghIssue.UpdatedAt.Time + } else if target.ghPR != nil { + lastModified = target.ghPR.UpdatedAt.Time + } + + return time.Since(lastModified) > threshold, nil + }, + } +} diff --git a/pkg/labeler.go b/pkg/labeler.go index eb19ef7..af79336 100644 --- a/pkg/labeler.go +++ b/pkg/labeler.go @@ -23,6 +23,7 @@ type LabelMatcher struct { Draft string Files []string Label string + LastModified string `yaml:"last-modified"` Mergeable string Negate bool Size *SizeConfig @@ -223,6 +224,7 @@ func (l *Labeler) findMatches(target *Target, config *LabelerConfigV1) (LabelUpd BodyCondition(), BranchCondition(), FilesCondition(l), + LastModifiedCondition(l), IsDraftCondition(), IsMergeableCondition(), SizeCondition(l), diff --git a/pkg/util.go b/pkg/util.go new file mode 100644 index 0000000..3d2988b --- /dev/null +++ b/pkg/util.go @@ -0,0 +1,30 @@ +package labeler + +import ( + "strconv" + "strings" + "time" +) + +func parseExtendedDuration(s string) (time.Duration, error) { + multiplier := time.Hour * 24 // default to days + + if strings.HasSuffix(s, "w") { + multiplier = time.Hour * 24 * 7 // weeks + s = strings.TrimSuffix(s, "w") + } else if strings.HasSuffix(s, "y") { + multiplier = time.Hour * 24 * 365 // years + s = strings.TrimSuffix(s, "y") + } else if strings.HasSuffix(s, "d") { + s = strings.TrimSuffix(s, "d") // days + } else { + return time.ParseDuration(s) // default to time.ParseDuration for hours, minutes, seconds + } + + value, err := strconv.Atoi(s) + if err != nil { + return 0, err + } + + return time.Duration(value) * multiplier, nil +} diff --git a/pkg/condition_age_test.go b/pkg/util_test.go similarity index 100% rename from pkg/condition_age_test.go rename to pkg/util_test.go