Skip to content

Commit

Permalink
Merge branch 'master' into command-palette
Browse files Browse the repository at this point in the history
  • Loading branch information
janfaracik authored Dec 2, 2024
2 parents 89da576 + e299979 commit 8c6024c
Show file tree
Hide file tree
Showing 51 changed files with 747 additions and 477 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/publish-release-artifact.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ jobs:
wget -q https://get.jenkins.io/${REPO}/${PROJECT_VERSION}/${FILE_NAME}
- name: Upload Release Asset
id: upload-war
uses: softprops/action-gh-release@e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8 # v2.0.9
uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down Expand Up @@ -108,7 +108,7 @@ jobs:
- name: Upload Release Asset
id: upload-deb
if: always()
uses: softprops/action-gh-release@e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8 # v2.0.9
uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down Expand Up @@ -144,7 +144,7 @@ jobs:
- name: Upload Release Asset
id: upload-rpm
if: always()
uses: softprops/action-gh-release@e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8 # v2.0.9
uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down Expand Up @@ -180,7 +180,7 @@ jobs:
- name: Upload Release Asset
id: upload-msi
if: always()
uses: softprops/action-gh-release@e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8 # v2.0.9
uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down Expand Up @@ -216,7 +216,7 @@ jobs:
- name: Upload Release Asset
id: upload-suse-rpm
if: always()
uses: softprops/action-gh-release@e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8 # v2.0.9
uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
Expand Down
2 changes: 1 addition & 1 deletion ath.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ set -o xtrace
cd "$(dirname "$0")"

# https://github.com/jenkinsci/acceptance-test-harness/releases
export ATH_VERSION=6072.vc7e4e6a_970b_c
export ATH_VERSION=6081.v29b_ce3c2771c

if [[ $# -eq 0 ]]; then
export JDK=17
Expand Down
14 changes: 7 additions & 7 deletions bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ THE SOFTWARE.

<properties>
<commons-fileupload2.version>2.0.0-M2</commons-fileupload2.version>
<stapler.version>1922.v3f3302a_7f16f</stapler.version>
<stapler.version>1928.v9115fe47607f</stapler.version>
<groovy.version>2.4.21</groovy.version>
</properties>

Expand All @@ -62,15 +62,15 @@ THE SOFTWARE.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-framework-bom</artifactId>
<version>6.1.14</version>
<version>6.2.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<!-- https://docs.spring.io/spring-security/reference/6.3/getting-spring-security.html#getting-maven-no-boot -->
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-bom</artifactId>
<version>6.3.4</version>
<version>6.4.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
Expand Down Expand Up @@ -109,7 +109,7 @@ THE SOFTWARE.
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.20</version>
<version>1.4.21</version>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
Expand All @@ -129,7 +129,7 @@ THE SOFTWARE.
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.17.0</version>
<version>2.18.0</version>
</dependency>
<dependency>
<groupId>commons-jelly</groupId>
Expand Down Expand Up @@ -295,7 +295,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.jvnet.hudson</groupId>
<artifactId>commons-jelly-tags-define</artifactId>
<version>1.1-jenkins-20240903</version>
<version>1.1-jenkins-20241115</version>
</dependency>
<dependency>
<groupId>org.jvnet.localizer</groupId>
Expand Down Expand Up @@ -335,7 +335,7 @@ THE SOFTWARE.
<dependency>
<groupId>org.kohsuke.stapler</groupId>
<artifactId>json-lib</artifactId>
<version>2.4-jenkins-7</version>
<version>2.4-jenkins-8</version>
</dependency>
<dependency>
<groupId>org.kohsuke.stapler</groupId>
Expand Down
27 changes: 3 additions & 24 deletions core/src/main/java/hudson/FilePath.java
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import jenkins.MasterToSlaveFileCallable;
import jenkins.SlaveToMasterFileCallable;
import jenkins.agents.ControllerToAgentFileCallable;
import jenkins.model.Jenkins;
import jenkins.security.MasterToSlaveCallable;
import jenkins.util.ContextResettingExecutorService;
Expand Down Expand Up @@ -520,30 +520,14 @@ public int archive(final ArchiverFactory factory, OutputStream os, final DirScan
return act(new Archive(factory, out, scanner, verificationRoot, openOptions));
}

private static class Archive extends MasterToSlaveFileCallable<Integer> {
private final ArchiverFactory factory;
private final OutputStream out;
private final DirScanner scanner;
private final String verificationRoot;
private OpenOption[] openOptions;

Archive(ArchiverFactory factory, OutputStream out, DirScanner scanner, String verificationRoot, OpenOption... openOptions) {
this.factory = factory;
this.out = out;
this.scanner = scanner;
this.verificationRoot = verificationRoot;
this.openOptions = openOptions;
}

private record Archive(ArchiverFactory factory, OutputStream out, DirScanner scanner, String verificationRoot, OpenOption... openOptions) implements ControllerToAgentFileCallable<Integer> {
@Override
public Integer invoke(File f, VirtualChannel channel) throws IOException {
try (Archiver a = factory.create(out)) {
scanner.scan(f, ignoringTmpDirs(ignoringSymlinks(a, verificationRoot, openOptions), verificationRoot, openOptions));
return a.countEntries();
}
}

private static final long serialVersionUID = 1L;
}

public int archive(final ArchiverFactory factory, OutputStream os, final FileFilter filter) throws IOException, InterruptedException {
Expand Down Expand Up @@ -1185,12 +1169,7 @@ public void copyFrom(org.apache.commons.fileupload.FileItem file) throws IOExcep
/**
* Code that gets executed on the machine where the {@link FilePath} is local.
* Used to act on {@link FilePath}.
* <strong>Warning:</strong> implementations must be serializable, so prefer a static nested class to an inner class.
*
* <p>
* Subtypes would likely want to extend from either {@link MasterToSlaveCallable}
* or {@link SlaveToMasterFileCallable}.
*
* A typical implementation would be a {@code record} implementing {@link ControllerToAgentFileCallable}.
* @see FilePath#act(FileCallable)
*/
public interface FileCallable<T> extends Serializable, RoleSensitive {
Expand Down
47 changes: 6 additions & 41 deletions core/src/main/java/hudson/Launcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import jenkins.agents.ControllerToAgentCallable;
import jenkins.model.Jenkins;
import jenkins.security.MasterToSlaveCallable;
import jenkins.tasks.filters.EnvVarsFilterLocalRule;
Expand Down Expand Up @@ -1114,8 +1115,7 @@ public Proc launch(ProcStarter ps) throws IOException {
final String workDir = psPwd == null ? null : psPwd.getRemote();

try {
RemoteLaunchCallable remote = new RemoteLaunchCallable(ps.commands, ps.masks, ps.envs, in, ps.reverseStdin, out, ps.reverseStdout, err, ps.reverseStderr, ps.quiet, workDir, listener, ps.stdoutListener);
remote.setEnvVarsFilterRuleWrapper(envVarsFilterRuleWrapper);
RemoteLaunchCallable remote = new RemoteLaunchCallable(ps.commands, ps.masks, ps.envs, in, ps.reverseStdin, out, ps.reverseStdout, err, ps.reverseStderr, ps.quiet, workDir, listener, ps.stdoutListener, envVarsFilterRuleWrapper);
// reset the rules to prevent build step without rules configuration to re-use those
envVarsFilterRuleWrapper = null;
return new ProcImpl(getChannel().call(remote));
Expand Down Expand Up @@ -1334,46 +1334,13 @@ public interface RemoteProcess {
IOTriplet getIOtriplet();
}

private static class RemoteLaunchCallable extends MasterToSlaveCallable<RemoteProcess, IOException> {
private final @NonNull List<String> cmd;
private final @CheckForNull boolean[] masks;
private final @CheckForNull String[] env;
private final @CheckForNull InputStream in;
private final @CheckForNull OutputStream out;
private final @CheckForNull OutputStream err;
private final @CheckForNull String workDir;
private final @NonNull TaskListener listener;
private final @CheckForNull TaskListener stdoutListener;
private final boolean reverseStdin, reverseStdout, reverseStderr;
private final boolean quiet;

private EnvVarsFilterRuleWrapper envVarsFilterRuleWrapper;

RemoteLaunchCallable(@NonNull List<String> cmd, @CheckForNull boolean[] masks, @CheckForNull String[] env,
private record RemoteLaunchCallable(@NonNull List<String> cmd, @CheckForNull boolean[] masks, @CheckForNull String[] env,
@CheckForNull InputStream in, boolean reverseStdin,
@CheckForNull OutputStream out, boolean reverseStdout,
@CheckForNull OutputStream err, boolean reverseStderr,
boolean quiet, @CheckForNull String workDir, @NonNull TaskListener listener, @CheckForNull TaskListener stdoutListener) {
this.cmd = new ArrayList<>(cmd);
this.masks = masks;
this.env = env;
this.in = in;
this.out = out;
this.err = err;
this.workDir = workDir;
this.listener = listener;
this.stdoutListener = stdoutListener;
this.reverseStdin = reverseStdin;
this.reverseStdout = reverseStdout;
this.reverseStderr = reverseStderr;
this.quiet = quiet;
}

@Restricted(NoExternalUse.class)
public void setEnvVarsFilterRuleWrapper(EnvVarsFilterRuleWrapper envVarsFilterRuleWrapper) {
this.envVarsFilterRuleWrapper = envVarsFilterRuleWrapper;
}

boolean quiet, @CheckForNull String workDir,
@NonNull TaskListener listener, @CheckForNull TaskListener stdoutListener,
@CheckForNull EnvVarsFilterRuleWrapper envVarsFilterRuleWrapper) implements ControllerToAgentCallable<RemoteProcess, IOException> {
@Override
public RemoteProcess call() throws IOException {
final Channel channel = getOpenChannelOrFail();
Expand Down Expand Up @@ -1433,8 +1400,6 @@ public IOTriplet getIOtriplet() {
}
});
}

private static final long serialVersionUID = 1L;
}

private static class RemoteChannelLaunchCallable extends MasterToSlaveCallable<OutputStream, IOException> {
Expand Down
20 changes: 17 additions & 3 deletions core/src/main/java/hudson/cli/CLIAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,26 @@ public boolean isWebSocketSupported() {
return WebSockets.isSupported();
}

/**
* Unlike {@link HttpResponses#errorWithoutStack} this sends the message in a header rather than the body.
* (Currently the WebSocket CLI is unable to process the body in an error message.)
*/
private static HttpResponse statusWithExplanation(int code, String errorMessage) {
return new HttpResponse() {
@Override
public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) {
rsp.setStatus(code);
rsp.setHeader("X-CLI-Error", errorMessage);
}
};
}

/**
* WebSocket endpoint.
*/
public HttpResponse doWs(StaplerRequest2 req) {
if (!WebSockets.isSupported()) {
return HttpResponses.notFound();
return statusWithExplanation(HttpServletResponse.SC_NOT_FOUND, "WebSocket is not supported in this servlet container (try the built-in Jetty instead)");
}
if (ALLOW_WEBSOCKET == null) {
final String actualOrigin = req.getHeader("Origin");
Expand All @@ -141,10 +155,10 @@ public HttpResponse doWs(StaplerRequest2 req) {

if (actualOrigin == null || !actualOrigin.equals(expectedOrigin)) {
LOGGER.log(Level.FINE, () -> "Rejecting origin: " + actualOrigin + "; expected was from request: " + expectedOrigin);
return HttpResponses.forbidden();
return statusWithExplanation(HttpServletResponse.SC_FORBIDDEN, "Unexpected request origin (check your reverse proxy settings)");
}
} else if (!ALLOW_WEBSOCKET) {
return HttpResponses.forbidden();
return statusWithExplanation(HttpServletResponse.SC_FORBIDDEN, "WebSocket support for CLI disabled for this controller");
}
Authentication authentication = Jenkins.getAuthentication2();
return WebSockets.upgrade(new WebSocketSession() {
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/hudson/model/ModifiableItemGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import org.kohsuke.stapler.StaplerRequest2;
import org.kohsuke.stapler.StaplerResponse;
import org.kohsuke.stapler.StaplerResponse2;
import org.kohsuke.stapler.interceptor.RequirePOST;

/**
* {@link ItemGroup} that is a general purpose container, which allows users and the rest of the program
Expand All @@ -50,7 +51,7 @@ public interface ModifiableItemGroup<T extends Item> extends ItemGroup<T> {
* The request format follows that of {@code &lt;n:form xmlns:n="/lib/form">}.
*
*/
@StaplerNotDispatchable
@RequirePOST
default T doCreateItem(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException {
if (ReflectionUtils.isOverridden(
ModifiableItemGroup.class,
Expand Down
22 changes: 6 additions & 16 deletions core/src/main/java/jenkins/MasterToSlaveFileCallable.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,16 @@
package jenkins;

import hudson.FilePath.FileCallable;
import hudson.remoting.VirtualChannel;
import java.io.File;
import jenkins.security.Roles;
import jenkins.slaves.RemotingVersionInfo;
import org.jenkinsci.remoting.RoleChecker;
import jenkins.agents.ControllerToAgentFileCallable;

/**
* {@link FileCallable}s that are meant to be only used on the master.
*
* Note that the logic within {@link #invoke(File, VirtualChannel)} should use API of a minimum supported Remoting version.
* See {@link RemotingVersionInfo#getMinimumSupportedVersion()}.
*
* {@link FileCallable}s that could run on an agent.
* For new code, implement {@link ControllerToAgentFileCallable}
* which has the advantage that it can be used on {@code record}s.
* @since 1.587 / 1.580.1
* @param <T> the return type; note that this must either be defined in your plugin or included in the stock JEP-200 whitelist
* @param <T> the return type
*/
public abstract class MasterToSlaveFileCallable<T> implements FileCallable<T> {
@Override
public void checkRoles(RoleChecker checker) throws SecurityException {
checker.check(this, Roles.SLAVE);
}
public abstract class MasterToSlaveFileCallable<T> implements ControllerToAgentFileCallable<T> {

private static final long serialVersionUID = 1L;
}
48 changes: 48 additions & 0 deletions core/src/main/java/jenkins/agents/ControllerToAgentCallable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* The MIT License
*
* Copyright 2024 CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package jenkins.agents;

import hudson.remoting.Callable;
import jenkins.security.Roles;
import jenkins.slaves.RemotingVersionInfo;
import org.jenkinsci.remoting.RoleChecker;

/**
* {@link Callable} meant to be serialized then run on an agent.
* A typical implementation will be a {@link Record}
* since instance state merely transfers a set of parameters to an agent JVM.
* <p>Note that the logic within {@link #call} may not use Remoting APIs
* newer than {@link RemotingVersionInfo#getMinimumSupportedVersion}.
* (Core and plugin APIs will be identical to those run inside the controller.)
* @param <V> the return type; note that this must either be defined in your plugin or included in the stock JEP-200 whitelist
* @since 2.485
*/
public interface ControllerToAgentCallable<V, T extends Throwable> extends Callable<V, T> {

@Override
default void checkRoles(RoleChecker checker) throws SecurityException {
checker.check(this, Roles.SLAVE);
}
}
Loading

0 comments on commit 8c6024c

Please sign in to comment.