-
-
Notifications
You must be signed in to change notification settings - Fork 8.8k
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
[JENKINS-24141] Pull ChangeLogSet-related logic out of AbstractBuild #2730
Conversation
Need to add tests, but first need to determine if this actually makes sense as I've implemented it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking basically right so far.
Do you plan to also port DependencyGraph
stuff (upstream/downstream, used tangentially by SCM-related code)?
@@ -637,7 +639,7 @@ public Calendar getLastChange() { | |||
} | |||
|
|||
@Exported | |||
public AbstractProject getProject() { | |||
public Job<?,?> getProject() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Binary-incompatible, I am afraid, so you will need to do something like
@Deprecated
public AbstractProject getProject() {
return project instanceof AbstractProject ? (AbstractProject) project : null;
}
@Exported(name="project")
public Job<?,?> getProject() {
return project;
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okiedokie.
modified.add(user); | ||
if (r instanceof RunWithSCM) { | ||
RunWithSCM runWithSCM = (RunWithSCM) r; | ||
for (ChangeLogSet<? extends ChangeLogSet.Entry> c : runWithSCM.getChangeSets()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tip: to minimize diff hunk size for reviewers (and thus reduce chance of merge conflicts, git blame
breakage, etc. etc.), you can keep the original indentation without violating code style:
for (Run<?,?> r : runs) {
if (canceled()) {
return;
}
if (!(r instanceof RunWithSCM)) {
continue;
}
for (ChangeLogSet.Entry entry : ((RunWithSCM) r).getChangeSet()) {
// …rest untouched
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will note for future reference.
} | ||
} | ||
} | ||
// TODO consider also adding the user of the UserCause when applicable | ||
buildCount++; | ||
// TODO this defeats lazy-loading. Should rather do a breadth-first search, as in hudson.plugins.view.dashboard.builds.LatestBuilds | ||
// (though currently there is no quick implementation of RunMap.size() ~ idOnDisk.size(), which would be needed for proper progress) | ||
progress((itemCount + 1.0 * buildCount / builds.size()) / (items.size() + 1)); | ||
progress((itemCount + 1.0 * buildCount / runs.size()) / (items.size() + 1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid gratuitous renames to minimize diff hunks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mea culpa. =)
import java.util.Set; | ||
|
||
/** | ||
* @since 2.xxx |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use FIXME
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wasn't sure what to do there - perfect.
|
||
@Nonnull List<ChangeLogSet<? extends ChangeLogSet.Entry>> getChangeSets(); | ||
|
||
@Nonnull Set<User> getCulprits(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this would be better done as a mixin so that we do not need to copy implementations of getCulprits
and hasParticipant
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was wondering about that - I decided to not go that far initially but now I will do so!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But fwiw, getCulprits
actually will differ, since AbstractBuild.getCulprits()
relies on AbstractBuild.getDependencyChanges(...)
, which isn't functionality that I think makes sense in WorkflowRun
. Especially since the Fingerprinter
stuff is allllll about AbstractProject
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aaaah, that's what you meant by DependencyGraph
work. I will see how it goes, then.
|
||
@Nonnull Set<User> getCulprits(); | ||
|
||
@Nonnull Calendar getTimestamp(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? This is already defined in Run
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I could invoke runWithSCM.getTimestamp()
without a bunch of awkward casting - but the mixin approach should help there.
And of course you will want a matching PR to |
@jglick Hadn't looked at the |
Also bumping to a distinct SNAPSHOT version for dependency builds.
@@ -114,7 +117,9 @@ | |||
import java.util.logging.Logger; | |||
|
|||
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; | |||
import static jenkins.model.Jenkins.*; | |||
import static jenkins.model.Jenkins.checkGoodName; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For whatever reason, the wildcard import was barfing for me. In general, I had weirdness with pre-existing imports/scoping here for reasons I'm not clear on.
|
Downstream of jenkinsci/jenkins#2730 More work to go, but this is the initial work.
Conflicts: cli/pom.xml core/pom.xml pom.xml test/pom.xml war/pom.xml
Conflicts: cli/pom.xml core/pom.xml pom.xml test/pom.xml war/pom.xml
Added initial |
This pull request originates from a CloudBees employee. At CloudBees, we require that all pull requests be reviewed by other CloudBees employees before we seek to have the change accepted. If you want to learn more about our process please see this explanation. |
Yeah, reverting the |
This reverts commit 7fe3a4a.
public interface RunWithSCM<JobT extends Job<JobT, RunT> & Queue.Task, | ||
RunT extends Run<JobT, RunT> & RunWithSCM<JobT,RunT> & Queue.Executable> { | ||
@Nonnull | ||
List<ChangeLogSet<? extends ChangeLogSet.Entry>> getChangeSets(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hoping we could take advantage of -source 8
to have all the methods here other than getRunWithSCMMixIn
get default implementations, and started prototyping doing this with other mixin classes. Unfortunately it does not seem to work in general (for example for LazyLoadingJob._getRuns()
), because apparently a concrete class cannot pick up a default method when the method is defined in an abstract superclass. Thus
public class Demo {
public static void main(String[] args) {
System.out.println(new C().answer());
}
public static abstract class AC {
public abstract int x();
}
public interface I {
default int answer() {return 42;}
}
public static class C extends AC implements I {}
}
fails to compile:
Demo.java:11: error: C is not abstract and does not override abstract method x() in AC
public static class C extends AC implements I {}
1 error
However I think it could work here, since the methods you are expecting these Run
s to define are not declared in Run
. I am still looking for possible uses in ParameterizedJobMixIn
& LazyBuildMixIn
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good times, good times. Lemme know what I should do when you know what I should do. =)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well the principle seems to work in #2864, though it is messier there since
- this was existing code designed to work in
-source 7
(or maybe it was even-source 6
at the time, I cannot recall) - a lot of the methods were defined in other types
Here I think it should be cleaner. Delete RunWithSCM
, asRun
, and getRunWithSCMMixIn
, and make RunWithSCMMixIn
into an interface
, with default
on as many methods as possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I'll give it a shot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm...we're ok with changing RunWithSCMMixIn
from an abstract class
to an interface
? In #2864, you kept the abstract class
/interface
split between ParameterizedJobMixIn
and ParameterizedJob
, which seems saner to me. I'm worrying about breaking compatibility for something out there that we may not know about that implements RunWithSCM
currently...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In #2864 I had to maintain that split since it already existed in public APIs. This is fresh code so we can design it more simply.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha. I'd forgotten that RunWithSCM
was introduced here! d'oh. =)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, so here's what I ended up doing:
- Renamed
RunWithSCMMixIn
toRunWithSCM
- if it should actually beRunWithSCMMixin
, lemme know and I can fix that. - Made the non-abstract methods from the old
RunWithSCMMixin
abstract class
intodefault
methods. - Got rid of
getRunWithSCMMixIn
fromAbstractBuild
. - I did keep
RunWithSCM.asRun()
, however - thegetCulprits()
andhasParticipants(User)
methods both needed to callRun
methods. There may very well be a way to do this right withoutasRun()
, and if so, I wanna know what it is. =)
Is this upstream of something? |
@daniel-beck see PR description. |
@daniel-beck @jglick In fairness, I added all those links after his comment. =) |
@jglick Shall I merge or do you want to? |
@abayer I would give @jenkinsci/code-reviewers some time to provide the feedback. 🐝 from me after the quick check. Will merge on Saturday evening if there is no negative feedback. |
@oleg-nenashev Alrightie! |
public Set<User> calculateCulprits() { | ||
Set<User> c = RunWithSCM.super.calculateCulprits(); | ||
|
||
AbstractBuild<P,R> p = getPreviousCompletedBuild(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this implements caching, where does it consider parallel builds that complete out of order?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shrug? It's the same logic as had previously existed for populating AbstractBuild.culprits
, just organized differently.
|
||
|
||
/** | ||
* RSS feed for changes in this project. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should note that @since TODO
it was pulled up into job.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On hold till I move comments from downstream PR by @jglick
FYI, I'm doing an ATH run with this to see if anything jumps out. |
Nothing did jump out from the ATH. @oleg-nenashev are we good to go? |
@abayer nope, I have not moved the comments yet though I see several ones are unanswered in the downstream PR |
@oleg-nenashev Ok, I thought I'd covered all the pertinent ones for this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🐝 I confirm that the important comment from the downstream PR has been addressed here.
@reviewbybees done
@abayer BTW I think some |
Starting with jenkinsci/jenkins#2730, `AbstractBuild.getChangeSet()` is `@NonNull`, so we can remove the `if` to protect against potential NPEs. Errors were: ``` [INFO] --- spotbugs-maven-plugin:3.1.11:check (default-cli) @ email-ext --- [INFO] BugInstance size is 4 [INFO] Error size is 0 [INFO] Total bugs: 4 [ERROR] Un appel de méthode dans hudson.plugins.emailext.EmailRecipientUtils.convertRecipientString(String, EnvVars, int, TaskListener) passe null à un paramètre déclaré @nonnull de hudson.model.User.get(String, boolean, Map) [hudson.plugins.emailext.EmailRecipientUtils] At EmailRecipientUtils.java:[line 82] NP_NONNULL_PARAM_VIOLATION [ERROR] Un appel de méthode dans hudson.plugins.emailext.plugins.recipients.RecipientProviderUtilities.getByLegacyUserCause(Run) passe null à un paramètre déclaré @nonnull de hudson.model.User.get(String, boolean, Map) [hudson.plugins.emailext.plugins.recipients.RecipientProviderUtilities] At RecipientProviderUtilities.java:[line 152] NP_NONNULL_PARAM_VIOLATION [ERROR] Un appel de méthode dans hudson.plugins.emailext.plugins.recipients.RecipientProviderUtilities.getByUserIdCause(Run) passe null à un paramètre déclaré @nonnull de hudson.model.User.get(String, boolean, Map) [hudson.plugins.emailext.plugins.recipients.RecipientProviderUtilities] At RecipientProviderUtilities.java:[line 133] NP_NONNULL_PARAM_VIOLATION [ERROR] Test de nullité redondant sur une valeur non nulle dans hudson.plugins.emailext.plugins.recipients.RecipientProviderUtilities.getChangeSetAuthors(Collection, RecipientProviderUtilities$IDebug) [hudson.plugins.emailext.plugins.recipients.RecipientProviderUtilities] Redundant null check at RecipientProviderUtilities.java:[line 75] RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE [INFO] ```
Starting with jenkinsci/jenkins#2730, `AbstractBuild.getChangeSet()` is `@NonNull`, so we can remove the `if` to protect against potential NPEs. Errors were: ``` [INFO] --- spotbugs-maven-plugin:3.1.11:check (default-cli) @ email-ext --- [INFO] BugInstance size is 4 [INFO] Error size is 0 [INFO] Total bugs: 4 [ERROR] Un appel de méthode dans hudson.plugins.emailext.EmailRecipientUtils.convertRecipientString(String, EnvVars, int, TaskListener) passe null à un paramètre déclaré @nonnull de hudson.model.User.get(String, boolean, Map) [hudson.plugins.emailext.EmailRecipientUtils] At EmailRecipientUtils.java:[line 82] NP_NONNULL_PARAM_VIOLATION [ERROR] Un appel de méthode dans hudson.plugins.emailext.plugins.recipients.RecipientProviderUtilities.getByLegacyUserCause(Run) passe null à un paramètre déclaré @nonnull de hudson.model.User.get(String, boolean, Map) [hudson.plugins.emailext.plugins.recipients.RecipientProviderUtilities] At RecipientProviderUtilities.java:[line 152] NP_NONNULL_PARAM_VIOLATION [ERROR] Un appel de méthode dans hudson.plugins.emailext.plugins.recipients.RecipientProviderUtilities.getByUserIdCause(Run) passe null à un paramètre déclaré @nonnull de hudson.model.User.get(String, boolean, Map) [hudson.plugins.emailext.plugins.recipients.RecipientProviderUtilities] At RecipientProviderUtilities.java:[line 133] NP_NONNULL_PARAM_VIOLATION [ERROR] Test de nullité redondant sur une valeur non nulle dans hudson.plugins.emailext.plugins.recipients.RecipientProviderUtilities.getChangeSetAuthors(Collection, RecipientProviderUtilities$IDebug) [hudson.plugins.emailext.plugins.recipients.RecipientProviderUtilities] Redundant null check at RecipientProviderUtilities.java:[line 75] RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE [INFO] ```
JENKINS-24141
SCM.buildEnvVars
needs to be changed toRun
.Port(spoiler - we don't want to do this, at least not here - this is a major change I don't think should be in this scope)DependencyGraph
as well? (questionable whether we want to do this - feedback desired)Changelog
Upstream of:
cc @reviewbybees esp @jglick