mirror of
https://github.com/jenkinsci/jenkins.git
synced 2026-10-26 19:15:09 +00:00
Switch to forking jvm for development mode with hpi:run (#27239)
This commit is contained in:
1 parent
2e228ff40b
commit
62d8d525c7
7 files changed
+121
-118
No files matched your search
@@ -4,15 +4,6 @@
|
||||
"prHourlyLimit": 0,
|
||||
"prConcurrentLimit": 0,
|
||||
"packageRules": [
|
||||
{
|
||||
"description": "Should be upgraded in lockstep in order to keep their corresponding Jetty versions aligned",
|
||||
"matchManagers": ["maven"],
|
||||
"groupName": "Winstone and Jetty",
|
||||
"matchPackageNames": [
|
||||
"org.eclipse.jetty.ee9:jetty-ee9-maven-plugin",
|
||||
"org.jenkins-ci:winstone"
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "Provided by Jetty and should be aligned with the version provided by the version of Jetty we deliver. See: https://github.com/jenkinsci/jenkins/pull/5211",
|
||||
"matchManagers": ["maven"],
|
||||
|
||||
+19
-4
@@ -59,10 +59,22 @@ and then attach IDE Debugger to it.
|
||||
To launch a development instance, after [building the WAR file](#building-the-war-file), run:
|
||||
|
||||
```sh
|
||||
MAVEN_OPTS='--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED' mvn -pl war jetty:run
|
||||
mvn -pl war hpi:run
|
||||
```
|
||||
|
||||
(Beware that `maven-plugin` builds will not work in this mode, due to class loading conflicts.)
|
||||
This forks a JVM that serves `war/target/jenkins` under Winstone, the same way `jenkins.war` is
|
||||
served in production. Jenkins is available on <http://localhost:8080/jenkins/> and uses
|
||||
`war/work` as its `JENKINS_HOME`; pass `-Dport=`, `-Dhost=` or `-DjenkinsHome=` to change that.
|
||||
|
||||
Edits to `war/src/main/webapp`, and to Jelly views and their sibling `.properties` files under
|
||||
`core/src/main/resources`, are picked up on the next page load. Edits to a `Messages.properties`
|
||||
take effect when you restart the development instance — no repackaging needed, but the bundle is
|
||||
cached for the life of the JVM. Changes to Java code still need a rebuild.
|
||||
|
||||
Because Jenkins now runs in its own JVM, starting Maven under a debugger no longer attaches to
|
||||
Jenkins. Pass `-Dmaven.hpi.debug=true` to have the forked JVM suspend and wait for a debugger, or
|
||||
give the option a JVM debug string of your own; see
|
||||
[maven-hpi-plugin#862](https://github.com/jenkinsci/maven-hpi-plugin/pull/862).
|
||||
|
||||
### Running the Yarn frontend build
|
||||
|
||||
@@ -85,10 +97,10 @@ yarn
|
||||
|
||||
To work on the `war` module frontend assets, two processes are needed at the same time:
|
||||
|
||||
On one terminal, start a development server that will not process frontend assets:
|
||||
On one terminal, start a development server:
|
||||
|
||||
```sh
|
||||
MAVEN_OPTS='--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.io=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED' mvn -pl war jetty:run -Dskip.frontend
|
||||
mvn -pl war hpi:run
|
||||
```
|
||||
|
||||
Open another terminal and start a [webpack](https://webpack.js.org/) dev server, after [optionally adding Node and Yarn to your path](#running-the-yarn-frontend-build):
|
||||
@@ -97,6 +109,9 @@ Open another terminal and start a [webpack](https://webpack.js.org/) dev server,
|
||||
yarn start
|
||||
```
|
||||
|
||||
`yarn start` writes to `war/src/main/webapp/jsbundles`, which the development server serves
|
||||
directly, so a browser reload is enough to pick up the rebuilt bundles.
|
||||
|
||||
### Linting
|
||||
|
||||
For linting we use a number of tools:
|
||||
|
||||
@@ -28,7 +28,7 @@ THE SOFTWARE.
|
||||
<parent>
|
||||
<groupId>org.jenkins-ci</groupId>
|
||||
<artifactId>jenkins</artifactId>
|
||||
<version>2.1391.vb_93f2a_83691d</version>
|
||||
<version>2.1395.v8534005506ec</version>
|
||||
<relativePath />
|
||||
</parent>
|
||||
|
||||
@@ -103,7 +103,6 @@ THE SOFTWARE.
|
||||
<!-- Skips node installation, "yarn install" and "yarn build". Only safe when
|
||||
war/src/main/webapp/jsbundles is already populated from an earlier build. -->
|
||||
<skip.frontend>false</skip.frontend>
|
||||
<!-- Make sure to keep the jetty-ee9-maven-plugin version in war/pom.xml in sync with the Jetty release in Winstone: -->
|
||||
<winstone.version>8.1047.v331d3186f463</winstone.version>
|
||||
<node.version>24.19.0</node.version>
|
||||
</properties>
|
||||
|
||||
+4
-3
@@ -30,16 +30,17 @@ Ensures that NetBeans knows which goals to run when Run Project is selected.
|
||||
<action>
|
||||
<actionName>run</actionName>
|
||||
<goals>
|
||||
<goal>jetty:run</goal>
|
||||
<goal>hpi:run</goal>
|
||||
</goals>
|
||||
</action>
|
||||
<action>
|
||||
<actionName>debug</actionName>
|
||||
<goals>
|
||||
<goal>jetty:run</goal>
|
||||
<goal>hpi:run</goal>
|
||||
</goals>
|
||||
<properties>
|
||||
<jpda.listen>maven</jpda.listen>
|
||||
<!-- Jenkins runs in a forked JVM, so suspend it and attach to the port it prints. -->
|
||||
<maven.hpi.debug>true</maven.hpi.debug>
|
||||
</properties>
|
||||
</action>
|
||||
</actions>
|
||||
+64
-62
@@ -262,28 +262,6 @@ THE SOFTWARE.
|
||||
<overWriteSnapshots>true</overWriteSnapshots>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<!-- see jetty-ee9-maven-plugin config and WebAppMain -->
|
||||
<id>support-log-formatter</id>
|
||||
<goals>
|
||||
<goal>copy</goal>
|
||||
</goals>
|
||||
<phase>generate-resources</phase>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>io.jenkins.lib</groupId>
|
||||
<artifactId>support-log-formatter</artifactId>
|
||||
<version>123.v72513b_f61500</version>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<outputDirectory>${project.build.directory}</outputDirectory>
|
||||
<stripVersion>true</stripVersion>
|
||||
<overWriteIfNewer>true</overWriteIfNewer>
|
||||
<overWriteReleases>false</overWriteReleases>
|
||||
<overWriteSnapshots>true</overWriteSnapshots>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
@@ -329,35 +307,75 @@ THE SOFTWARE.
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty.ee9</groupId>
|
||||
<artifactId>jetty-ee9-maven-plugin</artifactId>
|
||||
<!--
|
||||
Make sure to keep the Winstone version in pom.xml in sync with this version. If the current Winstone release
|
||||
contains a version of Jetty that is older than this, trigger Dependabot in jenkinsci/winstone and release the
|
||||
result before proceeding with the update here.
|
||||
Development instance: mvn -pl war hpi:run. Serves the exploded WAR under Winstone, the same way
|
||||
jenkins.war is served in production, so build the WAR first.
|
||||
-->
|
||||
<version>12.1.12</version>
|
||||
<groupId>org.jenkins-ci.tools</groupId>
|
||||
<artifactId>maven-hpi-plugin</artifactId>
|
||||
<!-- version specified in grandparent pom -->
|
||||
<configuration>
|
||||
<webAppFile>${project.build.directory}/${project.build.finalName}.war</webAppFile>
|
||||
<explodedWar>${project.build.directory}/${project.build.finalName}</explodedWar>
|
||||
<webApp>
|
||||
<contextPath>${contextPath}</contextPath>
|
||||
</webApp>
|
||||
<!--
|
||||
Reload webapp when you hit ENTER. (See JETTY-282 for more)
|
||||
Serve these from the source tree rather than from the copies in the exploded WAR, so that
|
||||
editing them (or running "yarn start", which writes to src/main/webapp/jsbundles) takes
|
||||
effect without repackaging.
|
||||
|
||||
Never link WEB-INF/classes as a whole: it is real build output holding the symbol SVGs that
|
||||
Symbol.loadSymbol reads off the class path as images/symbols/*.svg, and replacing it makes
|
||||
every icon render as the placeholder cross. Link the individual roots instead. A miss in
|
||||
WEB-INF/classes falls through to jenkins-core.jar, so the generated .stapler and .javadoc
|
||||
resources under these packages still resolve.
|
||||
|
||||
Putting the core roots in front of jenkins-core.jar is what lets an edited Messages.properties
|
||||
be picked up on the next restart rather than needing "mvn -pl core install" and a repackage.
|
||||
Only on restart: ResourceBundleHolder caches each bundle for the life of the JVM. Views and
|
||||
their sibling .properties are live, via stapler.resourcePath below.
|
||||
-->
|
||||
<scan>0</scan>
|
||||
<httpConnector>
|
||||
<host>${host}</host>
|
||||
<port>${port}</port>
|
||||
</httpConnector>
|
||||
<loginServices>
|
||||
<loginService implementation="org.eclipse.jetty.security.HashLoginService">
|
||||
<name>default</name>
|
||||
<config implementation="org.eclipse.jetty.maven.MavenResource">
|
||||
<resourceAsString>${basedir}/src/realm.properties</resourceAsString>
|
||||
</config>
|
||||
</loginService>
|
||||
</loginServices>
|
||||
<webrootLinks>
|
||||
<webrootLink>
|
||||
<path>jsbundles</path>
|
||||
<target>${project.basedir}/src/main/webapp/jsbundles</target>
|
||||
</webrootLink>
|
||||
<webrootLink>
|
||||
<path>images</path>
|
||||
<target>${project.basedir}/src/main/webapp/images</target>
|
||||
</webrootLink>
|
||||
<webrootLink>
|
||||
<path>scripts</path>
|
||||
<target>${project.basedir}/src/main/webapp/scripts</target>
|
||||
</webrootLink>
|
||||
<webrootLink>
|
||||
<path>css</path>
|
||||
<target>${project.basedir}/src/main/webapp/css</target>
|
||||
</webrootLink>
|
||||
<webrootLink>
|
||||
<path>help</path>
|
||||
<target>${project.basedir}/src/main/webapp/help</target>
|
||||
</webrootLink>
|
||||
<webrootLink>
|
||||
<path>WEB-INF/classes/images</path>
|
||||
<target>${project.basedir}/src/main/resources/images</target>
|
||||
</webrootLink>
|
||||
<webrootLink>
|
||||
<path>WEB-INF/classes/hudson</path>
|
||||
<target>${project.basedir}/../core/src/main/resources/hudson</target>
|
||||
</webrootLink>
|
||||
<webrootLink>
|
||||
<path>WEB-INF/classes/jenkins</path>
|
||||
<target>${project.basedir}/../core/src/main/resources/jenkins</target>
|
||||
</webrootLink>
|
||||
<webrootLink>
|
||||
<path>WEB-INF/classes/lib</path>
|
||||
<target>${project.basedir}/../core/src/main/resources/lib</target>
|
||||
</webrootLink>
|
||||
</webrootLinks>
|
||||
<systemProperties>
|
||||
<JENKINS_HOME>${JENKINS_HOME}</JENKINS_HOME>
|
||||
<!-- always reload views during debugging -->
|
||||
<stapler.jelly.noCache>true</stapler.jelly.noCache>
|
||||
<hudson.Main.development>true</hudson.Main.development>
|
||||
<!-- show the stapler evaluation during execution -->
|
||||
<stapler.trace>true</stapler.trace>
|
||||
<!-- show the full stack trace on errors (the oops page) -->
|
||||
@@ -365,26 +383,10 @@ THE SOFTWARE.
|
||||
<!-- always reload scripts during debugging -->
|
||||
<hudson.script.noCache>true</hudson.script.noCache>
|
||||
<!-- load view resources from the source directly, again for real time change -->
|
||||
<stapler.resourcePath>../core/src/main/resources;</stapler.resourcePath>
|
||||
<!-- enable the plugins in main by default -->
|
||||
<!-- run "mvn install" once will generate the.hpl -->
|
||||
<hudson.bundled.plugins>${project.build.directory}/${project.build.finalName}/WEB-INF/plugins/*.hpi</hudson.bundled.plugins>
|
||||
<stapler.resourcePath>${project.basedir}/../core/src/main/resources</stapler.resourcePath>
|
||||
<!-- stat collection pointless -->
|
||||
<hudson.model.UsageStatistics.disabled>true</hudson.model.UsageStatistics.disabled>
|
||||
<hudson.Main.development>true</hudson.Main.development>
|
||||
<!--
|
||||
Prevent org.apache.xalan.processor.TransformerFactoryImpl from being loaded from the Maven classpath,
|
||||
instead preferring com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl as is used in
|
||||
production contexts.
|
||||
-->
|
||||
<javax.xml.transform.TransformerFactory>com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl</javax.xml.transform.TransformerFactory>
|
||||
</systemProperties>
|
||||
<webApp>
|
||||
<!-- Allow resources to be reloaded and enable nicer console logging. -->
|
||||
<extraClasspath>${project.basedir}/../core/src/main/resources,${project.build.directory}/support-log-formatter.jar</extraClasspath>
|
||||
<contextPath>${contextPath}</contextPath>
|
||||
<webInfIncludeJarPattern>.*(jenkins-core|target/classes).*</webInfIncludeJarPattern>
|
||||
</webApp>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
@@ -213,6 +213,19 @@ public class Main {
|
||||
}
|
||||
}
|
||||
|
||||
File explodedWar = null;
|
||||
for (String arg : args) {
|
||||
if (arg.startsWith("--explodedWar=")) {
|
||||
explodedWar = new File(arg.substring("--explodedWar=".length()));
|
||||
if (!new File(explodedWar, "WEB-INF/web.xml").isFile()) {
|
||||
System.err.println("The explodedWar value is not an expanded WAR file: no WEB-INF/web.xml in " + explodedWar);
|
||||
System.exit(1);
|
||||
}
|
||||
// if specified multiple times, the first one wins
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (String arg : args) {
|
||||
if (arg.startsWith("--pluginroot=")) {
|
||||
System.setProperty("hudson.PluginManager.workDir",
|
||||
@@ -231,14 +244,22 @@ public class Main {
|
||||
|
||||
// figure out the arguments
|
||||
trimOffOurOptions(arguments);
|
||||
arguments.add(0, "--warfile=" + me.getAbsolutePath());
|
||||
if (!hasOption(arguments, "--webroot=")) {
|
||||
// defaults to ~/.jenkins/war since many users reported that cron job attempts to clean up
|
||||
// the contents in the temporary directory.
|
||||
final File jenkinsHome = getJenkinsHome();
|
||||
final File webRoot = new File(jenkinsHome, "war");
|
||||
System.out.println("webroot: " + webRoot);
|
||||
arguments.add("--webroot=" + webRoot);
|
||||
if (explodedWar != null) {
|
||||
// Serve the directory as it is. Passing --warfile as well would make Winstone extract the
|
||||
// WAR over the top of it, wiping it in the process.
|
||||
arguments.removeIf(arg -> arg.startsWith("--webroot="));
|
||||
System.out.println("webroot: " + explodedWar + " (already expanded)");
|
||||
arguments.add("--webroot=" + explodedWar);
|
||||
} else {
|
||||
arguments.add(0, "--warfile=" + me.getAbsolutePath());
|
||||
if (!hasOption(arguments, "--webroot=")) {
|
||||
// defaults to ~/.jenkins/war since many users reported that cron job attempts to clean up
|
||||
// the contents in the temporary directory.
|
||||
final File jenkinsHome = getJenkinsHome();
|
||||
final File webRoot = new File(jenkinsHome, "war");
|
||||
System.out.println("webroot: " + webRoot);
|
||||
arguments.add("--webroot=" + webRoot);
|
||||
}
|
||||
}
|
||||
|
||||
// only do a cleanup if you set the extractedFilesFolder property.
|
||||
@@ -292,6 +313,8 @@ public class Main {
|
||||
"\n" +
|
||||
"Options:\n" +
|
||||
" --webroot = folder where the WAR file is expanded into. Default is ${JENKINS_HOME}/war\n" +
|
||||
" --explodedWar = folder holding an already expanded WAR file, served as is. No extraction\n" +
|
||||
" is performed and --webroot is ignored\n" +
|
||||
" --pluginroot = folder where the plugin archives are expanded into. Default is ${JENKINS_HOME}/plugins\n" +
|
||||
" (NOTE: this option does not change the directory where the plugin archives are stored)\n" +
|
||||
" --extractedFilesFolder = folder where extracted files are to be located. Default is the temp folder\n" +
|
||||
@@ -348,7 +371,8 @@ public class Main {
|
||||
|
||||
private static void trimOffOurOptions(List<String> arguments) {
|
||||
arguments.removeIf(arg -> arg.startsWith("--extractedFilesFolder")
|
||||
|| arg.startsWith("--pluginroot") || arg.startsWith(ENABLE_FUTURE_JAVA_CLI_SWITCH));
|
||||
|| arg.startsWith("--pluginroot") || arg.startsWith("--explodedWar")
|
||||
|| arg.startsWith(ENABLE_FUTURE_JAVA_CLI_SWITCH));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
# The MIT License
|
||||
#
|
||||
# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
|
||||
#
|
||||
# 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.
|
||||
|
||||
# For the syntax of this file see:
|
||||
# https://wiki.eclipse.org/Jetty/Tutorial/Realms#HashLoginService
|
||||
|
||||
guest: guest
|
||||
admin: admin,admin
|
||||
alice: alice,admin
|
||||
david: david,developer
|
||||
Reference in new issue
Block a user