Skip to content

[JENKINS-64810] Add creation time boundaries to tags for discovery#1764

Open
dodo920306 wants to merge 11 commits intojenkinsci:masterfrom
dodo920306:feature/ignore-tags-not-within-the-time-boundary
Open

[JENKINS-64810] Add creation time boundaries to tags for discovery#1764
dodo920306 wants to merge 11 commits intojenkinsci:masterfrom
dodo920306:feature/ignore-tags-not-within-the-time-boundary

Conversation

@dodo920306
Copy link

@dodo920306 dodo920306 commented Jun 1, 2025

[JENKINS-64810] Multibranch pipeline still showing Git tags older than configured threshold

This PR does not address JENKINS-64810 in the way originally expected, because the issue stems from a misunderstanding of the help messages in the basic-branch-build-strategies-plugin.

The plugin currently describes the time-based tag filtering as:

The number of days since the tag was created before it is eligible for automatic building.

and

The number of days since the tag was created after which it is no longer eligible for automatic building.

The original issue incorrectly assumed that these settings should remove tag jobs outside the configured time range. However, what the basic-branch-build-strategies-plugin actually implements is an extension of jenkins.branch.BranchBuildStrategy from the branch-api-plugin, which does not have the authority to remove jobs. It simply prevents automatic builds for tags outside the specified time window—which it already does correctly.

While it might seem that this issue could be closed based on this clarification, I believe otherwise. After reaching out to the original reporter, Dirk Heinrichs, I found that—despite the misunderstanding of the underlying mechanism—their actual user need remains valid. As the reporter put it:

I guess the logic, or expectations in the plugin are wrong. It removes branch jobs X days after branch removal according to the configured retention time. But it seems to treat tag jobs in the same way, which is wrong, since tags are usually never removed. So since it correctly ignores tags created more than X days ago when creating tag jobs, it does not have any mechanism to remove the jobs again.
So what this ticket really is about is to treat tag jobs (or better: their removal) differently than branch jobs. For example: Remove tag jobs X days after their last (successful) build.

While this problem shouldn't be addressed by modifying the basic-branch-build-strategies-plugin, the user still needs a way to visibly filter old or future tag jobs through the UI.

After tracing through the codebase, I found that this functionality could be effectively implemented in the git-plugin. In this PR, I introduce two new string parameters—atLeastDays and atMostDays—to the TagDiscoveryTrait class. These parameters mirror the ones from the basic-branch-build-strategies-plugin and define the lower and upper bounds for the tag creation time.

I then added corresponding logic to GitSCMSourceContext to accept and propagate these values (converted into long), and finally used them in AbstractGitSCMSource inside the discoverTags function to filter tags based on age:

...
if (atLeastMillis >= 0L || atMostMillis >= 0L) {
    if (atMostMillis >= 0L && atLeastMillis > atMostMillis) {
        /* Invalid. It's impossible for any tag to satisfy this. */
        continue;
    }
    long tagAge = System.currentTimeMillis() - lastModified;
    if (atMostMillis >= 0L && tagAge > atMostMillis) {
        continue;
    }
    if (atLeastMillis >= 0L && tagAge < atLeastMillis) {
        continue;
    }
}
...

This implementation and its corresponding UI (.jelly definitions) are heavily based on TagBuildStrategyImpl from the basic-branch-build-strategies-plugin.

If this PR is merged, users will be able to use TagDiscoveryTrait to filter tag jobs by creation time, thereby fulfilling the practical need described in JENKINS-64810—even though the original interpretation of the issue was flawed.

Please also let me know if there’s anything I should revise or improve. Thank you for your time and guidance!

Testing done

None yet.
I could use some help here, as I'm unsure how to add proper tests for this change in AbstractGitSCMSourceTest.
I've installed it on my local Jenkins instance, and it works well with my git tags.

Submitter checklist

  • Make sure you are opening from a topic/feature/bugfix branch (right side) and not your main branch!
  • Ensure that the pull request title represents the desired changelog entry
  • Please describe what you did
  • Link to relevant issues in GitHub or Jira
  • Link to relevant pull requests, esp. upstream and downstream changes
  • Ensure you have provided tests that demonstrate the feature works or the issue is fixed

Introduce upper and lower bounds for tag creation time in TagDiscoveryTrait,
allowing AbstractGitSCMSource to determine whether a tag should be included
based on its timestamp.

Signed-off-by: dodo920306 <dodo920306@gmail.com>
@dodo920306 dodo920306 requested a review from a team as a code owner June 1, 2025 06:53
@dodo920306
Copy link
Author

dodo920306 commented Jul 9, 2025

Hello?
@jenkinsci/git-plugin-developers

@MarkEWaite
Copy link
Contributor

Hello? @jenkinsci/git-plugin-developers

Hi. I'm deeply involved in other topics currently. I don't expect to review this pull request for a month at least. You can use the incremental build of the pull request in your use so that you immediately get the benefit of your changes. When new changes merge to the master branch, update your branch with those changes and a new incremental build will be pushed to the Jenkins artifact repository.

@MarkEWaite MarkEWaite added the bug Incorrect or flawed behavior label Oct 3, 2025
@dodo920306
Copy link
Author

@MarkEWaite Is there any problem with this MR?

@MarkEWaite
Copy link
Contributor

@MarkEWaite Is there any problem with this MR?

I'm not available to review this pull request currently. Many other things are much higher priority for me.

You're welcome to use the incremental build of the plugin yourself and report your results. You're welcome to encourage others to use the incremental build of the plugin and report their results.

@MarkEWaite
Copy link
Contributor

MarkEWaite commented Jan 23, 2026

@MarkEWaite Is there any problem with this MR?

I found an immediate problem when I reviewed the names of the files that have been modified. The pull request includes no tests to show the problem and no tests to show that the problem is resolved. The git plugin is used in over 250,000 installations. I won't accept new functionality without very good automated test coverage.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds time-based filtering capabilities to the Git plugin's TagDiscoveryTrait, allowing users to filter discovered tags by their creation time (commit time). This addresses JENKINS-64810 by providing a mechanism to limit the visibility of tag jobs based on age boundaries, complementing the existing build strategy filters that only prevent automatic builds.

Changes:

  • Added atLeastDays and atMostDays parameters to TagDiscoveryTrait to define minimum and maximum tag ages
  • Extended GitSCMSourceContext with methods to convert day values to milliseconds and store the time boundaries
  • Modified AbstractGitSCMSource.discoverTags() to filter tags based on their age relative to current time

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 12 comments.

File Description
src/main/java/jenkins/plugins/git/traits/TagDiscoveryTrait.java Added constructor parameters and fields for time boundaries, along with getter methods
src/main/java/jenkins/plugins/git/GitSCMSourceContext.java Added fields to store time limits in milliseconds and conversion methods from days
src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java Added filtering logic in discoverTags method to skip tags outside the configured time window
src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/config.jelly Added UI input fields for the time boundary parameters

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 5 to 8
<f:number default=""/>
</f:entry>
<f:entry field="atMostDays" title="${%Ignore tags older than}">
<f:number default="7"/>
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new configuration fields "atLeastDays" and "atMostDays" lack help documentation. The config.jelly file adds these fields but there are no corresponding help-atLeastDays.html and help-atMostDays.html files to explain to users what these fields do.

These help files should explain:

  1. What the fields control (filtering tags by age)
  2. How the age is calculated (from tag creation/commit time)
  3. What empty/blank values mean
  4. Examples of usage (e.g., "Enter 7 to ignore tags older than 7 days")
  5. How these interact with each other (atMostDays should be greater than atLeastDays)

This is especially important since the UI labels "Ignore tags newer than" and "Ignore tags older than" might be confusing without additional context.

Suggested change
<f:number default=""/>
</f:entry>
<f:entry field="atMostDays" title="${%Ignore tags older than}">
<f:number default="7"/>
<f:number default=""/>
<f:help>
<p>
Minimum age of tags (in days) to <strong>include</strong> when discovering tags.
Tags newer than this value are ignored.
</p>
<p>
Tag age is calculated from the tag creation / commit timestamp to the time the
scan runs.
</p>
<p>
Leave this field blank to <strong>not</strong> filter out tags based on a minimum age
(no lower age bound).
</p>
<p>
Examples:
</p>
<ul>
<li><code>7</code> – ignore tags created in the last 7 days (only tags at least 7 days old are used).</li>
<li><code>0</code> – do not ignore tags for being too new (equivalent to leaving it blank).</li>
</ul>
<p>
When used together with <em>Ignore tags older than</em> (<code>atMostDays</code>),
this value should be less than or equal to the <em>older than</em> value to define a valid age range.
</p>
</f:help>
</f:entry>
<f:entry field="atMostDays" title="${%Ignore tags older than}">
<f:number default="7"/>
<f:help>
<p>
Maximum age of tags (in days) to <strong>include</strong> when discovering tags.
Tags older than this value are ignored.
</p>
<p>
Tag age is calculated from the tag creation / commit timestamp to the time the
scan runs.
</p>
<p>
Leave this field blank to <strong>not</strong> filter out tags based on a maximum age
(no upper age bound).
</p>
<p>
Examples:
</p>
<ul>
<li><code>7</code> – ignore tags older than 7 days (only tags from the last 7 days are used).</li>
<li><code>30</code> – ignore tags older than 30 days (only tags from the last 30 days are used).</li>
</ul>
<p>
When used together with <em>Ignore tags newer than</em> (<code>atLeastDays</code>),
this value should be greater than or equal to the <em>newer than</em> value so that the
age range is consistent.
</p>
</f:help>

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no other traits that includes such help messages for their fields in this project.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no other traits that includes such help messages for their fields in this project.

GitHub Copilot suggested the wrong approach here. Please refer to the following example files for the correct approach to add online help to traits:

  • src/main/resources/jenkins/plugins/git/traits/BranchDiscoveryTrait/help.html
  • src/main/resources/jenkins/plugins/git/traits/DiscoverOtherRefsTrait/help-nameMapping.html
  • src/main/resources/jenkins/plugins/git/traits/DiscoverOtherRefsTrait/help-ref.html
  • src/main/resources/jenkins/plugins/git/traits/DiscoverOtherRefsTrait/help.html
  • src/main/resources/jenkins/plugins/git/traits/RefSpecsSCMSourceTrait/RefSpecTemplate/help-value.html
  • src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/help.html

Copy link
Author

@dodo920306 dodo920306 Jan 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GitHub Copilot suggested the wrong approach here. Please refer to the following example files for the correct approach to add online help to traits:

* src/main/resources/jenkins/plugins/git/traits/BranchDiscoveryTrait/help.html

* src/main/resources/jenkins/plugins/git/traits/DiscoverOtherRefsTrait/help-nameMapping.html

* src/main/resources/jenkins/plugins/git/traits/DiscoverOtherRefsTrait/help-ref.html

* src/main/resources/jenkins/plugins/git/traits/DiscoverOtherRefsTrait/help.html

* src/main/resources/jenkins/plugins/git/traits/RefSpecsSCMSourceTrait/RefSpecTemplate/help-value.html

* src/main/resources/jenkins/plugins/git/traits/TagDiscoveryTrait/help.html

OK.

Comment on lines +79 to 81
ctx.withAtLeastTagCommitTimeDays(atLeastDays)
.withAtMostTagCommitTimeDays(atMostDays);
}
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR adds new functionality (time-based tag filtering) but mentions "None yet" for testing. The AbstractGitSCMSourceTest file already has comprehensive test coverage for TagDiscoveryTrait (as seen in tests like retrieveHeadsSupportsTagDiscovery_findTagsWithTagDiscoveryTrait), but there are no tests for the new time-based filtering parameters.

Tests should be added to verify:

  1. Tags are correctly filtered when atLeastDays is set (tags newer than threshold are excluded)
  2. Tags are correctly filtered when atMostDays is set (tags older than threshold are excluded)
  3. Both parameters work together correctly
  4. Edge case: when atLeastDays > atMostDays (invalid configuration), no tags are discovered
  5. Null/empty values are handled correctly (no filtering applied)
  6. Invalid input (non-numeric strings) is handled gracefully

This is important to ensure the feature works as expected and to prevent regressions.

Copilot uses AI. Check for mistakes.
Comment on lines 4 to 7
<f:entry field="atLeastDays" title="${%Ignore tags newer than}">
<f:number default=""/>
</f:entry>
<f:entry field="atMostDays" title="${%Ignore tags older than}">
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The UI field titles "Ignore tags newer than" and "Ignore tags older than" use double negatives that can be confusing. The field names are "atLeastDays" and "atMostDays" which refer to tag age requirements, but the labels use "ignore" which inverts the logic.

Consider more intuitive labels:

  • For atLeastDays: "Minimum tag age (days)" or "Only discover tags at least this many days old"
  • For atMostDays: "Maximum tag age (days)" or "Only discover tags at most this many days old"

Alternatively, use positive framing:

  • For atLeastDays: "Discover tags older than (days)"
  • For atMostDays: "Discover tags newer than (days)"

This would make the UI clearer and reduce the cognitive load on users trying to configure the right values.

Suggested change
<f:entry field="atLeastDays" title="${%Ignore tags newer than}">
<f:number default=""/>
</f:entry>
<f:entry field="atMostDays" title="${%Ignore tags older than}">
<f:entry field="atLeastDays" title="${%Discover tags older than (days)}">
<f:number default=""/>
</f:entry>
<f:entry field="atMostDays" title="${%Discover tags newer than (days)}">

Copilot uses AI. Check for mistakes.
Comment on lines 793 to 797
if (atLeastMillis >= 0L || atMostMillis >= 0L) {
if (atMostMillis >= 0L && atLeastMillis > atMostMillis) {
/* Invalid. It's impossible for any tag to satisfy this. */
continue;
}
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filtering logic checks if atMostMillis >= 0L && atLeastMillis > atMostMillis and continues to skip the tag if this invalid configuration is detected. However, this check is performed inside the loop for every tag, which is inefficient.

Consider moving this validation earlier, such as:

  1. In the getTagCommitTimeLimitMillisFromDays method or the withAtLeast/withAtMost methods in GitSCMSourceContext
  2. At the beginning of the discoverTags method before the loop

This would provide earlier feedback to users about configuration errors and avoid redundant checks for every tag.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is necessary.

Comment on lines 4 to 9
<f:entry field="atLeastDays" title="${%Ignore tags newer than}">
<f:number default=""/>
</f:entry>
<f:entry field="atMostDays" title="${%Ignore tags older than}">
<f:number default="7"/>
</f:entry>
Copy link

Copilot AI Jan 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The field order in the UI might be counterintuitive. The "atLeastDays" field (tags older than X days) appears before "atMostDays" field (tags newer than Y days). When users think about filtering by time range, they typically think in chronological order: "from X days ago to Y days ago" or in age order: "minimum age to maximum age".

Consider reordering the fields to be more intuitive:

  1. If using the current labels, swap them so "Ignore tags older than" (atMostDays) comes first, then "Ignore tags newer than" (atLeastDays)
  2. Or rename to "Minimum tag age" (atLeastDays) first, then "Maximum tag age" (atMostDays)

This would align better with user expectations when setting up a time range filter.

Suggested change
<f:entry field="atLeastDays" title="${%Ignore tags newer than}">
<f:number default=""/>
</f:entry>
<f:entry field="atMostDays" title="${%Ignore tags older than}">
<f:number default="7"/>
</f:entry>
<f:entry field="atMostDays" title="${%Ignore tags older than}">
<f:number default="7"/>
</f:entry>
<f:entry field="atLeastDays" title="${%Ignore tags newer than}">
<f:number default=""/>
</f:entry>

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I doubt this.

Tag time boundaries are primitive long which cannot be
NULL, so the `@CheckForNull` annotations on them are
useless and thus removed. Instead, default values `-1L`
are applied to initialize them.

Signed-off-by: dodo920306 <dodo920306@gmail.com>
If users input values that are not numbers
to TagDiscoveryTrait day limits, an uncaught
exception will be thrown for trying to parse
them to long, which is dangerous and should
be prevented.

Signed-off-by: dodo920306 <dodo920306@gmail.com>
Add lower bonds "0" to tag time boundaries
on UI.

Moreover, for backward compatibility, the
default value of `atMostDays` is removed.

Signed-off-by: dodo920306 <dodo920306@gmail.com>
Signed-off-by: dodo920306 <dodo920306@gmail.com>
@dodo920306
Copy link
Author

I found an immediate problem when I reviewed the names of the files that have been modified. The pull request includes no tests to show the problem and no tests to show that the problem is resolved. The git plugin is used in over 250,000 installations. I won't accept new functionality without very good automated test coverage.

OK. Thanks for such prompt reply. To be honest, I am not in a hurry to use the new feature added in this PR. Yes, I do believe this is a long-overdue feature rather than merely a bug fix; my intention is simply to contribute to the project. I did not mean to rush you in any way—I just did not want this PR to be forgotten. Sorry for the interruption.

Regarding the suggested changes automatically generated by Copilot, I have reviewed all of them. I may have missed or misunderstood some points, so if you believe any of the unaddressed suggestions are still necessary, please let me know.

As for the tests, as mentioned in the PR description, I am not very confident about adding new code to the existing test suite. However, since you have requested it, I will give it a try. It would be even better if someone could provide some guidance. Thanks again!

Use tag creation time instead of commit time when filtering tags by age.
For annotated tags, extract the tagger timestamp; for lightweight tags,
fall back to commit time. Both values are converted to milliseconds for
consistent comparison.

Signed-off-by: dodo920306 <dodo920306@gmail.com>
Signed-off-by: dodo920306 <dodo920306@gmail.com>
@github-actions github-actions bot added the tests Automated test addition or improvement label Jan 23, 2026
Signed-off-by: dodo920306 <dodo920306@gmail.com>
@dodo920306
Copy link
Author

OK. Thanks for such prompt reply. To be honest, I am not in a hurry to use the new feature added in this PR. Yes, I do believe this is a long-overdue feature rather than merely a bug fix; my intention is simply to contribute to the project. I did not mean to rush you in any way—I just did not want this PR to be forgotten. Sorry for the interruption.

Regarding the suggested changes automatically generated by Copilot, I have reviewed all of them. I may have missed or misunderstood some points, so if you believe any of the unaddressed suggestions are still necessary, please let me know.

As for the tests, as mentioned in the PR description, I am not very confident about adding new code to the existing test suite. However, since you have requested it, I will give it a try. It would be even better if someone could provide some guidance. Thanks again!

Added. Let's see the result.

Signed-off-by: dodo920306 <dodo920306@gmail.com>
@github-actions github-actions bot added the documentation Improvements or additions to documentation label Jan 26, 2026
This reverts commit 2dea2d7.

Signed-off-by: dodo920306 <dodo920306@gmail.com>
@dodo920306
Copy link
Author

dodo920306 commented Jan 27, 2026

I reverted 2dea2d7 because it seems like #3916 provides a better solution on this annotated tag creation timestamp determination problem. This PR focuses more on filtering tags during the discovery phase rather than deciding whether to build them as is done with build strategies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Incorrect or flawed behavior documentation Improvements or additions to documentation tests Automated test addition or improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants