Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert age matcher to use a duration config #159

Merged
merged 4 commits into from
Nov 22, 2024
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
37 changes: 23 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Please consider [sponsoring the project](https://github.com/sponsors/srvaroa) if
### How to trigger action

To trigger the action on events, add a file `.github/workflows/main.yml`
to your repository:
to your repository:

```yaml
name: Label PRs
Expand Down Expand Up @@ -294,7 +294,7 @@ With this config, the behaviour changes:

## Conditions

Below are the conditions currently supported in label matchers, in
Below are the conditions currently supported in label matchers, in
alphabetical order. Some important considerations:

* Conditions evaluate only when they are explicitly added in
Expand All @@ -308,20 +308,29 @@ alphabetical order. Some important considerations:

### Age (PRs and Issues) <a name="age" />

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.
This condition evaluates the creation date of the PR or Issue.

If you're looking to evaluate on the modification date of the issue or PR,
If you're looking to evaluate on the modification date of the issue or PR,
check on <a href="#last-modified" ></a>

This condition is best used when with a <a href="#schedule">schedule trigger</a>.

Example:
Examples:

```yaml
age-range:
at-most: 1d
```

Will label PRs or issues that were created at most one day ago.

```yaml
age: 1d
age-range:
at-least: 1w
```

Will label PRs or issues that were created at least one week ago.

The syntax for values is based on a number, followed by a suffix:

* s: seconds
Expand Down Expand Up @@ -412,7 +421,7 @@ This condition is satisfied when any of the PR files matches on the
given regexs.

```yaml
files:
files:
- "cmd\\/.*_tests.go"
- ".*\\/subfolder\\/.*\\.md"
```
Expand All @@ -425,9 +434,9 @@ and therefore must be escaped itself to appear as a literal in the regex.

### Last Modified (PRs and Issues) <a name="last-modified" />

This condition evaluates the modification date of the PR or Issue.
This condition evaluates the modification date of the PR or Issue.

If you're looking to evaluate on the creation date of the issue or PR,
If you're looking to evaluate on the creation date of the issue or PR,
check on <a href="#age" ></a>

This condition is best used when with a <a href="#schedule">schedule trigger</a>.
Expand Down Expand Up @@ -462,19 +471,19 @@ For example, `2d` means 2 days, `4w` means 4 weeks, and so on.

This condition is satisfied when the [mergeable
state](https://developer.github.com/v3/pulls/#response-1) matches that
of the PR.
of the PR.

```yaml
mergeable: True
```

Will match if the label is mergeable.
Will match if the label is mergeable.

```yaml
mergeable: False
```

Will match if the label is not mergeable.
Will match if the label is not mergeable.

### Size (PRs only) <a name="size" />

Expand Down Expand Up @@ -518,7 +527,7 @@ file or a Regex expression:
size:
exclude-files: ["yarn.lock", "\\/root\\/.+\\/test.md"]
above: 100
```
```

This condition will apply the `L` label if the diff is above 100 lines,
but NOT taking into account changes in `yarn.lock`, or any `test.md`
Expand Down
43 changes: 38 additions & 5 deletions pkg/condition_age.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,35 @@ func AgeCondition(l *Labeler) Condition {
return target.ghIssue != nil || target.ghPR != nil
},
Evaluate: func(target *Target, matcher LabelMatcher) (bool, error) {
// Parse the age from the configuration
ageDuration, err := parseExtendedDuration(matcher.Age)
if err != nil {
return false, fmt.Errorf("failed to parse age parameter in configuration: %v", err)
// Backward compatibility: If "age" is provided as a string, treat it as "at-least"
var atLeastDuration, atMostDuration time.Duration
var err error

// If they have specified a legacy "age" field, use that
// and treat it is as "at-least"
if matcher.Age != "" {
atLeastDuration, err = parseExtendedDuration(matcher.Age)
if err != nil {
return false, fmt.Errorf("failed to parse age parameter in configuration: %v", err)
}
} else if matcher.AgeRange != nil {
// Parse "at-least" if specified
if matcher.AgeRange.AtLeast != "" {
atLeastDuration, err = parseExtendedDuration(matcher.AgeRange.AtLeast)
if err != nil {
return false, fmt.Errorf("failed to parse `age.at-least` parameter in configuration: %v", err)
}
}

// Parse "at-most" if specified
if matcher.AgeRange.AtMost != "" {
atMostDuration, err = parseExtendedDuration(matcher.AgeRange.AtMost)
if err != nil {
return false, fmt.Errorf("failed to parse `age.at-most` parameter in configuration: %v", err)
}
}
} else {
return false, fmt.Errorf("no age conditions are set in config")
}

// Determine the creation time of the issue or PR
Expand All @@ -30,7 +55,15 @@ func AgeCondition(l *Labeler) Condition {

age := time.Since(createdAt)

return age > ageDuration, nil
// Check if the age of the issue/PR is within the specified range
if atLeastDuration != 0 && age < atLeastDuration {
return false, nil
}
if atMostDuration != 0 && age > atMostDuration {
return false, nil
}

return true, nil
},
}
}
3 changes: 2 additions & 1 deletion pkg/labeler.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ type SizeConfig struct {
}

type LabelMatcher struct {
Age string
Age string `yaml:"age,omitempty"` // Deprecated age config.
AgeRange *DurationConfig `yaml:"age-range,omitempty"`
AuthorCanMerge string `yaml:"author-can-merge"`
Authors []string
AuthorInTeam string `yaml:"author-in-team"`
Expand Down
26 changes: 26 additions & 0 deletions pkg/labeler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,32 @@ func TestHandleEvent(t *testing.T) {
initialLabels: []string{},
expectedLabels: []string{"ThisIsOld"},
},
// Test the AgeRange configuration
{
event: "pull_request",
payloads: []string{"create_pr"},
name: "Age of a PR in the past",
config: LabelerConfigV1{
Version: 1,
Labels: []LabelMatcher{
{
Label: "Getting Old",
AgeRange: &DurationConfig{
AtLeast: "7d",
AtMost: "14d",
},
},
{
Label: "Getting Ancient",
AgeRange: &DurationConfig{
AtLeast: "14d",
},
},
},
},
initialLabels: []string{},
expectedLabels: []string{"Getting Ancient"},
},
{
event: "pull_request",
payloads: []string{"create_draft_pr"},
Expand Down
Loading