-
-
Notifications
You must be signed in to change notification settings - Fork 9k
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-39300] View.getDisplayName() is ignored when rendering tabs #2603
Conversation
…ew tabs - Also fix the stapler documentation for the <l:tab> tag
* Returns the {@link ViewDescriptor} instances that can be instantiated for the {@link ViewGroup} in the current | ||
* {@link StaplerRequest}. <strong>NOTE: This method must be called from a {@link StaplerRequest}</strong> | ||
* @return the list of instantiable {@link ViewDescriptor} instances for the current {@link StaplerRequest} | ||
*/ |
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.
Note: this is the javadoc that applied to the method before my changes as the method would have blown up with a NPE if invoked outside of the newView.jelly
screen of a ViewGroup
as soon as AllView.isInstantiable()
was called
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.
Perhaps just check owner == null
and return all()
?
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.
Need to also check whether the StaplerRequest
is null.
- Also while we are at it, modernise ViewDescriptor instantiation to allow for descriptor visibility filtering
b3f71bb
to
e0a80dc
Compare
…criptorVisiblilityFilters too
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. |
@@ -3052,7 +3052,7 @@ public void run(Reactor session) throws Exception { | |||
// initialize views by inserting the default view if necessary | |||
// this is both for clean Jenkins and for backward compatibility. | |||
if(views.size()==0 || primaryView==null) { | |||
View v = new AllView(Messages.Hudson_ViewName()); | |||
View v = new AllView("all"); |
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.
This looks like it fixes JENKINS-38606.
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.
It is. But will it cause a fallout in upgrading Jenkins instances?
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 only affect new instances. Old instances can get the fix by recreating the All view (add new view, change default, delete all view, add back all view, change default, tidy up)
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.
We could be more aggressive and rename the AllView to all
but it is valid to give it whatever name you want... though perhaps we need some further tweaks
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.
This looks like a reasonable default for new All views. No need to edit existing ones. Would just cause confusion and broken links.
Whether the tab is active or not | ||
</st:attribute> | ||
<st:attribute name="title"> | ||
The title of the tab |
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.
Do we have an @since
equivalent for Jelly tags?
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 am restoring behaviour that was broken in this earlier commit (appears to be removed by omission as the old style documentation of parameters was retained)
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.
jenkinsci/stapler#84 created for you ;-)
…ly if safe to fix - Don't fix if there is already a view with the new default name - Don't fix if the AllView is not the primary view
@daniel-beck @oleg-nenashev so I have added a fix for JENKINS-38606... and we need to be able to invoke that fix from plugins (e.g. folders plugin) so I cannot make that |
Not actually safe, as there are code paths that add the view name to the URL even if it's the default view. I don't think we should fix JENKINS-38606 for existing installations. It modifies user data for a pretty weak reason. |
@daniel-beck OK, I have made this opt-in. I still think we should have the ability for an admin to force the fix applied everywhere as it could be quite difficult to fix all the |
Is this really not trivial to take care of in a script console script with maybe five lines? Do we really need a startup parameter (to be added in service configurations) for a one-time cleanup action here? |
@daniel-beck really? show me the five lines that find every ViewGroup (including the User properties for all users) and the folders etc and does the fix-up? For most admins it should not be an issue... but if it is an issue it could be very painful to fix by script or manually. Much better to provide a hook to fix the issue that is available to everyone IMHO. |
@daniel-beck can you respond please? Would like to get the change at least merged before we hit one of the last likely candidates for the next LTS |
I still have my doubt but I'd be happy to be outvoted. So far, nobody else has cared enough though @jenkinsci/code-reviewers Ping!). FWIW I would like to see other opinions on solving this using a new parameter. |
🐝 |
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.
Some minor inline comments, and tests are failing; 👍 on concept.
* @since FIXME | ||
*/ | ||
@Nonnull | ||
public static String applyJenkins38606Fixup(@Nonnull List<View> views, @Nonnull String primaryView) { |
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.
@Restricted(NoExternalUse.class)
(and remove @since
) unless this is something you really expect plugins to use.
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 expect plugins that implement ViewGroup will need to call into this method
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.
Is there a proposed PR calling it? From cloudbees-folder
? Then you should probably have a clearer name.
* fixing the view name by setting the system property {@code hudson.mode.AllView.JENKINS-38606} to {@code true}. | ||
* Use this method to round-trip the primary view name, e.g. | ||
* {@code primaryView = applyJenkins38606Fixup(views, primaryView)} | ||
* NOTE: we can only fix the localized name of an {@link AllView} if it is the primary view as otherwise urls |
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.
<p>
* {@code primaryView = applyJenkins38606Fixup(views, primaryView)} | ||
* NOTE: we can only fix the localized name of an {@link AllView} if it is the primary view as otherwise urls | ||
* would change, whereas the primary view is special and does not normally get accessed by the | ||
* {@code /view/_name_} url. |
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.
…though it can be, and those URLs will break. Right?
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.
Yes, and there are links in Jenkins to the default view's /view/whatever
URL.
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.
Yes, actually the new item link has switched from /view/All/newJob
to /view/all/newJob
(note the lowercase in the default view name).
// modern name, we are safe | ||
return primaryView; | ||
} | ||
if (SystemProperties.getBoolean(AllView.class.getName()+".JENKINS-38606", false)) { |
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.
getBoolean(String)
suffices.
// name conflict, we cannot rename the all view anyway | ||
return primaryView; | ||
} | ||
if (StringUtils.equals(v.getViewName(), primaryView)) { |
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.
AFAICT getViewName()
should be marked @Nonnull
.
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.
Done
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.
meaning you could use
if (v.getViewName().equals(primaryView)) {
* @return the validation result. | ||
* @since FIXME | ||
*/ | ||
@SuppressWarnings("unused") // expose utility check method to subclasses |
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.
Is there a particular subclass you had in mind? Not in this PR; some other linked one?
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.
Yes but it needs to use the Referer
header hack to resolve the View
so probably waiting on dedicated support in stapler for that
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 where is that subclass?
/** | ||
* Returns true if this {@link View} type is applicable in the specific {@link ViewGroup}. | ||
* | ||
* @return true to indicate applicable, in which case the view will be instantiable within the given owner. |
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.
Specify default implementation.
/** | ||
* Returns true if this {@link View} type is applicable to the given {@link ViewGroup} type. | ||
* | ||
* @return true to indicate applicable, in which case the view will be instantiable within the type of owner. |
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.
Specify default implementation.
@@ -32,7 +32,7 @@ THE SOFTWARE. | |||
<st:include page="sidepanel.jelly" it="${it.user}"/> | |||
|
|||
<l:main-panel> | |||
<j:invokeStatic var="views" className="hudson.model.View" method="allInstantiable" /> | |||
<j:invokeStatic var="views" className="hudson.model.View" method="allInstantiable"/> |
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.
Gratuitous diff hunk.
@@ -31,7 +31,7 @@ THE SOFTWARE. | |||
<st:include page="sidepanel.jelly" /> | |||
|
|||
<l:main-panel> | |||
<j:invokeStatic var="views" className="hudson.model.View" method="allInstantiable" /> | |||
<j:invokeStatic var="views" className="hudson.model.View" method="allInstantiable"/> |
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.
ditto
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.
@jglick I think i have addressed all your comments (in some way or other)
// name conflict, we cannot rename the all view anyway | ||
return primaryView; | ||
} | ||
if (StringUtils.equals(v.getViewName(), primaryView)) { |
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.
Done
* @return the validation result. | ||
* @since FIXME | ||
*/ | ||
@SuppressWarnings("unused") // expose utility check method to subclasses |
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.
Yes but it needs to use the Referer
header hack to resolve the View
so probably waiting on dedicated support in stapler for that
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.
Would like to discuss having better URL compatibility, and would like to see the downstream PR that various API methods here imply.
* @since FIXME | ||
*/ | ||
@Nonnull | ||
public static String applyJenkins38606Fixup(@Nonnull List<View> views, @Nonnull String primaryView) { |
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.
Is there a proposed PR calling it? From cloudbees-folder
? Then you should probably have a clearer name.
// name conflict, we cannot rename the all view anyway | ||
return primaryView; | ||
} | ||
if (StringUtils.equals(v.getViewName(), primaryView)) { |
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.
meaning you could use
if (v.getViewName().equals(primaryView)) {
* @return the validation result. | ||
* @since FIXME | ||
*/ | ||
@SuppressWarnings("unused") // expose utility check method to subclasses |
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 where is that subclass?
if (!lvc.shownByDefault()) continue; // skip this | ||
if (!lvc.shownByDefault()) { | ||
continue; // skip this | ||
} |
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.
gratuitous reformatting
// modern name, we are safe | ||
return primaryView; | ||
} | ||
if (SystemProperties.getBoolean(AllView.class.getName()+".JENKINS-38606")) { |
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.
Making this disabled by default makes it less than useful.
IIUC the concern is about compatibility for direct links to, say, http://jenkins/view/All/job/something/
. But that is easily solved: amend ViewGroupMixIn.getView
(called from Jenkins.getView(String)
, the Stapler URL binding) to fall back to searching by View.getDisplayName
if no match is found via getViewName
.
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.
Actually no, so the concern here is that you had been using say the DE locale when you created the folder... thus you would have http://jenkins/jobs/MyFolder/view/Alle/job/something
, the less likely concern is if you had started Jenkins in the IT locale (before changing it to something else) and you had http://jenkins/view/Tutto/job/something
Now what will happen with the fix-up is that it will spot these mistakes and say "Oh, those are localized names, that should really be all
"
Now when a user with the LT locale configured for their browser clicks on either of those two links:
http://jenkins/jobs/MyFolder/view/Alle/job/something
, well the primary AllView's displayName in LT isVisi
so falling back toView.getDisplayName()
will still not matchhttp://jenkins/view/Tutto/job/something
again has the same issue.
But thanks to pointing out ViewGroupMixIn.getView
what happens if we do not find a matching view name?
jenkins/core/src/main/java/hudson/model/ViewGroupMixIn.java
Lines 97 to 102 in 9172bca
if (name != null && !name.equals(primaryView())) { | |
// Fallback to subview of primary view if it is a ViewGroup | |
View pv = getPrimaryView(); | |
if (pv instanceof ViewGroup) | |
return ((ViewGroup)pv).getView(name); | |
} |
So what will happen is, the name is not null and the name is not all
and there was no other view with the name Visi
... so we will display the primary view.
So actually I think we can default this to ON and stop worrying
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.
Damn I read that wrong... but I think it does give us a solution instead
…r migration - This means we can default the migration to enabled
See jenkinsci/cloudbees-folder-plugin#79 for example usage of |
@rsandell @daniel-beck @jglick PR has been updated |
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.
Sounds good to the extent I understand it.
@@ -99,6 +101,15 @@ public View getView(String name) { | |||
View pv = getPrimaryView(); | |||
if (pv instanceof ViewGroup) | |||
return ((ViewGroup)pv).getView(name); | |||
if (pv instanceof AllView && AllView.DEFAULT_VIEW_NAME.equals(pv.name)) { |
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.
Sounds right but hard for me at least to follow how this will work in progress; recommend having some code coverage using @LocalData
to prove it works.
* @param c the container of the item. | ||
* @param d the descriptor of the view to be created. | ||
* @throws AccessDeniedException if the user doesn't have the permission. | ||
* @since 1.607 |
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.
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.
Ah but lots of test failures.
One test still fails:
|
if (pv instanceof AllView && AllView.DEFAULT_VIEW_NAME.equals(pv.name)) { | ||
// JENKINS-38606: primary view is the default AllView, is somebody using an old link to localized form? | ||
for (Locale l : Locale.getAvailableLocales()) { | ||
if (name.equals(Messages._Hudson_ViewName().toString(l))) { |
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 changing the translations will break this compatibility measure for that language? Is this so rare to be irrelevant?
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.
yes
I think we're good to merge now... i'll hold off until tomorrow and then merge just in case anyone has and issues with the test changes |
// bingo JENKINS-38606 detected | ||
LOGGER.log(Level.INFO, | ||
"JENKINS-38606 detected for AllView in {0}; renaming view from {1} to {2}", | ||
new Object[]{allView.owner.getUrl(), DEFAULT_VIEW_NAME}); |
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.
See JENKINS-39300
Also:
@jenkinsci/code-reviewers @reviewbybees