Skip to content

Commit 893c4b5

Browse files
janfaraciktimja
andauthored
Add support for tabs for the experimental run page (#11141)
Co-authored-by: Tim Jacomb <21194782+timja@users.noreply.github.com> Co-authored-by: Tim Jacomb <timjacomb1@gmail.com>
1 parent e69069b commit 893c4b5

File tree

32 files changed

+1060
-127
lines changed

32 files changed

+1060
-127
lines changed

core/src/main/java/hudson/model/Run.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
import jenkins.model.JenkinsLocationConfiguration;
121121
import jenkins.model.RunAction2;
122122
import jenkins.model.StandardArtifactManager;
123+
import jenkins.model.Tab;
123124
import jenkins.model.details.CauseDetail;
124125
import jenkins.model.details.Detail;
125126
import jenkins.model.details.DetailFactory;
@@ -2710,4 +2711,12 @@ public Class<Run> type() {
27102711
return List.of(new CauseDetail(target), new TimestampDetail(target), new DurationDetail(target));
27112712
}
27122713
}
2714+
2715+
/**
2716+
* Retrieves the tabs for a given run
2717+
*/
2718+
@Restricted(NoExternalUse.class)
2719+
public List<Tab> getRunTabs() {
2720+
return getActions(Tab.class);
2721+
}
27132722
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025, Jan Faracik
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
package jenkins.model;
26+
27+
import edu.umd.cs.findbugs.annotations.CheckForNull;
28+
import jenkins.management.Badge;
29+
30+
/**
31+
* Represents an entity that can display a {@link Badge}.
32+
* <p>
33+
* Implementations of this interface may provide a badge
34+
* to be shown on an associated action or UI element.
35+
* If no badge is provided, {@code null} may be returned.
36+
* </p>
37+
*
38+
* @since TODO
39+
*/
40+
public interface Badgeable {
41+
42+
/**
43+
* A {@link Badge} shown on the action.
44+
*
45+
* @return badge or {@code null} if no badge should be shown.
46+
* @since TODO
47+
*/
48+
default @CheckForNull Badge getBadge() {
49+
return null;
50+
}
51+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025, Jan Faracik
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
package jenkins.model;
26+
27+
import hudson.model.Action;
28+
import hudson.model.Actionable;
29+
30+
/**
31+
* Represents a tab element shown on {@link Actionable} views.
32+
* <p>
33+
* A {@code Tab} is an {@link Action} that can be attached to an {@link Actionable} object
34+
* (such as a job or build) and displayed as a separate tab in the UI.
35+
* </p>
36+
*
37+
* <p>
38+
* Tabs may also implement {@link Badgeable} to display a visual badge associated
39+
* with the tab’s action
40+
* </p>
41+
*
42+
* @since TODO
43+
*/
44+
public abstract class Tab implements Action, Badgeable {
45+
46+
protected Actionable object;
47+
48+
public Tab(Actionable object) {
49+
this.object = object;
50+
}
51+
52+
public Actionable getObject() {
53+
return object;
54+
}
55+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025, Jan Faracik
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
package jenkins.run;
26+
27+
import hudson.model.Actionable;
28+
import jenkins.model.Tab;
29+
30+
public class ChangesTab extends Tab {
31+
32+
public ChangesTab(Actionable object) {
33+
super(object);
34+
}
35+
36+
@Override
37+
public String getIconFileName() {
38+
return "symbol-changes";
39+
}
40+
41+
@Override
42+
public String getDisplayName() {
43+
return "Changes";
44+
}
45+
46+
@Override
47+
public String getUrlName() {
48+
return "changes";
49+
}
50+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025, Jan Faracik
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
package jenkins.run;
26+
27+
import edu.umd.cs.findbugs.annotations.NonNull;
28+
import hudson.Extension;
29+
import hudson.model.Run;
30+
import java.util.Collection;
31+
import java.util.Collections;
32+
import jenkins.model.Tab;
33+
import jenkins.model.TransientActionFactory;
34+
import jenkins.model.experimentalflags.NewBuildPageUserExperimentalFlag;
35+
import jenkins.scm.RunWithSCM;
36+
37+
@Extension(ordinal = Integer.MAX_VALUE - 2)
38+
public class ChangesTabFactory extends TransientActionFactory<Run> {
39+
40+
@Override
41+
public Class<Run> type() {
42+
return Run.class;
43+
}
44+
45+
@NonNull
46+
@Override
47+
public Collection<? extends Tab> createFor(@NonNull Run target) {
48+
boolean isExperimentalUiEnabled = new NewBuildPageUserExperimentalFlag().getFlagValue();
49+
50+
if (!isExperimentalUiEnabled) {
51+
return Collections.emptySet();
52+
}
53+
54+
if (target instanceof RunWithSCM<?, ?> targetWithSCM) {
55+
var hasChangeSet = !targetWithSCM.getChangeSets().isEmpty();
56+
if (hasChangeSet) {
57+
return Collections.singleton(new ChangesTab(target));
58+
}
59+
}
60+
61+
return Collections.emptySet();
62+
}
63+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025, Jan Faracik
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
package jenkins.run;
26+
27+
import hudson.model.Actionable;
28+
import jenkins.model.Tab;
29+
30+
public class ConsoleTab extends Tab {
31+
32+
public ConsoleTab(Actionable object) {
33+
super(object);
34+
}
35+
36+
@Override
37+
public String getIconFileName() {
38+
return "symbol-terminal";
39+
}
40+
41+
@Override
42+
public String getDisplayName() {
43+
return "Console";
44+
}
45+
46+
@Override
47+
public String getUrlName() {
48+
return "console";
49+
}
50+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* The MIT License
3+
*
4+
* Copyright (c) 2025, Jan Faracik
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
package jenkins.run;
26+
27+
import edu.umd.cs.findbugs.annotations.NonNull;
28+
import hudson.Extension;
29+
import hudson.Functions;
30+
import hudson.model.Run;
31+
import java.util.Collection;
32+
import java.util.Collections;
33+
import jenkins.console.DefaultConsoleUrlProvider;
34+
import jenkins.model.Tab;
35+
import jenkins.model.TransientActionFactory;
36+
import jenkins.model.experimentalflags.NewBuildPageUserExperimentalFlag;
37+
38+
@Extension(ordinal = Integer.MAX_VALUE - 1)
39+
public class ConsoleTabFactory extends TransientActionFactory<Run> {
40+
41+
@Override
42+
public Class<Run> type() {
43+
return Run.class;
44+
}
45+
46+
@NonNull
47+
@Override
48+
public Collection<? extends Tab> createFor(@NonNull Run target) {
49+
var consoleProvider = Functions.getConsoleProviderFor(target);
50+
boolean isExperimentalUiEnabled = new NewBuildPageUserExperimentalFlag().getFlagValue();
51+
52+
if (!consoleProvider.getClass().equals(DefaultConsoleUrlProvider.class) || !isExperimentalUiEnabled) {
53+
return Collections.emptySet();
54+
}
55+
56+
return Collections.singleton(new ConsoleTab(target));
57+
}
58+
}

0 commit comments

Comments
 (0)