diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 456f8fca6da7..a2ed88450df5 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -28,16 +28,17 @@ For refactoring and code cleanup changes, exercise the code before and after the ### Proposed changelog entries -- JENKINS-XXXXX, human-readable text +- human-readable text @@ -45,6 +46,11 @@ You may add multiple changelog entries if applicable by adding a new entry to th N/A + + ```[tasklist] ### Submitter checklist - [ ] The Jira issue, if it exists, is well-described. diff --git a/.github/workflows/label-conflicting-pr.yml b/.github/workflows/label-conflicting-pr.yml index ae90f55bc77d..8b78edd6004c 100644 --- a/.github/workflows/label-conflicting-pr.yml +++ b/.github/workflows/label-conflicting-pr.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Label conflicting PRs - uses: eps1lon/actions-label-merge-conflict@v3.0.1 + uses: eps1lon/actions-label-merge-conflict@v3.0.2 with: dirtyLabel: "unresolved-merge-conflict" repoToken: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/publish-release-artifact.yml b/.github/workflows/publish-release-artifact.yml index 31854bf8266f..ae5e6bf92602 100644 --- a/.github/workflows/publish-release-artifact.yml +++ b/.github/workflows/publish-release-artifact.yml @@ -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@69320dbe05506a9a39fc8ae11030b214ec2d1f87 + uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -108,7 +108,7 @@ jobs: - name: Upload Release Asset id: upload-deb if: always() - uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 + uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -144,7 +144,7 @@ jobs: - name: Upload Release Asset id: upload-rpm if: always() - uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 + uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -180,7 +180,7 @@ jobs: - name: Upload Release Asset id: upload-msi if: always() - uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 + uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: @@ -216,7 +216,7 @@ jobs: - name: Upload Release Asset id: upload-suse-rpm if: always() - uses: softprops/action-gh-release@69320dbe05506a9a39fc8ae11030b214ec2d1f87 + uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: diff --git a/.gitpod/Dockerfile b/.gitpod/Dockerfile index f2475612b107..63c4aff7d91a 100644 --- a/.gitpod/Dockerfile +++ b/.gitpod/Dockerfile @@ -1,6 +1,6 @@ FROM gitpod/workspace-full -ARG MAVEN_VERSION=3.9.7 +ARG MAVEN_VERSION=3.9.8 RUN brew install gh && \ bash -c ". /home/gitpod/.sdkman/bin/sdkman-init.sh && sdk install maven ${MAVEN_VERSION} && sdk default maven ${MAVEN_VERSION}" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 77c012b44c68..58af2c65852e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,7 +9,7 @@ This page provides information about contributing code to the Jenkins core codeb 1. Fork the repository on GitHub 2. Clone the forked repository to your machine 3. Install the necessary development tools. In order to develop Jenkins, you need the following: - - Java Development Kit (JDK) 11, 17 or 21. + - Java Development Kit (JDK) 17 or 21. In the Jenkins project we usually use [Eclipse Temurin](https://adoptium.net/) or [OpenJDK](https://openjdk.java.net/), but you can use other JDKs as well. - Apache Maven 3.8.1 or above. You can [download Maven here](https://maven.apache.org/download.cgi). In the Jenkins project we usually use the most recent Maven release. diff --git a/Jenkinsfile b/Jenkinsfile index 8b87983f43fc..2380b3b66d9a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -14,12 +14,12 @@ properties([ def axes = [ platforms: ['linux', 'windows'], - jdks: [11, 17, 21], + jdks: [17, 21], ] stage('Record build') { retry(conditions: [kubernetesAgent(handleNonKubernetes: true), nonresumable()], count: 2) { - node('maven-11') { + node('maven-17') { infra.checkoutSCM() /* diff --git a/ath.sh b/ath.sh index 3ab8d159b66e..81106967e54b 100644 --- a/ath.sh +++ b/ath.sh @@ -6,7 +6,7 @@ set -o xtrace cd "$(dirname "$0")" # https://github.com/jenkinsci/acceptance-test-harness/releases -export ATH_VERSION=5858.v4b_c4e3b_16099 +export ATH_VERSION=5909.vc4fa_3e55b_f84 if [[ $# -eq 0 ]]; then export JDK=17 diff --git a/bom/pom.xml b/bom/pom.xml index 273355a332b2..8f8e6412f7b0 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -40,7 +40,7 @@ THE SOFTWARE. 2.0.0-M2 2.0.13 - 1870.v48cc46ef5fee + 1892.v73465f3d074d 2.4.21 @@ -56,7 +56,7 @@ THE SOFTWARE. org.springframework spring-framework-bom - 5.3.36 + 5.3.37 pom import @@ -64,7 +64,7 @@ THE SOFTWARE. org.springframework.security spring-security-bom - 5.8.12 + 5.8.13 pom import @@ -82,7 +82,7 @@ THE SOFTWARE. com.google.guava guava - 33.2.0-jre + 33.2.1-jre @@ -113,7 +113,7 @@ THE SOFTWARE. commons-codec commons-codec - 1.17.0 + 1.17.1 commons-collections @@ -376,7 +376,7 @@ THE SOFTWARE. commons-logging commons-logging - 1.3.2 + 1.3.3 provided diff --git a/cli/pom.xml b/cli/pom.xml index 14d6323ca762..c037ed4a0ee8 100644 --- a/cli/pom.xml +++ b/cli/pom.xml @@ -119,7 +119,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.3 + 3.6.0 diff --git a/core/pom.xml b/core/pom.xml index 61c48e489794..95c289164930 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -507,6 +507,62 @@ THE SOFTWARE. + + org.apache.maven.plugins + maven-enforcer-plugin + + + + enforce-banned-dependencies + + enforce + + + + + + + com.fasterxml.jackson.* + com.github.ben-manes.caffeine:caffeine + com.github.jnr:jnr-posix + com.github.mwiede:jsch + com.google.code.gson:gson + com.jayway.jsonpath:json-path + commons-httpclient:commons-httpclient + com.sun.activation:javax.activation + com.sun.mail:javax.mail + com.sun.xml.bind:jaxb-impl + io.jsonwebtoken + + jakarta.activation:jakarta.activation-api:*:jar:compile + jakarta.activation:jakarta.activation-api:*:jar:runtime + jakarta.mail:jakarta.mail-api + javax.activation:javax.activation-api + javax.mail:javax.mail-api + javax.xml.bind:jaxb-api + joda-time:joda-time + + net.bytebuddy:byte-buddy:*:jar:compile + net.bytebuddy:byte-buddy:*:jar:runtime + net.i2p.crypto:eddsa + net.minidev + org.apache.commons:commons-lang3 + org.apache.commons:commons-text + org.apache.httpcomponents + org.bouncycastle + org.eclipse.angus:angus-activation + org.eclipse.angus:angus-mail + org.glassfish.jersey.* + org.json:json + org.ow2.asm + org.yaml:snakeyaml + + + + + + + org.codehaus.mojo build-helper-maven-plugin diff --git a/core/src/main/java/hudson/ClassicPluginStrategy.java b/core/src/main/java/hudson/ClassicPluginStrategy.java index d9b37f0fac29..3d6edf832f9f 100644 --- a/core/src/main/java/hudson/ClassicPluginStrategy.java +++ b/core/src/main/java/hudson/ClassicPluginStrategy.java @@ -252,7 +252,7 @@ private void fix(Attributes atts, List optionalDepende for (Dependency d : DetachedPluginsUtil.getImpliedDependencies(pluginName, jenkinsVersion)) { LOGGER.fine(() -> "implied dep " + pluginName + " → " + d.shortName); - pluginManager.considerDetachedPlugin(d.shortName); + pluginManager.considerDetachedPlugin(d.shortName, pluginName); optionalDependencies.add(d); } } @@ -269,17 +269,17 @@ public static List getImpliedDependencies(String plugi } /** - * @deprecated since TODO use {@link #createClassLoader(String, List, ClassLoader, Attributes)} + * @deprecated since 2.459 use {@link #createClassLoader(String, List, ClassLoader, Attributes)} */ - @Deprecated(since = "TODO") + @Deprecated(since = "2.459") protected ClassLoader createClassLoader(List paths, ClassLoader parent) throws IOException { return createClassLoader(paths, parent, null); } /** - * @deprecated since TODO use {@link #createClassLoader(String, List, ClassLoader, Attributes)} + * @deprecated since 2.459 use {@link #createClassLoader(String, List, ClassLoader, Attributes)} */ - @Deprecated(since="TODO") + @Deprecated(since="2.459") protected ClassLoader createClassLoader(List paths, ClassLoader parent, Attributes atts) throws IOException { // generate a legacy id so at least we can track to something return createClassLoader("unidentified-" + UUID.randomUUID(), paths, parent, atts); @@ -287,7 +287,7 @@ protected ClassLoader createClassLoader(List paths, ClassLoader parent, At /** * Creates a classloader that can load all the specified jar files and delegate to the given parent. - * @since TODO + * @since 2.459 */ protected ClassLoader createClassLoader(String name, List paths, ClassLoader parent, Attributes atts) throws IOException { boolean usePluginFirstClassLoader = diff --git a/core/src/main/java/hudson/DependencyRunner.java b/core/src/main/java/hudson/DependencyRunner.java index b7db91fb9416..f577440659cf 100644 --- a/core/src/main/java/hudson/DependencyRunner.java +++ b/core/src/main/java/hudson/DependencyRunner.java @@ -58,7 +58,7 @@ public void run() { // Get all top-level projects LOGGER.fine("assembling top level projects"); for (AbstractProject p : Jenkins.get().allItems(AbstractProject.class)) - if (p.getUpstreamProjects().size() == 0) { + if (p.getUpstreamProjects().isEmpty()) { LOGGER.fine("adding top level project " + p.getName()); topLevelProjects.add(p); } else { diff --git a/core/src/main/java/hudson/EnvVars.java b/core/src/main/java/hudson/EnvVars.java index 286151e46bf7..97def5f11a7f 100644 --- a/core/src/main/java/hudson/EnvVars.java +++ b/core/src/main/java/hudson/EnvVars.java @@ -114,8 +114,7 @@ public EnvVars(@NonNull Map m) { // because of the backward compatibility, some parts of Jenkins passes // EnvVars as Map so downcasting is safer. - if (m instanceof EnvVars) { - EnvVars lhs = (EnvVars) m; + if (m instanceof EnvVars lhs) { this.platform = lhs.platform; } } diff --git a/core/src/main/java/hudson/FilePath.java b/core/src/main/java/hudson/FilePath.java index 44a39b22836f..06773dd9a9ee 100644 --- a/core/src/main/java/hudson/FilePath.java +++ b/core/src/main/java/hudson/FilePath.java @@ -321,7 +321,7 @@ public static String normalize(@NonNull String path) { buf.append(m.group(1)); path = path.substring(m.end()); } - boolean isAbsolute = buf.length() > 0; + boolean isAbsolute = !buf.isEmpty(); // Split remaining path into tokens, trimming any duplicate or trailing separators List tokens = new ArrayList<>(); int s = 0, end = path.length(); @@ -366,7 +366,7 @@ public static String normalize(@NonNull String path) { } // Recombine tokens for (String token : tokens) buf.append(token); - if (buf.length() == 0) buf.append('.'); + if (buf.isEmpty()) buf.append('.'); return buf.toString(); } @@ -997,8 +997,7 @@ private boolean installIfNecessaryFrom(@NonNull URL archive, @NonNull TaskListen } } - if (con instanceof HttpURLConnection) { - HttpURLConnection httpCon = (HttpURLConnection) con; + if (con instanceof HttpURLConnection httpCon) { int responseCode = httpCon.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode == HttpURLConnection.HTTP_MOVED_TEMP) { @@ -1445,7 +1444,7 @@ private static class DeleteSuffixesRecursive extends MasterToSlaveFileCallable path.toFile()); + Util.deleteRecursive(file.toPath(), Path::toFile); } } @@ -1476,7 +1475,7 @@ private static class DeleteRecursive extends MasterToSlaveFileCallable { @Override public Void invoke(File f, VirtualChannel channel) throws IOException { - Util.deleteRecursive(fileToPath(f), path -> path.toFile()); + Util.deleteRecursive(fileToPath(f), Path::toFile); return null; } } @@ -1493,7 +1492,7 @@ private static class DeleteContents extends MasterToSlaveFileCallable { @Override public Void invoke(File f, VirtualChannel channel) throws IOException { - Util.deleteContentsRecursive(fileToPath(f), path -> path.toFile()); + Util.deleteContentsRecursive(fileToPath(f), Path::toFile); return null; } } diff --git a/core/src/main/java/hudson/Functions.java b/core/src/main/java/hudson/Functions.java index 2e6abc978540..cd25f9bc9871 100644 --- a/core/src/main/java/hudson/Functions.java +++ b/core/src/main/java/hudson/Functions.java @@ -316,8 +316,7 @@ public static void initPageVariables(JellyContext context) { */ public static Class getTypeParameter(Class c, Class base, int n) { Type parameterization = Types.getBaseClass(c, base); - if (parameterization instanceof ParameterizedType) { - ParameterizedType pt = (ParameterizedType) parameterization; + if (parameterization instanceof ParameterizedType pt) { return Types.erasure(Types.getTypeArgument(pt, n)); } else { throw new AssertionError(c + " doesn't properly parameterize " + base); @@ -1422,7 +1421,7 @@ public static String getRelativeNameFrom(@CheckForNull Item p, @CheckForNull Ite StringBuilder buf = new StringBuilder(); Item i = p; while (true) { - if (buf.length() > 0) buf.insert(0, separationString); + if (!buf.isEmpty()) buf.insert(0, separationString); buf.insert(0, useDisplayName ? i.getDisplayName() : i.getName()); ItemGroup gr = i.getParent(); @@ -1873,7 +1872,7 @@ public static String joinPath(String... components) { for (String s : components) { if (s.isEmpty()) continue; - if (buf.length() > 0) { + if (!buf.isEmpty()) { if (buf.charAt(buf.length() - 1) != '/') buf.append('/'); if (s.charAt(0) == '/') s = s.substring(1); @@ -1979,8 +1978,7 @@ public String getServerName() { @Deprecated public String getCheckUrl(String userDefined, Object descriptor, String field) { if (userDefined != null || field == null) return userDefined; - if (descriptor instanceof Descriptor) { - Descriptor d = (Descriptor) descriptor; + if (descriptor instanceof Descriptor d) { return d.getCheckUrl(field); } return null; @@ -1993,8 +1991,7 @@ public String getCheckUrl(String userDefined, Object descriptor, String field) { public void calcCheckUrl(Map attributes, String userDefined, Object descriptor, String field) { if (userDefined != null || field == null) return; - if (descriptor instanceof Descriptor) { - Descriptor d = (Descriptor) descriptor; + if (descriptor instanceof Descriptor d) { CheckMethod m = d.getCheckMethod(field); attributes.put("checkUrl", m.toStemUrl()); attributes.put("checkDependsOn", m.getDependsOn()); @@ -2057,7 +2054,7 @@ public static List> getCloudDescriptors() { * Prepend a prefix only when there's the specified body. */ public String prepend(String prefix, String body) { - if (body != null && body.length() > 0) + if (body != null && !body.isEmpty()) return prefix + body; return body; } diff --git a/core/src/main/java/hudson/PluginManager.java b/core/src/main/java/hudson/PluginManager.java index 5d80c6e623e4..75dd52c4d7b7 100644 --- a/core/src/main/java/hudson/PluginManager.java +++ b/core/src/main/java/hudson/PluginManager.java @@ -615,7 +615,7 @@ public void run(Reactor reactor) throws Exception { }}); } - void considerDetachedPlugin(String shortName) { + void considerDetachedPlugin(String shortName, String source) { if (new File(rootDir, shortName + ".jpi").isFile() || new File(rootDir, shortName + ".hpi").isFile() || new File(rootDir, shortName + ".jpl").isFile() || @@ -627,7 +627,7 @@ void considerDetachedPlugin(String shortName) { for (String loadedFile : loadPluginsFromWar(getDetachedLocation(), (dir, name) -> normalisePluginName(name).equals(shortName))) { String loaded = normalisePluginName(loadedFile); File arc = new File(rootDir, loaded + ".jpi"); - LOGGER.info(() -> "Loading a detached plugin as a dependency: " + arc); + LOGGER.info(() -> "Loading a detached plugin " + arc + " as a dependency of " + source); try { plugins.add(strategy.createPluginWrapper(arc)); } catch (IOException e) { @@ -716,6 +716,10 @@ protected static void addDependencies(URL hpiResUrl, String fromPath, Set d } Manifest manifest = parsePluginManifest(hpiResUrl); + if (manifest == null) { + return; + } + String dependencySpec = manifest.getMainAttributes().getValue("Plugin-Dependencies"); if (dependencySpec != null) { String[] dependencyTokens = dependencySpec.split(","); diff --git a/core/src/main/java/hudson/cli/CLIAction.java b/core/src/main/java/hudson/cli/CLIAction.java index 4265a6283a2b..9e29b141560c 100644 --- a/core/src/main/java/hudson/cli/CLIAction.java +++ b/core/src/main/java/hudson/cli/CLIAction.java @@ -217,7 +217,7 @@ protected void closed(int statusCode, String reason) { @Override public Object getTarget() { StaplerRequest req = Stapler.getCurrentRequest(); - if (req.getRestOfPath().length() == 0 && "POST".equals(req.getMethod())) { + if (req.getRestOfPath().isEmpty() && "POST".equals(req.getMethod())) { // CLI connection request if ("false".equals(req.getParameter("remoting"))) { throw new PlainCliEndpointResponse(); diff --git a/core/src/main/java/hudson/cli/GroovyshCommand.java b/core/src/main/java/hudson/cli/GroovyshCommand.java index 8bc4d522e254..18cbc6da7513 100644 --- a/core/src/main/java/hudson/cli/GroovyshCommand.java +++ b/core/src/main/java/hudson/cli/GroovyshCommand.java @@ -77,7 +77,7 @@ protected int run() { StringBuilder commandLine = new StringBuilder(); for (String arg : args) { - if (commandLine.length() > 0) { + if (!commandLine.isEmpty()) { commandLine.append(" "); } commandLine.append(arg); diff --git a/core/src/main/java/hudson/console/ExpandableDetailsNote.java b/core/src/main/java/hudson/console/ExpandableDetailsNote.java index 1f558e6a260b..beb623b5034c 100644 --- a/core/src/main/java/hudson/console/ExpandableDetailsNote.java +++ b/core/src/main/java/hudson/console/ExpandableDetailsNote.java @@ -26,8 +26,8 @@ import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; -import hudson.Functions; import hudson.MarkupText; +import hudson.Util; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; @@ -53,7 +53,8 @@ public ExpandableDetailsNote(String caption, String html) { @Override public ConsoleAnnotator annotate(Object context, MarkupText text, int charPos) { text.addMarkup(charPos, - "
" + html + "
"); + "
" + html + "
"); return null; } diff --git a/core/src/main/java/hudson/diagnosis/OldDataMonitor.java b/core/src/main/java/hudson/diagnosis/OldDataMonitor.java index b389221f763e..e2bfa4678fc9 100644 --- a/core/src/main/java/hudson/diagnosis/OldDataMonitor.java +++ b/core/src/main/java/hudson/diagnosis/OldDataMonitor.java @@ -218,7 +218,7 @@ public static void report(Saveable obj, Collection errors) { buf.append(e.getClass().getSimpleName()).append(": ").append(e.getMessage()); } } - if (buf.length() == 0) return; + if (buf.isEmpty()) return; Jenkins j = Jenkins.getInstanceOrNull(); if (j == null) { // Need this path, at least for unit tests, but also in case of very broken startup // Startup failed, something is very broken, so report what we can. diff --git a/core/src/main/java/hudson/init/impl/InstallUncaughtExceptionHandler.java b/core/src/main/java/hudson/init/impl/InstallUncaughtExceptionHandler.java index 8873925847dc..c305e9a6febc 100644 --- a/core/src/main/java/hudson/init/impl/InstallUncaughtExceptionHandler.java +++ b/core/src/main/java/hudson/init/impl/InstallUncaughtExceptionHandler.java @@ -18,8 +18,8 @@ import org.kohsuke.stapler.Stapler; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.UncaughtExceptionFilter; import org.kohsuke.stapler.WebApp; -import org.kohsuke.stapler.compression.CompressionFilter; /** * Deals with exceptions that get thrown all the way up to the Stapler rendering layer. @@ -30,7 +30,7 @@ public class InstallUncaughtExceptionHandler { @Initializer public static void init(final Jenkins j) throws IOException { - CompressionFilter.setUncaughtExceptionHandler(j.servletContext, (e, context, req, rsp) -> handleException(j, e, req, rsp, 500)); + UncaughtExceptionFilter.setUncaughtExceptionHandler(j.servletContext, (e, context, req, rsp) -> handleException(j, e, req, rsp, 500)); try { Thread.setDefaultUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler()); LOGGER.log(Level.FINE, "Successfully installed a global UncaughtExceptionHandler."); diff --git a/core/src/main/java/hudson/lifecycle/ExitLifecycle.java b/core/src/main/java/hudson/lifecycle/ExitLifecycle.java index f8fcc3abefbf..038dafc442a3 100644 --- a/core/src/main/java/hudson/lifecycle/ExitLifecycle.java +++ b/core/src/main/java/hudson/lifecycle/ExitLifecycle.java @@ -26,6 +26,7 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import hudson.Extension; +import hudson.util.BootFailure; import java.util.logging.Level; import java.util.logging.Logger; import jenkins.model.Jenkins; @@ -72,4 +73,9 @@ public void restart() { System.exit(exitOnRestart); } + + @Override + public void onBootFailure(BootFailure problem) { + restart(); + } } diff --git a/core/src/main/java/hudson/lifecycle/Lifecycle.java b/core/src/main/java/hudson/lifecycle/Lifecycle.java index dbc53d2b5005..fcd7769aeff2 100644 --- a/core/src/main/java/hudson/lifecycle/Lifecycle.java +++ b/core/src/main/java/hudson/lifecycle/Lifecycle.java @@ -32,6 +32,8 @@ import hudson.Util; import hudson.init.InitMilestone; import hudson.init.Initializer; +import hudson.util.BootFailure; +import hudson.util.JenkinsReloadFailed; import java.io.File; import java.io.IOException; import java.io.UncheckedIOException; @@ -324,6 +326,14 @@ public boolean supportsDynamicLoad() { return true; } + /** + * Called when Jenkins has failed to boot. + * @param problem a boot failure (could be {@link JenkinsReloadFailed}) + * @since TODO + */ + public void onBootFailure(BootFailure problem) { + } + @Restricted(NoExternalUse.class) public static final class PlaceholderLifecycle extends ExitLifecycle { diff --git a/core/src/main/java/hudson/logging/LogRecorder.java b/core/src/main/java/hudson/logging/LogRecorder.java index 23ebc72cde6a..86aea6575048 100644 --- a/core/src/main/java/hudson/logging/LogRecorder.java +++ b/core/src/main/java/hudson/logging/LogRecorder.java @@ -393,7 +393,7 @@ private static final class SetLevel extends MasterToSlaveCallable { void broadcast() { for (Computer c : Jenkins.get().getComputers()) { - if (c.getName().length() > 0) { // i.e. not master + if (!c.getName().isEmpty()) { // i.e. not master VirtualChannel ch = c.getChannel(); if (ch != null) { try { @@ -595,7 +595,7 @@ public int compare(Computer c1, Computer c2) { } }); for (Computer c : Jenkins.get().getComputers()) { - if (c.getName().length() == 0) { + if (c.getName().isEmpty()) { continue; // master } List recs = new ArrayList<>(); diff --git a/core/src/main/java/hudson/model/AbstractBuild.java b/core/src/main/java/hudson/model/AbstractBuild.java index bcd29082ebe1..85d62df78896 100644 --- a/core/src/main/java/hudson/model/AbstractBuild.java +++ b/core/src/main/java/hudson/model/AbstractBuild.java @@ -607,8 +607,7 @@ protected Launcher createLauncher(@NonNull BuildListener listener) throws IOExce final Node currentNode = getCurrentNode(); Launcher l = currentNode.createLauncher(listener); - if (project instanceof BuildableItemWithBuildWrappers) { - BuildableItemWithBuildWrappers biwbw = (BuildableItemWithBuildWrappers) project; + if (project instanceof BuildableItemWithBuildWrappers biwbw) { for (BuildWrapper bw : biwbw.getBuildWrappersList()) l = bw.decorateLauncher(AbstractBuild.this, l, listener); } diff --git a/core/src/main/java/hudson/model/AbstractItem.java b/core/src/main/java/hudson/model/AbstractItem.java index 5bd1d6a02d79..adebec8f289f 100644 --- a/core/src/main/java/hudson/model/AbstractItem.java +++ b/core/src/main/java/hudson/model/AbstractItem.java @@ -25,7 +25,6 @@ package hudson.model; -import static hudson.model.queue.Executables.getParentOf; import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; import com.infradna.tool.bridge_method_injector.WithBridgeMethods; @@ -39,9 +38,6 @@ import hudson.cli.declarative.CLIResolver; import hudson.model.listeners.ItemListener; import hudson.model.listeners.SaveableListener; -import hudson.model.queue.SubTask; -import hudson.model.queue.Tasks; -import hudson.model.queue.WorkUnit; import hudson.security.ACL; import hudson.security.ACLContext; import hudson.security.AccessControlled; @@ -57,12 +53,8 @@ import java.nio.charset.Charset; import java.nio.file.Files; import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; import java.util.ListIterator; -import java.util.Map; -import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; @@ -551,8 +543,7 @@ public final String getUrl() { List ancestors = req.getAncestors(); if (!ancestors.isEmpty()) { Ancestor last = ancestors.get(ancestors.size() - 1); - if (last.getObject() instanceof View) { - View view = (View) last.getObject(); + if (last.getObject() instanceof View view) { if (view.getOwner().getItemGroup() == getParent() && !view.isDefault()) { // Showing something inside a view, so should use that as the base URL. String prefix = req.getContextPath() + "/"; @@ -706,11 +697,13 @@ public void delete(StaplerRequest req, StaplerResponse rsp) throws IOException, * *

* Any exception indicates the deletion has failed, but {@link AbortException} would prevent the caller - * from showing the stack trace. This + * from showing the stack trace. + * @see ItemDeletion */ @Override public void delete() throws IOException, InterruptedException { checkPermission(DELETE); + ItemListener.checkBeforeDelete(this); boolean responsibleForAbortingBuilds = !ItemDeletion.contains(this); boolean ownsRegistration = ItemDeletion.register(this); if (!ownsRegistration && ItemDeletion.isRegistered(this)) { @@ -720,87 +713,7 @@ public void delete() throws IOException, InterruptedException { try { // if a build is in progress. Cancel it. if (responsibleForAbortingBuilds || ownsRegistration) { - Queue queue = Queue.getInstance(); - if (this instanceof Queue.Task) { - // clear any items in the queue so they do not get picked up - queue.cancel((Queue.Task) this); - } - // now cancel any child items - this happens after ItemDeletion registration, so we can use a snapshot - for (Queue.Item i : queue.getItems()) { - Item item = Tasks.getItemOf(i.task); - while (item != null) { - if (item == this) { - if (!queue.cancel(i)) { - LOGGER.warning(() -> "failed to cancel " + i); - } - break; - } - if (item.getParent() instanceof Item) { - item = (Item) item.getParent(); - } else { - break; - } - } - } - // interrupt any builds in progress (and this should be a recursive test so that folders do not pay - // the 15 second delay for every child item). This happens after queue cancellation, so will be - // a complete set of builds in flight - Map buildsInProgress = new LinkedHashMap<>(); - for (Computer c : Jenkins.get().getComputers()) { - for (Executor e : c.getAllExecutors()) { - final WorkUnit workUnit = e.getCurrentWorkUnit(); - final Queue.Executable executable = workUnit != null ? workUnit.getExecutable() : null; - final SubTask subtask = executable != null ? getParentOf(executable) : null; - - if (subtask != null) { - Item item = Tasks.getItemOf(subtask); - while (item != null) { - if (item == this) { - buildsInProgress.put(e, e.getCurrentExecutable()); - e.interrupt(Result.ABORTED); - break; - } - if (item.getParent() instanceof Item) { - item = (Item) item.getParent(); - } else { - break; - } - } - } - } - } - if (!buildsInProgress.isEmpty()) { - // give them 15 seconds or so to respond to the interrupt - long expiration = System.nanoTime() + TimeUnit.SECONDS.toNanos(15); - // comparison with executor.getCurrentExecutable() == computation currently should always be true - // as we no longer recycle Executors, but safer to future-proof in case we ever revisit recycling - while (!buildsInProgress.isEmpty() && expiration - System.nanoTime() > 0L) { - // we know that ItemDeletion will prevent any new builds in the queue - // ItemDeletion happens-before Queue.cancel so we know that the Queue will stay clear - // Queue.cancel happens-before collecting the buildsInProgress list - // thus buildsInProgress contains the complete set we need to interrupt and wait for - for (Iterator> iterator = - buildsInProgress.entrySet().iterator(); - iterator.hasNext(); ) { - Map.Entry entry = iterator.next(); - // comparison with executor.getCurrentExecutable() == executable currently should always be - // true as we no longer recycle Executors, but safer to future-proof in case we ever - // revisit recycling. - if (!entry.getKey().isAlive() - || entry.getValue() != entry.getKey().getCurrentExecutable()) { - iterator.remove(); - } - // I don't know why, but we have to keep interrupting - entry.getKey().interrupt(Result.ABORTED); - } - Thread.sleep(50L); - } - if (!buildsInProgress.isEmpty()) { - throw new Failure(Messages.AbstractItem_FailureToStopBuilds( - buildsInProgress.size(), getFullDisplayName() - )); - } - } + ItemDeletion.cancelBuildsInProgress(this); } if (this instanceof ItemGroup) { // delete individual items first diff --git a/core/src/main/java/hudson/model/AbstractProject.java b/core/src/main/java/hudson/model/AbstractProject.java index 5de1775b11cd..c568f8df8b31 100644 --- a/core/src/main/java/hudson/model/AbstractProject.java +++ b/core/src/main/java/hudson/model/AbstractProject.java @@ -518,8 +518,7 @@ private AbstractBuild getBuildForDeprecatedMethods() { Executor e = Executor.currentExecutor(); if (e != null) { Executable exe = e.getCurrentExecutable(); - if (exe instanceof AbstractBuild) { - AbstractBuild b = (AbstractBuild) exe; + if (exe instanceof AbstractBuild b) { if (b.getProject() == this) return b; } @@ -1012,6 +1011,7 @@ public List getActions() { * null if no information is available (for example, * if no build was done yet.) */ + @SuppressWarnings("deprecation") @Override public Node getLastBuiltOn() { // where was it built on? diff --git a/core/src/main/java/hudson/model/AdministrativeMonitor.java b/core/src/main/java/hudson/model/AdministrativeMonitor.java index 7a9a0dde970c..bdbfb48027d3 100644 --- a/core/src/main/java/hudson/model/AdministrativeMonitor.java +++ b/core/src/main/java/hudson/model/AdministrativeMonitor.java @@ -183,7 +183,7 @@ public void doDisable(StaplerRequest req, StaplerResponse rsp) throws IOExceptio /** * Required permission to view this admin monitor. - * By default {@link Jenkins#ADMINISTER}, but {@link Jenkins#SYSTEM_READ} is also supported. + * By default {@link Jenkins#ADMINISTER}, but {@link Jenkins#SYSTEM_READ} or {@link Jenkins#MANAGE} are also supported. *

* Changing this permission check to return {@link Jenkins#SYSTEM_READ} will make the active * administrative monitor appear on {@code manage.jelly} and on the globally visible @@ -191,23 +191,69 @@ public void doDisable(StaplerRequest req, StaplerResponse rsp) throws IOExceptio * {@link #doDisable(StaplerRequest, StaplerResponse)} will still always require Administer permission. *

*

+ * This method only allows for a single permission to be returned. If more complex permission checks are required, + * override {@link #checkRequiredPermission()} and {@link #hasRequiredPermission()} instead. + *

+ *

* Implementers need to ensure that {@code doAct} and other web methods perform necessary permission checks: * Users with System Read permissions are expected to be limited to read-only access. * Form UI elements that change system state, e.g. toggling a feature on or off, need to be hidden from users * lacking Administer permission. *

+ * @since 2.233 + * @deprecated Callers should use {@link #checkRequiredPermission()} or {@link #hasRequiredPermission()}. */ + @Deprecated public Permission getRequiredPermission() { return Jenkins.ADMINISTER; } + /** + * Checks if the current user has the minimum required permission to view this administrative monitor. + *

+ * Subclasses may override this method and {@link #hasRequiredPermission()} instead of {@link #getRequiredPermission()} to perform more complex permission checks, + * for example, checking either {@link Jenkins#MANAGE} or {@link Jenkins#SYSTEM_READ}. + *

+ * @see #getRequiredPermission() + * @see #hasRequiredPermission() + * @since 2.468 + */ + public void checkRequiredPermission() { + Jenkins.get().checkPermission(getRequiredPermission()); + } + + /** + * Checks if the current user has the minimum required permission to view this administrative monitor. + *

+ * Subclasses may override this method and {@link #checkRequiredPermission} instead of {@link #getRequiredPermission()} to perform more complex permission checks, + * for example, checking either {@link Jenkins#MANAGE} or {@link Jenkins#SYSTEM_READ}. + *

+ * @see #getRequiredPermission() + * @see #checkRequiredPermission() + * @since 2.468 + */ + public boolean hasRequiredPermission() { + return Jenkins.get().hasPermission(getRequiredPermission()); + } + + /** + * Checks if the current user has the minimum required permission to view any administrative monitor. + * + * @return true if the current user has the minimum required permission to view any administrative monitor. + * + * @since 2.468 + */ + public static boolean hasPermissionToDisplay() { + return Jenkins.get().hasAnyPermission(Jenkins.SYSTEM_READ, Jenkins.MANAGE); + } + /** * Ensure that URLs in this administrative monitor are only accessible to users with {@link #getRequiredPermission()}. */ @Override @Restricted(NoExternalUse.class) public Object getTarget() { - Jenkins.get().checkPermission(getRequiredPermission()); + checkRequiredPermission(); return this; } diff --git a/core/src/main/java/hudson/model/Api.java b/core/src/main/java/hudson/model/Api.java index 11db76c3581d..23e72072112f 100644 --- a/core/src/main/java/hudson/model/Api.java +++ b/core/src/main/java/hudson/model/Api.java @@ -190,8 +190,7 @@ public void doXml(StaplerRequest req, StaplerResponse rsp, return; } - // switch to gzipped output - try (OutputStream o = rsp.getCompressedOutputStream(req)) { + try (OutputStream o = rsp.getOutputStream()) { if (isSimpleOutput(result)) { // simple output allowed rsp.setContentType("text/plain;charset=UTF-8"); diff --git a/core/src/main/java/hudson/model/BooleanParameterDefinition.java b/core/src/main/java/hudson/model/BooleanParameterDefinition.java index 5e270ef46da1..6e9db32216fd 100644 --- a/core/src/main/java/hudson/model/BooleanParameterDefinition.java +++ b/core/src/main/java/hudson/model/BooleanParameterDefinition.java @@ -59,8 +59,7 @@ public BooleanParameterDefinition(@NonNull String name, boolean defaultValue, @C @Override public ParameterDefinition copyWithDefaultValue(ParameterValue defaultValue) { - if (defaultValue instanceof BooleanParameterValue) { - BooleanParameterValue value = (BooleanParameterValue) defaultValue; + if (defaultValue instanceof BooleanParameterValue value) { return new BooleanParameterDefinition(getName(), value.value, getDescription()); } else { return this; diff --git a/core/src/main/java/hudson/model/BuildAuthorizationToken.java b/core/src/main/java/hudson/model/BuildAuthorizationToken.java index f101eb3d6e74..a09ed113e1cf 100644 --- a/core/src/main/java/hudson/model/BuildAuthorizationToken.java +++ b/core/src/main/java/hudson/model/BuildAuthorizationToken.java @@ -29,7 +29,6 @@ import hudson.security.ACL; import java.io.IOException; import javax.servlet.http.HttpServletResponse; -import jenkins.security.ApiTokenProperty; import org.kohsuke.stapler.HttpResponses; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; @@ -82,10 +81,6 @@ public static void checkPermission(Job project, BuildAuthorizationToken to return; } - if (req.getAttribute(ApiTokenProperty.class.getName()) instanceof User) { - return; - } - rsp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED); rsp.addHeader("Allow", "POST"); throw HttpResponses.forwardToView(project, "requirePOST.jelly"); diff --git a/core/src/main/java/hudson/model/CauseAction.java b/core/src/main/java/hudson/model/CauseAction.java index eca42ffb6999..316cf3a182d6 100644 --- a/core/src/main/java/hudson/model/CauseAction.java +++ b/core/src/main/java/hudson/model/CauseAction.java @@ -61,8 +61,7 @@ public CauseAction(Cause c) { private void addCause(Cause c) { synchronized (causeBag) { - Integer cnt = causeBag.get(c); - causeBag.put(c, cnt == null ? 1 : cnt + 1); + causeBag.compute(c, (unused, cnt) -> cnt == null ? 1 : cnt + 1); } } diff --git a/core/src/main/java/hudson/model/Computer.java b/core/src/main/java/hudson/model/Computer.java index 6df0b65354a1..38af6b5a56b3 100644 --- a/core/src/main/java/hudson/model/Computer.java +++ b/core/src/main/java/hudson/model/Computer.java @@ -1519,7 +1519,7 @@ public void doDumpExportTable(StaplerRequest req, StaplerResponse rsp) throws IO checkPermission(Jenkins.ADMINISTER); rsp.setContentType("text/plain"); - try (PrintWriter w = new PrintWriter(rsp.getCompressedWriter(req))) { + try (PrintWriter w = new PrintWriter(rsp.getWriter())) { VirtualChannel vc = getChannel(); if (vc instanceof Channel) { w.println("Controller to agent"); diff --git a/core/src/main/java/hudson/model/Descriptor.java b/core/src/main/java/hudson/model/Descriptor.java index 817115c3ad17..b5eb07784d27 100644 --- a/core/src/main/java/hudson/model/Descriptor.java +++ b/core/src/main/java/hudson/model/Descriptor.java @@ -294,8 +294,7 @@ protected Descriptor() { // detect an type error Type bt = Types.getBaseClass(getClass(), Descriptor.class); - if (bt instanceof ParameterizedType) { - ParameterizedType pt = (ParameterizedType) bt; + if (bt instanceof ParameterizedType pt) { // this 't' is the closest approximation of T of Descriptor. Class t = Types.erasure(pt.getActualTypeArguments()[0]); if (!t.isAssignableFrom(clazz)) @@ -595,6 +594,9 @@ public T newInstance(@Nullable StaplerRequest req, @NonNull JSONObject formData) return verifyNewInstance(bindJSON(req, clazz, formData, true)); } } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException | RuntimeException e) { + if (e instanceof RuntimeException && e instanceof HttpResponse) { + throw (RuntimeException) e; + } throw new LinkageError("Failed to instantiate " + clazz + " from " + RedactSecretJsonInErrorMessageSanitizer.INSTANCE.sanitize(formData), e); } } @@ -675,7 +677,7 @@ public Object instantiate(Class actualType, JSONObject json) { + actualType.getName() + " " + json); } } catch (Exception x) { - LOGGER.log(Level.WARNING, "falling back to default instantiation " + actualType.getName() + " " + json, x); + LOGGER.log(x instanceof HttpResponse ? Level.FINE : Level.WARNING, "falling back to default instantiation " + actualType.getName() + " " + json, x); // If nested objects are not using newInstance, bindJSON will wind up throwing the same exception anyway, // so logging above will result in a duplicated stack trace. // However if they *are* then this is the only way to find errors in that newInstance. @@ -688,8 +690,7 @@ public Object instantiate(Class actualType, JSONObject json) { @Override public Object onConvert(Type targetType, Class targetTypeErasure, Object jsonSource) { - if (jsonSource instanceof JSONObject) { - JSONObject json = (JSONObject) jsonSource; + if (jsonSource instanceof JSONObject json) { if (isApplicable(targetTypeErasure, json)) { LOGGER.log(Level.FINE, "switching to newInstance {0} {1}", new Object[] {targetTypeErasure.getName(), json}); try { @@ -895,8 +896,7 @@ protected final String getViewPage(Class clazz, String pageName) { protected List getPossibleViewNames(String baseName) { List names = new ArrayList<>(); for (Facet f : WebApp.get(Jenkins.get().servletContext).facets) { - if (f instanceof JellyCompatibleFacet) { - JellyCompatibleFacet jcf = (JellyCompatibleFacet) f; + if (f instanceof JellyCompatibleFacet jcf) { for (String ext : jcf.getScriptExtensions()) names.add(baseName + ext); } @@ -1007,6 +1007,10 @@ public static URL getStaticHelpUrl(StaplerRequest req, Klass c, String suffix if (url != null) return url; url = c.getResource(base + '_' + locale.getLanguage() + ".html"); if (url != null) return url; + if (locale.getLanguage().equals("en")) { + url = c.getResource(base + ".html"); + if (url != null) return url; + } } // default diff --git a/core/src/main/java/hudson/model/DirectoryBrowserSupport.java b/core/src/main/java/hudson/model/DirectoryBrowserSupport.java index 8083efa72dbf..9d455f4c1bd3 100644 --- a/core/src/main/java/hudson/model/DirectoryBrowserSupport.java +++ b/core/src/main/java/hudson/model/DirectoryBrowserSupport.java @@ -33,6 +33,7 @@ import java.io.OutputStream; import java.io.Serializable; import java.net.URL; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.LinkOption; import java.nio.file.OpenOption; @@ -90,11 +91,6 @@ public final class DirectoryBrowserSupport implements HttpResponse { private static final Pattern TMPDIR_PATTERN = Pattern.compile(".+@tmp/.*"); - /** - * Escape hatch for the protection against SECURITY-2481. If enabled, the absolute paths on Windows will be allowed. - */ - static final String ALLOW_ABSOLUTE_PATH_PROPERTY_NAME = DirectoryBrowserSupport.class.getName() + ".allowAbsolutePath"; - public final ModelObject owner; public final String title; @@ -230,7 +226,7 @@ private void serveFile(StaplerRequest req, StaplerResponse rsp, VirtualFile root String pathElement = pathTokens.nextToken(); // Treat * and ? as wildcard unless they match a literal filename if ((pathElement.contains("?") || pathElement.contains("*")) - && inBase && !root.child((_base.length() > 0 ? _base + "/" : "") + pathElement).exists()) + && inBase && !root.child((!_base.isEmpty() ? _base + "/" : "") + pathElement).exists()) inBase = false; if (pathElement.equals("*zip*")) { // the expected syntax is foo/bar/*zip*/bar.zip @@ -245,7 +241,7 @@ private void serveFile(StaplerRequest req, StaplerResponse rsp, VirtualFile root } StringBuilder sb = inBase ? _base : _rest; - if (sb.length() > 0) sb.append('/'); + if (!sb.isEmpty()) sb.append('/'); sb.append(pathElement); if (!inBase) restSize++; @@ -260,13 +256,11 @@ private void serveFile(StaplerRequest req, StaplerResponse rsp, VirtualFile root if (base.isEmpty()) { baseFile = root; } else { - if (!SystemProperties.getBoolean(ALLOW_ABSOLUTE_PATH_PROPERTY_NAME, false)) { - boolean isAbsolute = root.run(new IsAbsolute(base)); - if (isAbsolute) { - LOGGER.info(() -> "SECURITY-2481 The path provided in the URL (" + base + ") is absolute and thus is refused."); - rsp.sendError(HttpServletResponse.SC_NOT_FOUND); - return; - } + boolean isAbsolute = root.run(new IsAbsolute(base)); + if (isAbsolute) { + LOGGER.info(() -> "SECURITY-2481 The path provided in the URL (" + base + ") is absolute and thus is refused."); + rsp.sendError(HttpServletResponse.SC_NOT_FOUND); + return; } baseFile = root.child(base); } @@ -315,7 +309,7 @@ private void serveFile(StaplerRequest req, StaplerResponse rsp, VirtualFile root } List> glob = null; - boolean patternUsed = rest.length() > 0; + boolean patternUsed = !rest.isEmpty(); boolean containsSymlink = false; boolean containsTmpDir = false; if (patternUsed) { @@ -530,7 +524,7 @@ private static String createBackRef(int times) { private static void zip(StaplerResponse rsp, VirtualFile root, VirtualFile dir, String glob) throws IOException, InterruptedException { OutputStream outputStream = rsp.getOutputStream(); try (ZipOutputStream zos = new ZipOutputStream(outputStream)) { - zos.setEncoding(System.getProperty("file.encoding")); // TODO JENKINS-20663 make this overridable via query parameter + zos.setEncoding(Charset.defaultCharset().displayName()); // TODO JENKINS-20663 make this overridable via query parameter // TODO consider using run(Callable) here if (glob.isEmpty()) { diff --git a/core/src/main/java/hudson/model/DownloadService.java b/core/src/main/java/hudson/model/DownloadService.java index b9a5610c4e35..0988b36785dd 100644 --- a/core/src/main/java/hudson/model/DownloadService.java +++ b/core/src/main/java/hudson/model/DownloadService.java @@ -404,7 +404,7 @@ public FormValidation updateNow() throws IOException { } jsonList.add(o); } - if (jsonList.size() == 0 && toolInstallerMetadataExists) { + if (jsonList.isEmpty() && toolInstallerMetadataExists) { return FormValidation.warning("None of the tool installer metadata passed the signature check"); } else if (!toolInstallerMetadataExists) { LOGGER.log(Level.WARNING, "No tool installer metadata found for " + id); diff --git a/core/src/main/java/hudson/model/ExecutorListener.java b/core/src/main/java/hudson/model/ExecutorListener.java index 6500e6acc2ec..beff34804d92 100644 --- a/core/src/main/java/hudson/model/ExecutorListener.java +++ b/core/src/main/java/hudson/model/ExecutorListener.java @@ -30,7 +30,7 @@ /** * A listener for task related events from executors. * A {@link Computer#getRetentionStrategy} or {@link SlaveComputer#getLauncher} may implement this interface. - * Or you may create an implementation as an extension (since TODO). + * Or you may create an implementation as an extension (since 2.318). * @author Stephen Connolly * @since 1.312 */ diff --git a/core/src/main/java/hudson/model/Fingerprint.java b/core/src/main/java/hudson/model/Fingerprint.java index bd7721906b5f..df482e28e03c 100644 --- a/core/src/main/java/hudson/model/Fingerprint.java +++ b/core/src/main/java/hudson/model/Fingerprint.java @@ -608,7 +608,7 @@ public synchronized boolean removeAll(RangeSet that) { public synchronized String toString() { StringBuilder buf = new StringBuilder(); for (Range r : ranges) { - if (buf.length() > 0) buf.append(','); + if (!buf.isEmpty()) buf.append(','); buf.append(r); } return buf.toString(); @@ -787,7 +787,7 @@ public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingC public static String serialize(RangeSet src) { StringBuilder buf = new StringBuilder(src.ranges.size() * 10); for (Range r : src.ranges) { - if (buf.length() > 0) buf.append(','); + if (!buf.isEmpty()) buf.append(','); if (r.isSingle()) buf.append(r.start); else diff --git a/core/src/main/java/hudson/model/Items.java b/core/src/main/java/hudson/model/Items.java index a1386565cfd0..fac4ae8a4a01 100644 --- a/core/src/main/java/hudson/model/Items.java +++ b/core/src/main/java/hudson/model/Items.java @@ -208,7 +208,7 @@ public static TopLevelItemDescriptor getDescriptor(String fqcn) { public static String toNameList(Collection items) { StringBuilder buf = new StringBuilder(); for (Item item : items) { - if (buf.length() > 0) + if (!buf.isEmpty()) buf.append(", "); buf.append(item.getFullName()); } diff --git a/core/src/main/java/hudson/model/Job.java b/core/src/main/java/hudson/model/Job.java index 92f1d374fb08..4bd28ff2e325 100644 --- a/core/src/main/java/hudson/model/Job.java +++ b/core/src/main/java/hudson/model/Job.java @@ -266,8 +266,7 @@ public void onCopied(Item src, Item item) { // If any of the other ItemListeners modify the job, they effect // a save, which will clear the holdOffBuildUntilUserSave and // causing a regression of JENKINS-2494 - if (item instanceof Job) { - Job job = (Job) item; + if (item instanceof Job job) { synchronized (job) { job.holdOffBuildUntilUserSave = false; } @@ -1110,8 +1109,7 @@ class FeedItem { List entries = new ArrayList<>(); String scmDisplayName = ""; - if (this instanceof SCMTriggerItem) { - SCMTriggerItem scmItem = (SCMTriggerItem) this; + if (this instanceof SCMTriggerItem scmItem) { List scmNames = new ArrayList<>(); for (SCM s : scmItem.getSCMs()) { scmNames.add(s.getDescriptor().getDisplayName()); diff --git a/core/src/main/java/hudson/model/Label.java b/core/src/main/java/hudson/model/Label.java index 94d8b9683ed7..88661c6df690 100644 --- a/core/src/main/java/hudson/model/Label.java +++ b/core/src/main/java/hudson/model/Label.java @@ -591,7 +591,7 @@ public Object unmarshal(HierarchicalStreamReader reader, final UnmarshallingCont public static Set parse(@CheckForNull String labels) { final Set r = new TreeSet<>(); labels = fixNull(labels); - if (labels.length() > 0) { + if (!labels.isEmpty()) { Jenkins j = Jenkins.get(); LabelAtom labelAtom = j.tryGetLabelAtom(labels); if (labelAtom == null) { diff --git a/core/src/main/java/hudson/model/ListView.java b/core/src/main/java/hudson/model/ListView.java index 77852e994ece..d8f6a8d48bcb 100644 --- a/core/src/main/java/hudson/model/ListView.java +++ b/core/src/main/java/hudson/model/ListView.java @@ -359,7 +359,7 @@ public boolean isAddToCurrentView() { private boolean needToAddToCurrentView(StaplerRequest req) throws ServletException { String json = req.getParameter("json"); - if (json != null && json.length() > 0) { + if (json != null && !json.isEmpty()) { // Submitted via UI JSONObject form = req.getSubmittedForm(); return form.has("addToCurrentView") && form.getBoolean("addToCurrentView"); diff --git a/core/src/main/java/hudson/model/MyViewsProperty.java b/core/src/main/java/hudson/model/MyViewsProperty.java index 9d7b8b651d1c..71809d788eae 100644 --- a/core/src/main/java/hudson/model/MyViewsProperty.java +++ b/core/src/main/java/hudson/model/MyViewsProperty.java @@ -29,6 +29,7 @@ import hudson.Extension; import hudson.Util; import hudson.model.Descriptor.FormException; +import hudson.model.userproperty.UserPropertyCategory; import hudson.security.ACL; import hudson.util.FormValidation; import hudson.views.MyViewsTabBar; @@ -246,6 +247,11 @@ public String getDisplayName() { public UserProperty newInstance(User user) { return new MyViewsProperty(); } + + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Preferences.class); + } } @Override diff --git a/core/src/main/java/hudson/model/PaneStatusProperties.java b/core/src/main/java/hudson/model/PaneStatusProperties.java index 29a460349440..4807020ca714 100644 --- a/core/src/main/java/hudson/model/PaneStatusProperties.java +++ b/core/src/main/java/hudson/model/PaneStatusProperties.java @@ -2,7 +2,9 @@ import static java.lang.String.format; +import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; +import hudson.model.userproperty.UserPropertyCategory; import hudson.util.PersistedList; import java.io.IOException; import javax.servlet.http.HttpSession; @@ -56,6 +58,10 @@ public boolean isEnabled() { return false; } + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Invisible.class); + } } private static class PaneStatusPropertiesSessionFallback extends PaneStatusProperties { diff --git a/core/src/main/java/hudson/model/Queue.java b/core/src/main/java/hudson/model/Queue.java index d489f042100d..0d299fb9426d 100644 --- a/core/src/main/java/hudson/model/Queue.java +++ b/core/src/main/java/hudson/model/Queue.java @@ -130,6 +130,7 @@ import org.kohsuke.stapler.HttpResponse; import org.kohsuke.stapler.HttpResponses; import org.kohsuke.stapler.QueryParameter; +import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.export.Exported; import org.kohsuke.stapler.export.ExportedBean; import org.kohsuke.stapler.interceptor.RequirePOST; @@ -2414,6 +2415,10 @@ public Api getApi() throws AccessDeniedException { } } + public HttpResponse doIndex(StaplerRequest req) { + return HttpResponses.text("Queue item exists. For details check, for example, " + req.getRequestURI() + "api/json?tree=cancelled,executable[url]"); + } + protected Object readResolve() { this.future = new FutureImpl(task); return this; diff --git a/core/src/main/java/hudson/model/Run.java b/core/src/main/java/hudson/model/Run.java index 324a5eff3cb9..33658252b922 100644 --- a/core/src/main/java/hudson/model/Run.java +++ b/core/src/main/java/hudson/model/Run.java @@ -1341,7 +1341,7 @@ public void computeDisplayName() { private String combineLast(String[] token, int n) { StringBuilder buf = new StringBuilder(); for (int i = Math.max(0, token.length - n); i < token.length; i++) { - if (buf.length() > 0) buf.append('/'); + if (!buf.isEmpty()) buf.append('/'); buf.append(token[i]); } return buf.toString(); @@ -2286,7 +2286,7 @@ public void doBuildTimestamp(StaplerRequest req, StaplerResponse rsp, @QueryPara public void doConsoleText(StaplerRequest req, StaplerResponse rsp) throws IOException { rsp.setContentType("text/plain;charset=UTF-8"); try (InputStream input = getLogInputStream(); - OutputStream os = rsp.getCompressedOutputStream(req); + OutputStream os = rsp.getOutputStream(); PlainTextConsoleOutputStream out = new PlainTextConsoleOutputStream(os)) { IOUtils.copy(input, out); } diff --git a/core/src/main/java/hudson/model/TimeZoneProperty.java b/core/src/main/java/hudson/model/TimeZoneProperty.java index bdf39c58527e..2675448dad80 100644 --- a/core/src/main/java/hudson/model/TimeZoneProperty.java +++ b/core/src/main/java/hudson/model/TimeZoneProperty.java @@ -4,6 +4,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import hudson.Util; +import hudson.model.userproperty.UserPropertyCategory; import hudson.util.FormValidation; import hudson.util.ListBoxModel; import hudson.util.ListBoxModel.Option; @@ -106,6 +107,10 @@ public FormValidation doCheckTimeZoneName(@QueryParameter String timeZoneName) { } } + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Account.class); + } } @CheckForNull diff --git a/core/src/main/java/hudson/model/TopLevelItemDescriptor.java b/core/src/main/java/hudson/model/TopLevelItemDescriptor.java index 16aa01807ff8..d2ebe3065349 100644 --- a/core/src/main/java/hudson/model/TopLevelItemDescriptor.java +++ b/core/src/main/java/hudson/model/TopLevelItemDescriptor.java @@ -239,7 +239,7 @@ public String getIconClassName() { // this one is easy... too easy... also will never happen return IconSet.toNormalizedIconNameClass(path); } - if (Jenkins.RESOURCE_PATH.length() > 0 && path.startsWith(Jenkins.RESOURCE_PATH)) { + if (!Jenkins.RESOURCE_PATH.isEmpty() && path.startsWith(Jenkins.RESOURCE_PATH)) { // will to live falling path = path.substring(Jenkins.RESOURCE_PATH.length()); } diff --git a/core/src/main/java/hudson/model/UpdateCenter.java b/core/src/main/java/hudson/model/UpdateCenter.java index 56fd6e77c988..218cbf6b96a4 100644 --- a/core/src/main/java/hudson/model/UpdateCenter.java +++ b/core/src/main/java/hudson/model/UpdateCenter.java @@ -390,7 +390,7 @@ public Badge getBadge() { if (size > 0) { StringBuilder tooltip = new StringBuilder(); Badge.Severity severity = Badge.Severity.WARNING; - int securityFixSize = (int) plugins.stream().filter(plugin -> plugin.fixesSecurityVulnerabilities()).count(); + int securityFixSize = (int) plugins.stream().filter(Plugin::fixesSecurityVulnerabilities).count(); int incompatibleSize = (int) plugins.stream().filter(plugin -> !plugin.isCompatibleWithInstalledVersion()).count(); if (size > 1) { tooltip.append(jenkins.management.Messages.PluginsLink_updatesAvailable(size)); @@ -1322,6 +1322,10 @@ public File download(DownloadJob job, URL src) throws IOException { sha512 != null ? new DigestOutputStream(_out, sha512) : _out, sha256) : _out, sha1) : _out; InputStream in = con.getInputStream(); CountingInputStream cin = new CountingInputStream(in)) { + if (LOGGER.isLoggable(Level.FINE)) { + var sourceUrlString = getSourceUrl(src, con); + LOGGER.fine(() -> "Downloading " + job.getName() + " from " + sourceUrlString); + } while ((len = cin.read(buf)) >= 0) { out.write(buf, 0, len); final int count = cin.getCount(); @@ -1358,15 +1362,22 @@ public File download(DownloadJob job, URL src) throws IOException { return tmp; } catch (IOException e) { // assist troubleshooting in case of e.g. "too many redirects" by printing actual URL - String extraMessage = ""; - if (con != null && con.getURL() != null && !src.toString().equals(con.getURL().toString())) { - // Two URLs are considered equal if different hosts resolve to same IP. Prefer to log in case of string inequality, - // because who knows how the server responds to different host name in the request header? - // Also, since it involved name resolution, it'd be an expensive operation. - extraMessage = " (redirected to: " + con.getURL() + ")"; + throw new IOException("Failed to download from " + getSourceUrl(src, con), e); + } + } + + private static String getSourceUrl(@NonNull URL src, @CheckForNull URLConnection connection) { + var sourceUrlString = src.toExternalForm(); + if (connection != null) { + var connectionURL = connection.getURL(); + if (connectionURL != null) { + var finalUrlString = connectionURL.toExternalForm(); + if (!sourceUrlString.equals(finalUrlString)) { + return sourceUrlString + " → " + finalUrlString; + } } - throw new IOException("Failed to download from " + src + extraMessage, e); } + return sourceUrlString; } /** diff --git a/core/src/main/java/hudson/model/UpdateSite.java b/core/src/main/java/hudson/model/UpdateSite.java index 7488a9c85b57..8a38ef2d470b 100644 --- a/core/src/main/java/hudson/model/UpdateSite.java +++ b/core/src/main/java/hudson/model/UpdateSite.java @@ -192,7 +192,7 @@ public long getDataTimestamp() { @Deprecated public @CheckForNull Future updateDirectly(final boolean signatureCheck) { if (! getDataFile().exists() || isDue()) { - return Jenkins.get().getUpdateCenter().updateService.submit(new Callable() { + return Jenkins.get().getUpdateCenter().updateService.submit(new Callable<>() { @Override public FormValidation call() throws Exception { return updateDirectlyNow(signatureCheck); } diff --git a/core/src/main/java/hudson/model/User.java b/core/src/main/java/hudson/model/User.java index a242385cb11a..792622eb3c54 100644 --- a/core/src/main/java/hudson/model/User.java +++ b/core/src/main/java/hudson/model/User.java @@ -39,13 +39,11 @@ import hudson.XmlFile; import hudson.init.InitMilestone; import hudson.init.Initializer; -import hudson.model.Descriptor.FormException; import hudson.model.listeners.SaveableListener; import hudson.security.ACL; import hudson.security.AccessControlled; import hudson.security.SecurityRealm; import hudson.security.UserMayOrMayNotExistException2; -import hudson.util.FormApply; import hudson.util.FormValidation; import hudson.util.RunList; import hudson.util.XStream2; @@ -77,7 +75,6 @@ import jenkins.security.LastGrantedAuthoritiesProperty; import jenkins.security.UserDetailsCache; import jenkins.util.SystemProperties; -import net.sf.json.JSONObject; import org.jenkinsci.Symbol; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -87,7 +84,6 @@ import org.kohsuke.stapler.export.Exported; import org.kohsuke.stapler.export.ExportedBean; import org.kohsuke.stapler.interceptor.RequirePOST; -import org.kohsuke.stapler.verb.POST; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -342,6 +338,29 @@ public synchronized void addProperty(@NonNull UserProperty p) throws IOException save(); } + /** + * Expand {@link #addProperty(UserProperty)} for multiple properties to be done at once. + * Expected to be used by the categorized configuration pages to update part of the properties. + * The properties not included in the list will be let untouched. + * It will call the {@link UserProperty#setUser(User)} method and at the end, {@link #save()} once. + * + * @since 2.468 + */ + public synchronized void addProperties(@NonNull List multipleProperties) throws IOException { + List newProperties = new ArrayList<>(this.properties); + for (UserProperty property : multipleProperties) { + UserProperty oldProp = getProperty(property.getClass()); + if (oldProp != null) { + newProperties.remove(oldProp); + } + newProperties.add(property); + property.setUser(this); + } + + this.properties = newProperties; + this.save(); + } + /** * List of all {@link UserProperty}s exposed primarily for the remoting API. */ @@ -859,48 +878,6 @@ public Api getApi() { return new Api(this); } - /** - * Accepts submission from the configuration page. - */ - @POST - public void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException { - checkPermission(Jenkins.ADMINISTER); - - JSONObject json = req.getSubmittedForm(); - String oldFullName = this.fullName; - fullName = json.getString("fullName"); - description = json.getString("description"); - - List props = new ArrayList<>(); - int i = 0; - for (UserPropertyDescriptor d : UserProperty.all()) { - UserProperty p = getProperty(d.clazz); - - JSONObject o = json.optJSONObject("userProperty" + i++); - if (o != null) { - if (p != null) { - p = p.reconfigure(req, o); - } else { - p = d.newInstance(req, o); - } - } - - if (p != null) { - p.setUser(this); - props.add(p); - } - } - this.properties = props; - - save(); - - if (oldFullName != null && !oldFullName.equals(this.fullName)) { - UserDetailsCache.get().invalidate(oldFullName); - } - - FormApply.success(".").generateResponse(req, rsp, this); - } - /** * Deletes this user from Hudson. */ diff --git a/core/src/main/java/hudson/model/UserProperty.java b/core/src/main/java/hudson/model/UserProperty.java index a9b9dbae7acd..a6ebeb738b23 100644 --- a/core/src/main/java/hudson/model/UserProperty.java +++ b/core/src/main/java/hudson/model/UserProperty.java @@ -24,9 +24,13 @@ package hudson.model; +import edu.umd.cs.findbugs.annotations.NonNull; import hudson.DescriptorExtensionList; import hudson.ExtensionPoint; import hudson.model.Descriptor.FormException; +import hudson.model.userproperty.UserPropertyCategory; +import java.util.ArrayList; +import java.util.List; import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.kohsuke.stapler.StaplerRequest; @@ -58,6 +62,10 @@ public abstract class UserProperty implements ReconfigurableDescribable all( return Jenkins.get().getDescriptorList(UserProperty.class); } + /** + * Returns all the registered {@link UserPropertyCategory} descriptors for a given category. + * + * @since 2.468 + */ + public static List allByCategoryClass(@NonNull Class categoryClass) { + DescriptorExtensionList all = all(); + + List onlyForTheCategory = new ArrayList<>(all.size()); + for (UserPropertyDescriptor descriptor : all) { + if (descriptor.getUserPropertyCategory().getClass().equals(categoryClass)) { + onlyForTheCategory.add(descriptor); + } + } + + return onlyForTheCategory; + } + @Override public UserProperty reconfigure(StaplerRequest req, JSONObject form) throws FormException { return form == null ? null : getDescriptor().newInstance(req, form); diff --git a/core/src/main/java/hudson/model/UserPropertyDescriptor.java b/core/src/main/java/hudson/model/UserPropertyDescriptor.java index 22e05ea59aff..66762bf3c716 100644 --- a/core/src/main/java/hudson/model/UserPropertyDescriptor.java +++ b/core/src/main/java/hudson/model/UserPropertyDescriptor.java @@ -24,6 +24,12 @@ package hudson.model; +import edu.umd.cs.findbugs.annotations.CheckForNull; +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.model.userproperty.UserPropertyCategory; +import java.util.Optional; +import org.jenkinsci.Symbol; + /** * {@link Descriptor} for {@link UserProperty}. * @@ -73,4 +79,51 @@ protected UserPropertyDescriptor() { public boolean isEnabled() { return true; } + + /** + * Define the category for this user property descriptor. + * + * @return never null, always the same value for a given instance of {@link Descriptor}. + * + * @since 2.468 + */ + public @NonNull UserPropertyCategory getUserPropertyCategory() { + // As this method is expected to be overloaded by subclasses + // the logic here is just done to support plugins with older core version + String categoryAsString = this.getUserPropertyCategoryAsString(); + if (categoryAsString != null) { + Optional firstIfFound = UserPropertyCategory.all().stream() + .filter(cat -> { + Symbol symbolAnnotation = cat.getClass().getAnnotation(Symbol.class); + if (symbolAnnotation != null) { + for (String symbolValue : symbolAnnotation.value()) { + if (symbolValue.equalsIgnoreCase(categoryAsString)) { + return true; + } + } + } + return false; + }) + .findFirst(); + if (firstIfFound.isPresent()) { + return firstIfFound.get(); + } + } + return UserPropertyCategory.get(UserPropertyCategory.Unclassified.class); + } + + /** + * Method proposed to prevent plugins to rely on too recent core version + * while keeping the possibility to use the categories. + * + * @deprecated This should only be used when the core requirement is below the version this method was added + * + * @return String name corresponding to the symbol of {@link #getUserPropertyCategory()} + * + * @since 2.468 + */ + @Deprecated + protected @CheckForNull String getUserPropertyCategoryAsString() { + return null; + } } diff --git a/core/src/main/java/hudson/model/View.java b/core/src/main/java/hudson/model/View.java index e3775143730a..7b1bd98eb9ee 100644 --- a/core/src/main/java/hudson/model/View.java +++ b/core/src/main/java/hudson/model/View.java @@ -510,8 +510,7 @@ private boolean filterQueueItemTest(Queue.Item item, Collection vi } } // Check root project for sub-job projects (e.g. matrix jobs). - if (item.task instanceof AbstractProject) { - AbstractProject project = (AbstractProject) item.task; + if (item.task instanceof AbstractProject project) { return viewItems.contains(project.getRootProject()); } return false; @@ -855,8 +854,7 @@ public BuildTimelineWidget getTimeline() { public void doRssLatest(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { List lastBuilds = new ArrayList<>(); for (TopLevelItem item : getItems()) { - if (item instanceof Job) { - Job job = (Job) item; + if (item instanceof Job job) { Run lb = job.getLastBuild(); if (lb != null) lastBuilds.add(lb); } diff --git a/core/src/main/java/hudson/model/listeners/ItemListener.java b/core/src/main/java/hudson/model/listeners/ItemListener.java index aef431c3207b..fe09a9c56373 100644 --- a/core/src/main/java/hudson/model/listeners/ItemListener.java +++ b/core/src/main/java/hudson/model/listeners/ItemListener.java @@ -35,6 +35,8 @@ import java.util.logging.Level; import java.util.logging.Logger; import jenkins.util.Listeners; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; /** * Receives notifications about CRUD operations of {@link Item}. @@ -94,6 +96,16 @@ public void onCopied(Item src, Item item) { public void onLoaded() { } + /** + * Called before an item is deleted, providing the ability to veto the deletion operation before it starts. + * @param item the item being deleted + * @throws Failure to veto the operation. + * @throws InterruptedException If a blocking condition was interrupted, also vetoing the operation. + * @since TODO + */ + public void onCheckDelete(Item item) throws Failure, InterruptedException { + } + /** * Called right before a job is going to be deleted. * @@ -205,6 +217,19 @@ public static void fireOnUpdated(final Item item) { Listeners.notify(ItemListener.class, false, l -> l.onUpdated(item)); } + @Restricted(NoExternalUse.class) + public static void checkBeforeDelete(Item item) throws Failure, InterruptedException { + for (ItemListener l : all()) { + try { + l.onCheckDelete(item); + } catch (Failure e) { + throw e; + } catch (RuntimeException x) { + LOGGER.log(Level.WARNING, "failed to send event to listener of " + l.getClass(), x); + } + } + } + /** @since 1.548 */ public static void fireOnDeleted(final Item item) { Listeners.notify(ItemListener.class, false, l -> l.onDeleted(item)); diff --git a/core/src/main/java/hudson/model/queue/MappingWorksheet.java b/core/src/main/java/hudson/model/queue/MappingWorksheet.java index 9dbeaa3816f4..8150dd1bc132 100644 --- a/core/src/main/java/hudson/model/queue/MappingWorksheet.java +++ b/core/src/main/java/hudson/model/queue/MappingWorksheet.java @@ -190,7 +190,9 @@ public class WorkChunk extends ReadOnlyList { * If the previous execution of this task run on a certain node * and this task prefers to run on the same node, return that. * Otherwise null. + * @deprecated Unused. */ + @Deprecated public final ExecutorChunk lastBuiltOn; @@ -200,6 +202,7 @@ private WorkChunk(List base, int index) { this.index = index; this.assignedLabel = getAssignedLabel(base.get(0)); + @SuppressWarnings("deprecation") Node lbo = base.get(0).getLastBuiltOn(); for (ExecutorChunk ec : executors) { if (ec.node == lbo) { diff --git a/core/src/main/java/hudson/model/queue/QueueTaskFilter.java b/core/src/main/java/hudson/model/queue/QueueTaskFilter.java index e2a113dfaa59..a36c5ca7c753 100644 --- a/core/src/main/java/hudson/model/queue/QueueTaskFilter.java +++ b/core/src/main/java/hudson/model/queue/QueueTaskFilter.java @@ -52,6 +52,7 @@ public Label getAssignedLabel() { return base.getAssignedLabel(); } + @Deprecated @Override public Node getLastBuiltOn() { return base.getLastBuiltOn(); diff --git a/core/src/main/java/hudson/model/queue/SubTask.java b/core/src/main/java/hudson/model/queue/SubTask.java index f8b7dd435088..0690d074617c 100644 --- a/core/src/main/java/hudson/model/queue/SubTask.java +++ b/core/src/main/java/hudson/model/queue/SubTask.java @@ -62,7 +62,9 @@ default Label getAssignedLabel() { * and this task prefers to run on the same node, return that. * Otherwise null. * @return by default, null + * @deprecated Unused. */ + @Deprecated default Node getLastBuiltOn() { return null; } diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategory.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategory.java new file mode 100644 index 000000000000..5d5467b6eed4 --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategory.java @@ -0,0 +1,204 @@ +/* + * The MIT License + * + * Copyright (c) 2022, 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 hudson.model.userproperty; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import hudson.ExtensionList; +import hudson.ExtensionPoint; +import hudson.model.ModelObject; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.DoNotUse; + +/** + * Grouping of related {@link UserProperty}s. + * + *

+ * To facilitate the separation of the user properties into multiple pages, tabs, and so on, + * {@link UserProperty}s are classified into categories (such as "security", "preferences", as well + * as the catch-all "unclassified".) Categories themselves are extensible — plugins may introduce + * its own category as well, although that should only happen if you are creating a big enough subsystem. + * + * @since 2.468 + * @see UserProperty + */ +public abstract class UserPropertyCategory implements ExtensionPoint, ModelObject { + /** + * One-line plain text message that explains what this category is about. + * This can be used in the UI to help the user pick the right category. + * + * The text should be longer than {@link #getDisplayName()} + */ + public abstract String getShortDescription(); + + /** + * Returns all the registered {@link UserPropertyCategory} descriptors. + */ + public static ExtensionList all() { + return ExtensionList.lookup(UserPropertyCategory.class); + } + + public static @NonNull T get(Class type) { + T category = all().get(type); + if (category == null) { + throw new AssertionError("Category not found. It seems the " + type + " is not annotated with @Extension and so not registered"); + } + return category; + } + + /** + * This category is used when the {@link hudson.model.UserPropertyDescriptor} has not implemented + * the {@link UserPropertyDescriptor#getUserPropertyCategory()} method + * (or the getUserPropertyCategoryAsString method for compatibility reason). + *

+ * If you do not know what to use, choose the {@link Account} instead of this one. + */ + @Extension + @Symbol("unclassified") + @Restricted(DoNotUse.class) + public static class Unclassified extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Unclassified_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Unclassified_ShortDescription(); + } + } + + /** + * User property related to account settings (e.g. timezone, email, ...). + *

+ * It could be seen as the default choice for {@link UserProperty} that are defining their category. + * Currently it has the same effect as {@link Unclassified} but the behavior could change in the future. + */ + @Extension + @Symbol("account") + public static class Account extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Account_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Account_ShortDescription(); + } + } + + /** + * Preferences related configurations (e.g. notification type, default view, ...). + */ + @Extension + @Symbol("preferences") + public static class Preferences extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Preferences_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Preferences_ShortDescription(); + } + } + + /** + * Per user feature flags (e.g. new design, ...). + */ + @Extension + @Symbol("experimental") + public static class Experimental extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Experimental_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Experimental_ShortDescription(); + } + } + + /** + * User interface related configurations (e.g. theme, language, ...). + *

+ * See also {@link jenkins.appearance.AppearanceCategory}. + */ + @Extension + @Symbol("appearance") + public static class Appearance extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Appearance_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Appearance_ShortDescription(); + } + } + + + /** + * Security related configurations (e.g. API Token, SSH keys, ...). + * With this separation, we can more easily add control on their modifications. + */ + @Extension + @Symbol("security") + public static class Security extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Security_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Security_ShortDescription(); + } + } + + /** + * For user properties that are not expected to be displayed, + * typically automatically configured by automated behavior, without direct user interaction. + */ + @Extension + @Symbol("invisible") + public static class Invisible extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Invisible_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Invisible_ShortDescription(); + } + } +} diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAccountAction.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAccountAction.java new file mode 100644 index 000000000000..822cdc6f4c99 --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAccountAction.java @@ -0,0 +1,121 @@ +/* + * The MIT License + * + * Copyright (c) 2022, 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 hudson.model.userproperty; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.DescriptorExtensionList; +import hudson.Extension; +import hudson.model.Action; +import hudson.model.Descriptor; +import hudson.model.TransientUserActionFactory; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import javax.servlet.ServletException; +import jenkins.model.Jenkins; +import jenkins.security.UserDetailsCache; +import net.sf.json.JSONObject; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.verb.POST; + +@Restricted(NoExternalUse.class) +public class UserPropertyCategoryAccountAction extends UserPropertyCategoryAction implements Action { + public UserPropertyCategoryAccountAction(@NonNull User user) { + super(user); + } + + @Override + public String getDisplayName() { + return Messages.UserPropertyCategoryAccountAction_DisplayName(); + } + + @Override + public String getIconFileName() { + return getTargetUser().hasPermission(Jenkins.ADMINISTER) ? "symbol-settings" : null; + } + + @Override + public String getUrlName() { + return "account"; + } + + public @NonNull List getMyCategoryDescriptors() { + return allByTwoCategoryClasses(UserPropertyCategory.Unclassified.class, UserPropertyCategory.Account.class); + } + + private static List allByTwoCategoryClasses( + @NonNull Class categoryClass1, + @NonNull Class categoryClass2 + ) { + DescriptorExtensionList all = UserProperty.all(); + + List filteredList = new ArrayList<>(all.size()); + for (UserPropertyDescriptor descriptor : all) { + Class currClass = descriptor.getUserPropertyCategory().getClass(); + if (currClass.equals(categoryClass1) || currClass.equals(categoryClass2)) { + filteredList.add(descriptor); + } + } + + return filteredList; + } + + @POST + public void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { + User targetUser = this.getTargetUser(); + targetUser.checkPermission(Jenkins.ADMINISTER); + + JSONObject json = req.getSubmittedForm(); + + String oldFullName = targetUser.getFullName(); + targetUser.setFullName(json.getString("fullName")); + targetUser.setDescription(json.getString("description")); + + super.doConfigSubmit(req, rsp); + + if (!oldFullName.equals(targetUser.getFullName())) { + UserDetailsCache.get().invalidate(oldFullName); + } + } + + /** + * Inject the outer class configuration page into the sidenav and the request routing of the user + */ + @Extension(ordinal = 400) + @Symbol("account") + public static class AccountActionFactory extends TransientUserActionFactory { + public Collection createFor(User target) { + return Collections.singleton(new UserPropertyCategoryAccountAction(target)); + } + } +} diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAction.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAction.java new file mode 100644 index 000000000000..caec7c1bdf88 --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAction.java @@ -0,0 +1,65 @@ +package hudson.model.userproperty; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.model.Descriptor; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import hudson.util.FormApply; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.servlet.ServletException; +import jenkins.model.Jenkins; +import net.sf.json.JSONObject; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.verb.POST; + +public abstract class UserPropertyCategoryAction { + + private final User targetUser; + + public UserPropertyCategoryAction(User targetUser) { + this.targetUser = targetUser; + } + + public @NonNull User getTargetUser() { + return targetUser; + } + + public @NonNull abstract List getMyCategoryDescriptors(); + + @POST + public void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { + this.targetUser.checkPermission(Jenkins.ADMINISTER); + + JSONObject json = req.getSubmittedForm(); + + List props = new ArrayList<>(); + List myCategoryDescriptors = getMyCategoryDescriptors(); + int i = 0; + for (UserPropertyDescriptor d : myCategoryDescriptors) { + UserProperty p = this.targetUser.getProperty(d.clazz); + + JSONObject o = json.optJSONObject("userProperty" + i++); + if (o != null) { + if (p != null) { + p = p.reconfigure(req, o); + } else { + p = d.newInstance(req, o); + } + } + + if (p != null) { + props.add(p); + } + } + this.targetUser.addProperties(props); + + this.targetUser.save(); + + // we are in /user///, going to /user// + FormApply.success("..").generateResponse(req, rsp, this); + } +} diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAppearanceAction.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAppearanceAction.java new file mode 100644 index 000000000000..88d08a8add70 --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAppearanceAction.java @@ -0,0 +1,76 @@ +/* + * The MIT License + * + * Copyright (c) 2022, 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 hudson.model.userproperty; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import hudson.model.Action; +import hudson.model.TransientUserActionFactory; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import jenkins.model.Jenkins; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class UserPropertyCategoryAppearanceAction extends UserPropertyCategoryAction implements Action { + public UserPropertyCategoryAppearanceAction(@NonNull User user) { + super(user); + } + + @Override + public String getDisplayName() { + return Messages.UserPropertyCategoryAppearanceAction_DisplayName(); + } + + @Override + public String getIconFileName() { + return getTargetUser().hasPermission(Jenkins.ADMINISTER) ? "symbol-brush-outline" : null; + } + + @Override + public String getUrlName() { + return "appearance"; + } + + public @NonNull List getMyCategoryDescriptors() { + return UserProperty.allByCategoryClass(UserPropertyCategory.Appearance.class); + } + + /** + * Inject the outer class configuration page into the sidenav and the request routing of the user + */ + @Extension(ordinal = 350) + @Symbol("appearance") + public static class AppearanceActionFactory extends TransientUserActionFactory { + public Collection createFor(User target) { + return Collections.singleton(new UserPropertyCategoryAppearanceAction(target)); + } + } +} diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryExperimentalAction.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryExperimentalAction.java new file mode 100644 index 000000000000..bb242bacad7a --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryExperimentalAction.java @@ -0,0 +1,76 @@ +/* + * The MIT License + * + * Copyright (c) 2022, 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 hudson.model.userproperty; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import hudson.model.Action; +import hudson.model.TransientUserActionFactory; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import jenkins.model.Jenkins; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class UserPropertyCategoryExperimentalAction extends UserPropertyCategoryAction implements Action { + public UserPropertyCategoryExperimentalAction(@NonNull User user) { + super(user); + } + + @Override + public String getDisplayName() { + return Messages.UserPropertyCategoryExperimentalAction_DisplayName(); + } + + @Override + public String getIconFileName() { + return getTargetUser().hasPermission(Jenkins.ADMINISTER) ? "symbol-flask" : null; + } + + @Override + public String getUrlName() { + return "experiments"; + } + + public @NonNull List getMyCategoryDescriptors() { + return UserProperty.allByCategoryClass(UserPropertyCategory.Experimental.class); + } + + /** + * Inject the outer class configuration page into the sidenav and the request routing of the user + */ + @Extension(ordinal = 100) + @Symbol("experimental") + public static class ExperimentalActionFactory extends TransientUserActionFactory { + public Collection createFor(User target) { + return Collections.singleton(new UserPropertyCategoryExperimentalAction(target)); + } + } +} diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryPreferencesAction.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryPreferencesAction.java new file mode 100644 index 000000000000..7a74b702e6c0 --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryPreferencesAction.java @@ -0,0 +1,76 @@ +/* + * The MIT License + * + * Copyright (c) 2022, 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 hudson.model.userproperty; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import hudson.model.Action; +import hudson.model.TransientUserActionFactory; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import jenkins.model.Jenkins; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class UserPropertyCategoryPreferencesAction extends UserPropertyCategoryAction implements Action { + public UserPropertyCategoryPreferencesAction(@NonNull User user) { + super(user); + } + + @Override + public String getDisplayName() { + return Messages.UserPropertyCategoryPreferencesAction_DisplayName(); + } + + @Override + public String getIconFileName() { + return getTargetUser().hasPermission(Jenkins.ADMINISTER) ? "symbol-parameters" : null; + } + + @Override + public String getUrlName() { + return "preferences"; + } + + public @NonNull List getMyCategoryDescriptors() { + return UserProperty.allByCategoryClass(UserPropertyCategory.Preferences.class); + } + + /** + * Inject the outer class configuration page into the sidenav and the request routing of the user + */ + @Extension(ordinal = 300) + @Symbol("preferences") + public static class PreferencesActionFactory extends TransientUserActionFactory { + public Collection createFor(User target) { + return Collections.singleton(new UserPropertyCategoryPreferencesAction(target)); + } + } +} diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategorySecurityAction.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategorySecurityAction.java new file mode 100644 index 000000000000..a6cb3e6ed3c4 --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategorySecurityAction.java @@ -0,0 +1,77 @@ +/* + * The MIT License + * + * Copyright (c) 2022, 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 hudson.model.userproperty; + + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import hudson.model.Action; +import hudson.model.TransientUserActionFactory; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import jenkins.model.Jenkins; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class UserPropertyCategorySecurityAction extends UserPropertyCategoryAction implements Action { + public UserPropertyCategorySecurityAction(@NonNull User user) { + super(user); + } + + @Override + public String getDisplayName() { + return Messages.UserPropertyCategorySecurityAction_DisplayName(); + } + + @Override + public String getIconFileName() { + return getTargetUser().hasPermission(Jenkins.ADMINISTER) ? "symbol-lock-closed" : null; + } + + @Override + public String getUrlName() { + return "security"; + } + + public @NonNull List getMyCategoryDescriptors() { + return UserProperty.allByCategoryClass(UserPropertyCategory.Security.class); + } + + /** + * Inject the outer class configuration page into the sidenav and the request routing of the user + */ + @Extension(ordinal = 200) + @Symbol("security") + public static class SecurityActionFactory extends TransientUserActionFactory { + public Collection createFor(User target) { + return Collections.singleton(new UserPropertyCategorySecurityAction(target)); + } + } +} diff --git a/core/src/main/java/hudson/scm/ChangeLogSet.java b/core/src/main/java/hudson/scm/ChangeLogSet.java index a0c4a4c9cd79..f9f29720355f 100644 --- a/core/src/main/java/hudson/scm/ChangeLogSet.java +++ b/core/src/main/java/hudson/scm/ChangeLogSet.java @@ -238,7 +238,7 @@ public Collection getAffectedFiles() { ChangeLogSet parent = getParent(); if (null != parent) { String kind = parent.getKind(); - if (null != kind && kind.trim().length() > 0) scm = kind; + if (null != kind && !kind.trim().isEmpty()) scm = kind; } throw new UnsupportedOperationException("getAffectedFiles() is not implemented by " + scm); } diff --git a/core/src/main/java/hudson/scm/browsers/QueryBuilder.java b/core/src/main/java/hudson/scm/browsers/QueryBuilder.java index 06d933aa7ef3..72e6ebc0d557 100644 --- a/core/src/main/java/hudson/scm/browsers/QueryBuilder.java +++ b/core/src/main/java/hudson/scm/browsers/QueryBuilder.java @@ -38,7 +38,7 @@ public QueryBuilder(String s) { public QueryBuilder add(String s) { if (s == null) return this; // nothing to add - if (buf.length() == 0) buf.append('?'); + if (buf.isEmpty()) buf.append('?'); else buf.append('&'); buf.append(s); return this; diff --git a/core/src/main/java/hudson/search/ParsedQuickSilver.java b/core/src/main/java/hudson/search/ParsedQuickSilver.java index dc214892ac00..879f9c080d16 100644 --- a/core/src/main/java/hudson/search/ParsedQuickSilver.java +++ b/core/src/main/java/hudson/search/ParsedQuickSilver.java @@ -85,7 +85,7 @@ private ParsedQuickSilver(Class clazz) { private String splitName(String url) { StringBuilder buf = new StringBuilder(url.length() + 5); for (String token : url.split("(?<=[a-z])(?=[A-Z])")) { - if (buf.length() > 0) buf.append(' '); + if (!buf.isEmpty()) buf.append(' '); buf.append(Introspector.decapitalize(token)); } return buf.toString(); diff --git a/core/src/main/java/hudson/search/SuggestedItem.java b/core/src/main/java/hudson/search/SuggestedItem.java index 86dbc36b5fe3..9ba455270e58 100644 --- a/core/src/main/java/hudson/search/SuggestedItem.java +++ b/core/src/main/java/hudson/search/SuggestedItem.java @@ -111,7 +111,7 @@ private void getUrl(StringBuilder buf) { buf.setLength(0); buf.append(f); } else { - if (buf.length() == 0 || buf.charAt(buf.length() - 1) != '/') + if (buf.isEmpty() || buf.charAt(buf.length() - 1) != '/') buf.append('/'); buf.append(f); } diff --git a/core/src/main/java/hudson/search/UserSearchProperty.java b/core/src/main/java/hudson/search/UserSearchProperty.java index 7e9836944c0b..a3515dd08874 100644 --- a/core/src/main/java/hudson/search/UserSearchProperty.java +++ b/core/src/main/java/hudson/search/UserSearchProperty.java @@ -5,6 +5,7 @@ import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; +import hudson.model.userproperty.UserPropertyCategory; import net.sf.json.JSONObject; import org.jenkinsci.Symbol; import org.kohsuke.stapler.StaplerRequest; @@ -54,6 +55,10 @@ public UserProperty newInstance(StaplerRequest req, JSONObject formData) throws return new UserSearchProperty(formData.optBoolean("insensitiveSearch")); } + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Preferences.class); + } } } diff --git a/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java b/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java index 6305a69a6abb..bd122244c7e2 100644 --- a/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java +++ b/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java @@ -39,6 +39,7 @@ import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; +import hudson.model.userproperty.UserPropertyCategory; import hudson.security.FederatedLoginService.FederatedIdentity; import hudson.security.captcha.CaptchaSupport; import hudson.util.FormValidation; @@ -449,7 +450,7 @@ private SignupInfo validateAccountCreationForm(StaplerRequest req, boolean valid si.errors.put("password1", Messages.HudsonPrivateSecurityRealm_CreateAccount_PasswordNotMatch()); } - if (!(si.password1 != null && si.password1.length() != 0)) { + if (!(si.password1 != null && !si.password1.isEmpty())) { si.errors.put("password1", Messages.HudsonPrivateSecurityRealm_CreateAccount_PasswordRequired()); } @@ -801,7 +802,6 @@ public boolean equals(Object o) { public int hashCode() { return getUsername().hashCode(); } - } public static class ConverterImpl extends XStream2.PassthruConverter

{ @@ -884,6 +884,11 @@ public boolean isEnabled() { public UserProperty newInstance(User user) { return null; } + + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Security.class); + } } } diff --git a/core/src/main/java/hudson/security/SecurityRealm.java b/core/src/main/java/hudson/security/SecurityRealm.java index 525368f65692..b969a57eb781 100644 --- a/core/src/main/java/hudson/security/SecurityRealm.java +++ b/core/src/main/java/hudson/security/SecurityRealm.java @@ -326,7 +326,7 @@ public void doLogout(StaplerRequest req, StaplerResponse rsp) throws IOException Authentication auth = SecurityContextHolder.getContext().getAuthentication(); SecurityContextHolder.clearContext(); - String contextPath = req.getContextPath().length() > 0 ? req.getContextPath() : "/"; + String contextPath = !req.getContextPath().isEmpty() ? req.getContextPath() : "/"; resetRememberMeCookie(req, rsp, contextPath); clearStaleSessionCookies(req, rsp, contextPath); diff --git a/core/src/main/java/hudson/security/csrf/CrumbFilter.java b/core/src/main/java/hudson/security/csrf/CrumbFilter.java index 03e17a0fd894..8b4b558938e7 100644 --- a/core/src/main/java/hudson/security/csrf/CrumbFilter.java +++ b/core/src/main/java/hudson/security/csrf/CrumbFilter.java @@ -105,7 +105,7 @@ private static String canonicalPath(String path) { buf.append(token); } // translation: if (path.endsWith("/") && !buf.endsWith("/")) - if (path.endsWith("/") && (buf.length() == 0 || buf.charAt(buf.length() - 1) != '/')) + if (path.endsWith("/") && (buf.isEmpty() || buf.charAt(buf.length() - 1) != '/')) buf.append('/'); return buf.toString(); } diff --git a/core/src/main/java/hudson/security/csrf/CrumbIssuer.java b/core/src/main/java/hudson/security/csrf/CrumbIssuer.java index 384f0a765ddd..cd0c51b03fb0 100644 --- a/core/src/main/java/hudson/security/csrf/CrumbIssuer.java +++ b/core/src/main/java/hudson/security/csrf/CrumbIssuer.java @@ -78,7 +78,7 @@ public String getCrumb(ServletRequest request) { if (crumb == null) { crumb = issueCrumb(request, getDescriptor().getCrumbSalt()); if (request != null) { - if (crumb != null && crumb.length() > 0) { + if (crumb != null && !crumb.isEmpty()) { request.setAttribute(CRUMB_ATTRIBUTE, crumb); } else { request.removeAttribute(CRUMB_ATTRIBUTE); @@ -204,7 +204,7 @@ public static class RestrictedApi extends Api { text = null; } if (text != null) { - try (OutputStream o = rsp.getCompressedOutputStream(req)) { + try (OutputStream o = rsp.getOutputStream()) { rsp.setContentType("text/plain;charset=UTF-8"); o.write(text.getBytes(StandardCharsets.UTF_8)); } diff --git a/core/src/main/java/hudson/slaves/CloudRetentionStrategy.java b/core/src/main/java/hudson/slaves/CloudRetentionStrategy.java index ec0142dd4768..e4601a2fad31 100644 --- a/core/src/main/java/hudson/slaves/CloudRetentionStrategy.java +++ b/core/src/main/java/hudson/slaves/CloudRetentionStrategy.java @@ -64,7 +64,7 @@ public long check(final AbstractCloudComputer c) { } } } - return 1; + return 0; } /** diff --git a/core/src/main/java/hudson/slaves/CloudSlaveRetentionStrategy.java b/core/src/main/java/hudson/slaves/CloudSlaveRetentionStrategy.java index 4e1b376caffe..a8dfeba1b20a 100644 --- a/core/src/main/java/hudson/slaves/CloudSlaveRetentionStrategy.java +++ b/core/src/main/java/hudson/slaves/CloudSlaveRetentionStrategy.java @@ -37,7 +37,7 @@ public long check(T c) { } } } - return checkCycle(); + return TimeUnit.MILLISECONDS.toMinutes(checkCycle()); } /** diff --git a/core/src/main/java/hudson/slaves/ComputerRetentionWork.java b/core/src/main/java/hudson/slaves/ComputerRetentionWork.java index ddee61115a03..42256855117d 100644 --- a/core/src/main/java/hudson/slaves/ComputerRetentionWork.java +++ b/core/src/main/java/hudson/slaves/ComputerRetentionWork.java @@ -25,13 +25,15 @@ package hudson.slaves; import hudson.Extension; +import hudson.ExtensionList; +import hudson.model.AperiodicWork; import hudson.model.Computer; import hudson.model.Node; -import hudson.model.PeriodicWork; import hudson.model.Queue; import java.util.Map; import java.util.WeakHashMap; import java.util.concurrent.TimeUnit; +import jenkins.model.GlobalComputerRetentionCheckIntervalConfiguration; import jenkins.model.Jenkins; import org.jenkinsci.Symbol; @@ -42,7 +44,7 @@ * @author Stephen Connolly */ @Extension @Symbol("computerRetention") -public class ComputerRetentionWork extends PeriodicWork { +public class ComputerRetentionWork extends AperiodicWork { /** * Use weak hash map to avoid leaking {@link Computer}. @@ -51,12 +53,18 @@ public class ComputerRetentionWork extends PeriodicWork { @Override public long getRecurrencePeriod() { - return MIN; + return ExtensionList.lookupSingleton(GlobalComputerRetentionCheckIntervalConfiguration.class).getComputerRetentionCheckInterval() * 1000L; + } + + @Override + public AperiodicWork getNewInstance() { + // ComputerRetentionWork is a singleton. + return this; } @SuppressWarnings("unchecked") @Override - protected void doRun() { + protected void doAperiodicRun() { final long startRun = System.currentTimeMillis(); for (final Computer c : Jenkins.get().getComputers()) { Queue.withLock(new Runnable() { @@ -67,8 +75,7 @@ public void run() { return; if (!nextCheck.containsKey(c) || startRun > nextCheck.get(c)) { // at the moment I don't trust strategies to wait more than 60 minutes - // strategies need to wait at least one minute - final long waitInMins = Math.max(1, Math.min(60, c.getRetentionStrategy().check(c))); + final long waitInMins = Math.max(0, Math.min(60, c.getRetentionStrategy().check(c))); nextCheck.put(c, startRun + TimeUnit.MINUTES.toMillis(waitInMins)); } } diff --git a/core/src/main/java/hudson/slaves/RetentionStrategy.java b/core/src/main/java/hudson/slaves/RetentionStrategy.java index e06b8e42c069..687e44d5c172 100644 --- a/core/src/main/java/hudson/slaves/RetentionStrategy.java +++ b/core/src/main/java/hudson/slaves/RetentionStrategy.java @@ -171,7 +171,7 @@ public Always() { public long check(SlaveComputer c) { if (c.isOffline() && !c.isConnecting() && c.isLaunchSupported()) c.tryReconnect(); - return 1; + return 0; } @Extension(ordinal = 100) @Symbol("always") @@ -285,7 +285,7 @@ public long check(final SlaveComputer c) { return TimeUnit.MILLISECONDS.toMinutes(TimeUnit.MINUTES.toMillis(idleDelay) - idleMilliseconds); } } - return 1; + return 0; } @Extension @Symbol("demand") diff --git a/core/src/main/java/hudson/slaves/SimpleScheduledRetentionStrategy.java b/core/src/main/java/hudson/slaves/SimpleScheduledRetentionStrategy.java index ef6e3d0c8658..ea90529b29b4 100644 --- a/core/src/main/java/hudson/slaves/SimpleScheduledRetentionStrategy.java +++ b/core/src/main/java/hudson/slaves/SimpleScheduledRetentionStrategy.java @@ -209,7 +209,7 @@ public void run() { LOGGER.log(INFO, "Disabling new jobs for computer {0} as it has finished its scheduled uptime", new Object[]{c.getName()}); - return 1; + return 0; } else if (c.isIdle() && c.isAcceptingTasks()) { Queue.withLock(new Runnable() { @Override @@ -243,7 +243,7 @@ public void run() { } } } - return 1; + return 0; } private synchronized boolean isOnlineScheduled() { diff --git a/core/src/main/java/hudson/tasks/Fingerprinter.java b/core/src/main/java/hudson/tasks/Fingerprinter.java index 3be7631bb1f0..4d843b27b003 100644 --- a/core/src/main/java/hudson/tasks/Fingerprinter.java +++ b/core/src/main/java/hudson/tasks/Fingerprinter.java @@ -182,7 +182,7 @@ public void perform(Run build, FilePath workspace, EnvVars environment, La Map record = new HashMap<>(); - if (targets.length() != 0) { + if (!targets.isEmpty()) { String expandedTargets = targets; if (build instanceof AbstractBuild) { // no expansion for pipelines expandedTargets = environment.expand(expandedTargets); diff --git a/core/src/main/java/hudson/tools/AbstractCommandInstaller.java b/core/src/main/java/hudson/tools/AbstractCommandInstaller.java index 46e7bc6657a2..88cbe5915cc0 100644 --- a/core/src/main/java/hudson/tools/AbstractCommandInstaller.java +++ b/core/src/main/java/hudson/tools/AbstractCommandInstaller.java @@ -90,7 +90,7 @@ public abstract static class Descriptor { public FormValidation doCheckCommand(@QueryParameter String value) { - if (value.length() > 0) { + if (!value.isEmpty()) { return FormValidation.ok(); } else { return FormValidation.error(Messages.CommandInstaller_no_command()); @@ -98,7 +98,7 @@ public FormValidation doCheckCommand(@QueryParameter String value) { } public FormValidation doCheckToolHome(@QueryParameter String value) { - if (value.length() > 0) { + if (!value.isEmpty()) { return FormValidation.ok(); } else { return FormValidation.error(Messages.CommandInstaller_no_toolHome()); diff --git a/core/src/main/java/hudson/tools/InstallerTranslator.java b/core/src/main/java/hudson/tools/InstallerTranslator.java index 35db845dd2e6..45e24cadf60d 100644 --- a/core/src/main/java/hudson/tools/InstallerTranslator.java +++ b/core/src/main/java/hudson/tools/InstallerTranslator.java @@ -59,11 +59,8 @@ public String getToolHome(Node node, ToolInstallation tool, TaskListener log) th if (installer.appliesTo(node)) { Semaphore semaphore; synchronized (mutexByNode) { - Map mutexByTool = mutexByNode.computeIfAbsent(node, k -> new WeakHashMap<>()); - semaphore = mutexByTool.get(tool); - if (semaphore == null) { - mutexByTool.put(tool, semaphore = new Semaphore(1)); - } + Map mutexByTool = mutexByNode.computeIfAbsent(node, unused -> new WeakHashMap<>()); + semaphore = mutexByTool.computeIfAbsent(tool, unused -> new Semaphore(1)); } semaphore.acquire(); try { diff --git a/core/src/main/java/hudson/triggers/SCMTrigger.java b/core/src/main/java/hudson/triggers/SCMTrigger.java index e35a3b66af69..43fdc6bb1062 100644 --- a/core/src/main/java/hudson/triggers/SCMTrigger.java +++ b/core/src/main/java/hudson/triggers/SCMTrigger.java @@ -468,7 +468,7 @@ public String getUrlName() { */ public void doPollingLog(StaplerRequest req, StaplerResponse rsp) throws IOException { rsp.setContentType("text/plain;charset=UTF-8"); - try (OutputStream os = rsp.getCompressedOutputStream(req); + try (OutputStream os = rsp.getOutputStream(); // Prevent jelly from flushing stream so Content-Length header can be added afterwards FlushProofOutputStream out = new FlushProofOutputStream(os)) { getPollingLogText().writeLogTo(0, out); diff --git a/core/src/main/java/hudson/util/ArgumentListBuilder.java b/core/src/main/java/hudson/util/ArgumentListBuilder.java index 245f3e74a99b..9b2c7bebb594 100644 --- a/core/src/main/java/hudson/util/ArgumentListBuilder.java +++ b/core/src/main/java/hudson/util/ArgumentListBuilder.java @@ -295,7 +295,7 @@ public List toList() { public String toStringWithQuote() { StringBuilder buf = new StringBuilder(); for (String arg : args) { - if (buf.length() > 0) buf.append(' '); + if (!buf.isEmpty()) buf.append(' '); if (arg.indexOf(' ') >= 0 || arg.isEmpty()) buf.append('"').append(arg).append('"'); @@ -400,7 +400,7 @@ private static boolean startQuoting(StringBuilder buf, String arg, int atIndex) * @return true if there are any masked arguments; false otherwise */ public boolean hasMaskedArguments() { - return mask.length() > 0; + return !mask.isEmpty(); } /** @@ -437,7 +437,7 @@ public String toString() { if (mask.get(i)) arg = "******"; - if (buf.length() > 0) buf.append(' '); + if (!buf.isEmpty()) buf.append(' '); if (arg.indexOf(' ') >= 0 || arg.isEmpty()) buf.append('"').append(arg).append('"'); diff --git a/core/src/main/java/hudson/util/BootFailure.java b/core/src/main/java/hudson/util/BootFailure.java index a460ffea148e..f23cf7fa66b7 100644 --- a/core/src/main/java/hudson/util/BootFailure.java +++ b/core/src/main/java/hudson/util/BootFailure.java @@ -15,6 +15,7 @@ import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.ServletContext; +import jenkins.model.Jenkins; import jenkins.util.groovy.GroovyHookScript; import org.kohsuke.stapler.WebApp; @@ -51,6 +52,7 @@ public void publish(ServletContext context, @CheckForNull File home) { .bind("servletContext", context) .bind("attempts", loadAttempts(home)) .run(); + Jenkins.get().getLifecycle().onBootFailure(this); } /** diff --git a/core/src/main/java/hudson/util/DescribableList.java b/core/src/main/java/hudson/util/DescribableList.java index a73dac196b2c..9c62af2f191a 100644 --- a/core/src/main/java/hudson/util/DescribableList.java +++ b/core/src/main/java/hudson/util/DescribableList.java @@ -219,8 +219,7 @@ public void rebuildHetero(StaplerRequest req, JSONObject formData, Collection T act(ProcessCallable callable) throws IOException, InterruptedExc } /* - On MacOS X, there's no procfs - instead you'd do it with the sysctl - + On MacOS X, there's no procfs + instead you'd do it with sysctl + There's CLI but that doesn't seem to offer the access to per-process info - + diff --git a/core/src/main/java/hudson/util/RemotingDiagnostics.java b/core/src/main/java/hudson/util/RemotingDiagnostics.java index 1756d2933b18..06a42beee69d 100644 --- a/core/src/main/java/hudson/util/RemotingDiagnostics.java +++ b/core/src/main/java/hudson/util/RemotingDiagnostics.java @@ -217,7 +217,7 @@ public void doHeapDump(StaplerRequest req, StaplerResponse rsp) throws IOExcepti FilePath dump = obtain(); try { - dump.copyTo(rsp.getCompressedOutputStream(req)); + dump.copyTo(rsp.getOutputStream()); } finally { dump.delete(); } diff --git a/core/src/main/java/hudson/util/XStream2.java b/core/src/main/java/hudson/util/XStream2.java index cf1b5e9bcaab..774008e5e694 100644 --- a/core/src/main/java/hudson/util/XStream2.java +++ b/core/src/main/java/hudson/util/XStream2.java @@ -469,7 +469,7 @@ public Class realClass(String elementName) { */ private static final class AssociatedConverterImpl implements Converter { private final XStream xstream; - private static final ClassValue> classCache = new ClassValue>() { + private static final ClassValue> classCache = new ClassValue<>() { @Override protected Class computeValue(Class type) { return computeConverterClass(type); diff --git a/core/src/main/java/hudson/views/ListViewColumn.java b/core/src/main/java/hudson/views/ListViewColumn.java index 1796f4cc495c..91e93e2145da 100644 --- a/core/src/main/java/hudson/views/ListViewColumn.java +++ b/core/src/main/java/hudson/views/ListViewColumn.java @@ -157,8 +157,7 @@ private static List createDefaultInitialColumnList(List d : descriptors) try { - if (d instanceof ListViewColumnDescriptor) { - ListViewColumnDescriptor ld = (ListViewColumnDescriptor) d; + if (d instanceof ListViewColumnDescriptor ld) { if (!ld.shownByDefault()) { continue; // skip this } diff --git a/core/src/main/java/jenkins/agents/CloudSet.java b/core/src/main/java/jenkins/agents/CloudSet.java index addefceb83ff..163556a001d1 100644 --- a/core/src/main/java/jenkins/agents/CloudSet.java +++ b/core/src/main/java/jenkins/agents/CloudSet.java @@ -41,7 +41,6 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.logging.Level; @@ -131,7 +130,7 @@ public String getCloudUpdateCenterCategoryLabel() { @Override public ModelObjectWithContextMenu.ContextMenu doChildrenContextMenu(StaplerRequest request, StaplerResponse response) throws Exception { ModelObjectWithContextMenu.ContextMenu m = new ModelObjectWithContextMenu.ContextMenu(); - Jenkins.get().clouds.stream().forEach(c -> m.add(c)); + Jenkins.get().clouds.stream().forEach(m::add); return m; } @@ -265,7 +264,7 @@ public void doReorder(StaplerRequest req, StaplerResponse rsp) throws IOExceptio } var namesList = Arrays.asList(names); var clouds = new ArrayList<>(Jenkins.get().clouds); - Collections.sort(clouds, Comparator.comparingInt(c -> getIndexOf(namesList, c))); + clouds.sort(Comparator.comparingInt(c -> getIndexOf(namesList, c))); Jenkins.get().clouds.replaceBy(clouds); rsp.sendRedirect2("."); } diff --git a/core/src/main/java/jenkins/agents/WebSocketAgents.java b/core/src/main/java/jenkins/agents/WebSocketAgents.java index 005587c6365a..d9560f156ebd 100644 --- a/core/src/main/java/jenkins/agents/WebSocketAgents.java +++ b/core/src/main/java/jenkins/agents/WebSocketAgents.java @@ -36,6 +36,7 @@ import hudson.remoting.ChannelBuilder; import hudson.remoting.ChunkHeader; import hudson.remoting.Engine; +import hudson.slaves.SlaveComputer; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; @@ -107,7 +108,9 @@ public HttpResponse doIndex(StaplerRequest req, StaplerResponse rsp) throws IOEx Capability remoteCapability = Capability.fromASCII(remoteCapabilityStr); LOGGER.fine(() -> "received " + remoteCapability); rsp.setHeader(Capability.KEY, new Capability().toASCII()); - rsp.setHeader(Engine.REMOTING_MINIMUM_VERSION_HEADER, RemotingVersionInfo.getMinimumSupportedVersion().toString()); + if (!SlaveComputer.ALLOW_UNSUPPORTED_REMOTING_VERSIONS) { + rsp.setHeader(Engine.REMOTING_MINIMUM_VERSION_HEADER, RemotingVersionInfo.getMinimumSupportedVersion().toString()); + } rsp.setHeader(Engine.WEBSOCKET_COOKIE_HEADER, cookie); return WebSockets.upgrade(new Session(state, agent, remoteCapability)); } diff --git a/core/src/main/java/jenkins/diagnostics/URICheckEncodingMonitor.java b/core/src/main/java/jenkins/diagnostics/URICheckEncodingMonitor.java index 3563699b19b7..9fdd7bc38436 100644 --- a/core/src/main/java/jenkins/diagnostics/URICheckEncodingMonitor.java +++ b/core/src/main/java/jenkins/diagnostics/URICheckEncodingMonitor.java @@ -7,6 +7,7 @@ import hudson.model.AdministrativeMonitor; import hudson.util.FormValidation; import java.io.IOException; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.logging.Level; import java.util.logging.Logger; @@ -22,7 +23,7 @@ public class URICheckEncodingMonitor extends AdministrativeMonitor { private static final Logger LOGGER = Logger.getLogger(URICheckEncodingMonitor.class.getName()); public boolean isCheckEnabled() { - return !"ISO-8859-1".equalsIgnoreCase(System.getProperty("file.encoding")); + return !"ISO-8859-1".equalsIgnoreCase(Charset.defaultCharset().displayName()); } @Override diff --git a/core/src/main/java/jenkins/fingerprints/FileFingerprintStorage.java b/core/src/main/java/jenkins/fingerprints/FileFingerprintStorage.java index d3154e6db6a3..409788ba5706 100644 --- a/core/src/main/java/jenkins/fingerprints/FileFingerprintStorage.java +++ b/core/src/main/java/jenkins/fingerprints/FileFingerprintStorage.java @@ -101,11 +101,10 @@ public FileFingerprintStorage() {} try { Object loaded = configFile.read(); - if (!(loaded instanceof Fingerprint)) { + if (!(loaded instanceof Fingerprint f)) { throw new IOException("Unexpected Fingerprint type. Expected " + Fingerprint.class + " or subclass but got " + (loaded != null ? loaded.getClass() : "null")); } - Fingerprint f = (Fingerprint) loaded; if (f.getPersistedFacets() == null) { logger.log(Level.WARNING, "Malformed fingerprint {0}: Missing facets", configFile); Files.deleteIfExists(Util.fileToPath(file)); diff --git a/core/src/main/java/jenkins/install/InstallUtil.java b/core/src/main/java/jenkins/install/InstallUtil.java index 3d1bf24e267d..6fb37e20bf3a 100644 --- a/core/src/main/java/jenkins/install/InstallUtil.java +++ b/core/src/main/java/jenkins/install/InstallUtil.java @@ -234,7 +234,7 @@ public static void saveLastExecVersion() { if (configFile.exists()) { try { String lastVersion = XMLUtils.getValue("/hudson/version", configFile); - if (lastVersion.length() > 0) { + if (!lastVersion.isEmpty()) { LOGGER.log(Level.FINE, "discovered serialized lastVersion {0}", lastVersion); return lastVersion; } diff --git a/core/src/main/java/jenkins/management/AdministrativeMonitorsDecorator.java b/core/src/main/java/jenkins/management/AdministrativeMonitorsDecorator.java index cc1d5214e0ae..5b94090f4e3b 100644 --- a/core/src/main/java/jenkins/management/AdministrativeMonitorsDecorator.java +++ b/core/src/main/java/jenkins/management/AdministrativeMonitorsDecorator.java @@ -139,7 +139,7 @@ private Collection getAllActiveAdministrativeMonitors() { * @return the list of active monitors if we should display them, otherwise null. */ public Collection getMonitorsToDisplay() { - if (!Jenkins.get().hasPermission(Jenkins.SYSTEM_READ)) { + if (!(AdministrativeMonitor.hasPermissionToDisplay())) { return null; } @@ -150,7 +150,7 @@ public Collection getMonitorsToDisplay() { } List ancestors = req.getAncestors(); - if (ancestors == null || ancestors.size() == 0) { + if (ancestors == null || ancestors.isEmpty()) { // ??? return null; } diff --git a/core/src/main/java/jenkins/model/GlobalComputerRetentionCheckIntervalConfiguration.java b/core/src/main/java/jenkins/model/GlobalComputerRetentionCheckIntervalConfiguration.java new file mode 100644 index 000000000000..46d760fe8ee2 --- /dev/null +++ b/core/src/main/java/jenkins/model/GlobalComputerRetentionCheckIntervalConfiguration.java @@ -0,0 +1,72 @@ +package jenkins.model; + +import hudson.Extension; +import hudson.model.PersistentDescriptor; +import java.util.logging.Logger; +import net.sf.json.JSONException; +import net.sf.json.JSONObject; +import org.jenkinsci.Symbol; +import org.kohsuke.stapler.StaplerRequest; + +/** + * Configures check interval for computer retention. + * + * @author Jakob Ackermann + */ +@Extension(ordinal = 401) @Symbol("computerRetentionCheckInterval") +public class GlobalComputerRetentionCheckIntervalConfiguration extends GlobalConfiguration implements PersistentDescriptor { + /** + * For {@link hudson.slaves.ComputerRetentionWork#getRecurrencePeriod()} + */ + private int computerRetentionCheckInterval = 60; + + /** + * Gets the check interval for computer retention. + * + * @since 2.463 + */ + public int getComputerRetentionCheckInterval() { + if (computerRetentionCheckInterval <= 0) { + LOGGER.info("computerRetentionCheckInterval must be greater than zero, falling back to 60s"); + return 60; + } + if (computerRetentionCheckInterval > 60) { + LOGGER.info("computerRetentionCheckInterval is limited to 60s"); + return 60; + } + return computerRetentionCheckInterval; + } + + /** + * Updates the check interval for computer retention and restarts the check cycle. + * + * @param interval new check interval in seconds + * @throws IllegalArgumentException interval must be greater than zero + * @since 2.463 + */ + private void setComputerRetentionCheckInterval(int interval) throws IllegalArgumentException { + if (interval <= 0) { + throw new IllegalArgumentException("interval must be greater than zero"); + } + if (interval > 60) { + throw new IllegalArgumentException("interval must be below or equal 60s"); + } + computerRetentionCheckInterval = interval; + save(); + } + + @Override + public boolean configure(StaplerRequest req, JSONObject json) throws FormException { + try { + final int interval = json.getInt("computerRetentionCheckInterval"); + setComputerRetentionCheckInterval(interval); + return true; + } catch (IllegalArgumentException e) { + throw new FormException(e, "computerRetentionCheckInterval"); + } catch (JSONException e) { + throw new FormException(e.getMessage(), "computerRetentionCheckInterval"); + } + } + + private static final Logger LOGGER = Logger.getLogger(GlobalComputerRetentionCheckIntervalConfiguration.class.getName()); +} diff --git a/core/src/main/java/jenkins/model/Jenkins.java b/core/src/main/java/jenkins/model/Jenkins.java index 7fe515fddf0e..a3376f99d75e 100644 --- a/core/src/main/java/jenkins/model/Jenkins.java +++ b/core/src/main/java/jenkins/model/Jenkins.java @@ -499,7 +499,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve * STARTUP_MARKER_FILE.get(); // returns false if we are on a fresh startup. True for next startups. * } */ - private static transient FileBoolean STARTUP_MARKER_FILE; + private static FileBoolean STARTUP_MARKER_FILE; private volatile List jdks = new ArrayList<>(); @@ -2355,12 +2355,12 @@ public AdministrativeMonitor getAdministrativeMonitor(String id) { * @since 2.64 */ public List getActiveAdministrativeMonitors() { - if (!Jenkins.get().hasPermission(SYSTEM_READ)) { + if (!AdministrativeMonitor.hasPermissionToDisplay()) { return Collections.emptyList(); } return administrativeMonitors.stream().filter(m -> { try { - return Jenkins.get().hasPermission(m.getRequiredPermission()) && m.isEnabled() && m.isActivated(); + return m.hasRequiredPermission() && m.isEnabled() && m.isActivated(); } catch (Throwable x) { LOGGER.log(Level.WARNING, null, x); return false; @@ -3106,8 +3106,7 @@ public Item getItem(String pathName, ItemGroup context) { continue; } - if (ctx instanceof ItemGroup) { - ItemGroup g = (ItemGroup) ctx; + if (ctx instanceof ItemGroup g) { Item i = g.getItem(s); if (i == null || !i.hasPermission(Item.READ)) { // TODO consider DISCOVER ctx = null; // can't go up further @@ -3477,10 +3476,9 @@ private void setBuildsAndWorkspacesDir() throws IOException, InvalidBuildsDir { File d = new File(replacedValue); if (!d.isDirectory()) { // if dir does not exist (almost guaranteed) need to make sure nearest existing ancestor can be written to - d = d.getParentFile(); - while (!d.exists()) { + do { d = d.getParentFile(); - } + } while (!d.exists()); if (!d.canWrite()) { throw new InvalidBuildsDir(newBuildsDirValue + " does not exist and probably cannot be created"); } diff --git a/core/src/main/java/jenkins/model/ParameterizedJobMixIn.java b/core/src/main/java/jenkins/model/ParameterizedJobMixIn.java index be71a97c7379..662ffa9359e2 100644 --- a/core/src/main/java/jenkins/model/ParameterizedJobMixIn.java +++ b/core/src/main/java/jenkins/model/ParameterizedJobMixIn.java @@ -218,6 +218,7 @@ public final void doBuild(StaplerRequest req, StaplerResponse rsp, @QueryParamet Queue.Item item = Jenkins.get().getQueue().schedule2(asJob(), delay.getTimeInSeconds(), getBuildCause(asJob(), req)).getItem(); if (item != null) { + // TODO JENKINS-66105 use SC_SEE_OTHER if !ScheduleResult.created rsp.sendRedirect(SC_CREATED, req.getContextPath() + '/' + item.getUrl()); } else { rsp.sendRedirect("."); @@ -346,7 +347,7 @@ static ParameterizedJob resolveForCLI(@Argument(required = true, metaVar = "NAME * (Would have been done entirely as an interface with default methods had this been designed for Java 8.) */ default ParameterizedJobMixIn getParameterizedJobMixIn() { - return new ParameterizedJobMixIn() { + return new ParameterizedJobMixIn<>() { @SuppressWarnings("unchecked") // untypable @Override protected JobT asJob() { return (JobT) ParameterizedJob.this; diff --git a/test/src/test/resources/jenkins/security/stapler/StaplerDispatchValidatorTest/Groovy/compress.groovy b/core/src/main/java/jenkins/model/experimentalflags/RemoveYuiUserExperimentalFlag.java similarity index 60% rename from test/src/test/resources/jenkins/security/stapler/StaplerDispatchValidatorTest/Groovy/compress.groovy rename to core/src/main/java/jenkins/model/experimentalflags/RemoveYuiUserExperimentalFlag.java index 2c342e42bf97..e8f8dcc31775 100644 --- a/test/src/test/resources/jenkins/security/stapler/StaplerDispatchValidatorTest/Groovy/compress.groovy +++ b/core/src/main/java/jenkins/model/experimentalflags/RemoveYuiUserExperimentalFlag.java @@ -1,7 +1,7 @@ /* * The MIT License * - * Copyright (c) 2019 CloudBees, Inc. + * Copyright (c) 2024, Markus Winter * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,13 +22,28 @@ * THE SOFTWARE. */ -package jenkins.security.stapler.StaplerDispatchValidatorTest.Groovy +package jenkins.model.experimentalflags; -def st = namespace('jelly:stapler') -def l = namespace('/lib/layout') -st.compress { - l.view { - st.contentType(value: 'text/html') - st.include(page: 'frag') +import edu.umd.cs.findbugs.annotations.Nullable; +import hudson.Extension; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Extension +@Restricted(NoExternalUse.class) +public class RemoveYuiUserExperimentalFlag extends BooleanUserExperimentalFlag { + public RemoveYuiUserExperimentalFlag() { + super("remove-yui.flag"); + } + + @Override + public String getDisplayName() { + return "Remove YUI"; + } + + @Nullable + @Override + public String getShortDescription() { + return "Remove YUI from all Jenkins UI pages. This will break anything that depends on YUI"; } } diff --git a/core/src/main/java/jenkins/model/experimentalflags/UserExperimentalFlagsProperty.java b/core/src/main/java/jenkins/model/experimentalflags/UserExperimentalFlagsProperty.java index 6732f2e5d696..85332d26973c 100644 --- a/core/src/main/java/jenkins/model/experimentalflags/UserExperimentalFlagsProperty.java +++ b/core/src/main/java/jenkins/model/experimentalflags/UserExperimentalFlagsProperty.java @@ -31,6 +31,7 @@ import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; +import hudson.model.userproperty.UserPropertyCategory; import java.util.HashMap; import java.util.Map; import net.sf.json.JSONObject; @@ -76,13 +77,19 @@ public static final class DescriptorImpl extends UserPropertyDescriptor { public UserProperty newInstance(@Nullable StaplerRequest req, @NonNull JSONObject formData) throws FormException { JSONObject flagsObj = formData.getJSONObject("flags"); Map flags = new HashMap<>(); - for (Object key : flagsObj.keySet()) { - String value = (String) flagsObj.get((String) key); + for (String key : flagsObj.keySet()) { + String value = (String) flagsObj.get(key); if (!value.isEmpty()) { - flags.put((String) key, value); + flags.put(key, value); } } return new UserExperimentalFlagsProperty(flags); } + + @NonNull + @Override + public UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Experimental.class); + } } } diff --git a/core/src/main/java/jenkins/model/lazy/LazyBuildMixIn.java b/core/src/main/java/jenkins/model/lazy/LazyBuildMixIn.java index 203ea976bccd..c73c5cbf80f1 100644 --- a/core/src/main/java/jenkins/model/lazy/LazyBuildMixIn.java +++ b/core/src/main/java/jenkins/model/lazy/LazyBuildMixIn.java @@ -298,7 +298,7 @@ public List getEstimatedDurationCandidates() { /** * @deprecated Remove any code calling this method, history widget is now created via {@link jenkins.widgets.WidgetFactory} implementation. */ - @Deprecated(forRemoval = true, since = "TODO") + @Deprecated(forRemoval = true, since = "2.459") public final HistoryWidget createHistoryWidget() { throw new IllegalStateException("HistoryWidget is now created via WidgetFactory implementation"); } diff --git a/core/src/main/java/jenkins/model/queue/ItemDeletion.java b/core/src/main/java/jenkins/model/queue/ItemDeletion.java index e5c9fc2ca87e..fd18edde04a5 100644 --- a/core/src/main/java/jenkins/model/queue/ItemDeletion.java +++ b/core/src/main/java/jenkins/model/queue/ItemDeletion.java @@ -28,25 +28,42 @@ import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import hudson.ExtensionList; +import hudson.model.AbstractItem; import hudson.model.Action; +import hudson.model.Computer; +import hudson.model.Executor; +import hudson.model.Failure; import hudson.model.Item; +import hudson.model.Messages; import hudson.model.Queue; +import hudson.model.Result; +import hudson.model.queue.Executables; +import hudson.model.queue.SubTask; import hudson.model.queue.Tasks; +import hudson.model.queue.WorkUnit; import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.logging.Logger; +import jenkins.model.Jenkins; import net.jcip.annotations.GuardedBy; /** * A {@link Queue.QueueDecisionHandler} that blocks items being deleted from entering the queue. - * + * @see AbstractItem#delete() * @since 2.55 */ @Extension public class ItemDeletion extends Queue.QueueDecisionHandler { + private static final Logger LOGGER = Logger.getLogger(ItemDeletion.class.getName()); + /** * Lock to guard the {@link #registrations} set. */ @@ -176,4 +193,94 @@ public boolean shouldSchedule(Queue.Task p, List actions) { } return true; } + + /** + * Cancels any builds in progress of this item (if a job) or descendants (if a folder). + * Also cancels any associated queue items. + * @param initiatingItem an item being deleted + * @since TODO + */ + public static void cancelBuildsInProgress(@NonNull Item initiatingItem) throws Failure, InterruptedException { + Queue queue = Queue.getInstance(); + if (initiatingItem instanceof Queue.Task) { + // clear any items in the queue so they do not get picked up + queue.cancel((Queue.Task) initiatingItem); + } + // now cancel any child items - this happens after ItemDeletion registration, so we can use a snapshot + for (Queue.Item i : queue.getItems()) { + Item item = Tasks.getItemOf(i.task); + while (item != null) { + if (item == initiatingItem) { + if (!queue.cancel(i)) { + LOGGER.warning(() -> "failed to cancel " + i); + } + break; + } + if (item.getParent() instanceof Item) { + item = (Item) item.getParent(); + } else { + break; + } + } + } + // interrupt any builds in progress (and this should be a recursive test so that folders do not pay + // the 15 second delay for every child item). This happens after queue cancellation, so will be + // a complete set of builds in flight + Map buildsInProgress = new LinkedHashMap<>(); + for (Computer c : Jenkins.get().getComputers()) { + for (Executor e : c.getAllExecutors()) { + final WorkUnit workUnit = e.getCurrentWorkUnit(); + final Queue.Executable executable = workUnit != null ? workUnit.getExecutable() : null; + final SubTask subtask = executable != null ? Executables.getParentOf(executable) : null; + if (subtask != null) { + Item item = Tasks.getItemOf(subtask); + while (item != null) { + if (item == initiatingItem) { + buildsInProgress.put(e, e.getCurrentExecutable()); + e.interrupt(Result.ABORTED); + break; + } + if (item.getParent() instanceof Item) { + item = (Item) item.getParent(); + } else { + break; + } + } + } + } + } + if (!buildsInProgress.isEmpty()) { + // give them 15 seconds or so to respond to the interrupt + long expiration = System.nanoTime() + TimeUnit.SECONDS.toNanos(15); + // comparison with executor.getCurrentExecutable() == computation currently should always be true + // as we no longer recycle Executors, but safer to future-proof in case we ever revisit recycling + while (!buildsInProgress.isEmpty() && expiration - System.nanoTime() > 0L) { + // we know that ItemDeletion will prevent any new builds in the queue + // ItemDeletion happens-before Queue.cancel so we know that the Queue will stay clear + // Queue.cancel happens-before collecting the buildsInProgress list + // thus buildsInProgress contains the complete set we need to interrupt and wait for + for (Iterator> iterator = + buildsInProgress.entrySet().iterator(); + iterator.hasNext(); ) { + Map.Entry entry = iterator.next(); + // comparison with executor.getCurrentExecutable() == executable currently should always be + // true as we no longer recycle Executors, but safer to future-proof in case we ever + // revisit recycling. + if (!entry.getKey().isAlive() + || entry.getValue() != entry.getKey().getCurrentExecutable()) { + iterator.remove(); + } + // I don't know why, but we have to keep interrupting + entry.getKey().interrupt(Result.ABORTED); + } + Thread.sleep(50L); + } + if (!buildsInProgress.isEmpty()) { + throw new Failure(Messages.AbstractItem_FailureToStopBuilds( + buildsInProgress.size(), initiatingItem.getFullDisplayName() + )); + } + } + } + } diff --git a/core/src/main/java/jenkins/monitor/JavaVersionRecommendationAdminMonitor.java b/core/src/main/java/jenkins/monitor/JavaVersionRecommendationAdminMonitor.java index 4b3642bb059c..c95740613765 100644 --- a/core/src/main/java/jenkins/monitor/JavaVersionRecommendationAdminMonitor.java +++ b/core/src/main/java/jenkins/monitor/JavaVersionRecommendationAdminMonitor.java @@ -78,16 +78,6 @@ public class JavaVersionRecommendationAdminMonitor extends AdministrativeMonitor static { NavigableMap supportedVersions = new TreeMap<>(); - // Adjust Java 11 end of life date for weekly and LTS - if (Jenkins.VERSION.split("[.]").length > 2) { - // LTS will require Java 17 or newer beginning 30 Oct 2024 - // https://groups.google.com/g/jenkinsci-dev/c/gsXAqOQQEPc/m/VT9IBYdmAQAJ - supportedVersions.put(11, LocalDate.of(2024, 10, 30)); // Temurin: 2024-10-31 - } else { - // Weekly will require Java 17 or newer beginning 18 Jun 2024 - // https://groups.google.com/g/jenkinsci-dev/c/gsXAqOQQEPc/m/4fn4Un1iAwAJ - supportedVersions.put(11, LocalDate.of(2024, 6, 18)); // Temurin: 2024-10-31 - } supportedVersions.put(17, LocalDate.of(2026, 3, 31)); // Temurin: 2027-10-31 supportedVersions.put(21, LocalDate.of(2027, 9, 30)); // Temurin: 2029-09-30 SUPPORTED_JAVA_VERSIONS = Collections.unmodifiableNavigableMap(supportedVersions); diff --git a/core/src/main/java/jenkins/org/apache/commons/validator/routines/UrlValidator.java b/core/src/main/java/jenkins/org/apache/commons/validator/routines/UrlValidator.java index 40c0eae1d13f..555d0c58f5e3 100644 --- a/core/src/main/java/jenkins/org/apache/commons/validator/routines/UrlValidator.java +++ b/core/src/main/java/jenkins/org/apache/commons/validator/routines/UrlValidator.java @@ -420,7 +420,7 @@ protected boolean isValidAuthority(String authority) { } } String port = authorityMatcher.group(PARSE_AUTHORITY_PORT); - if (port != null && port.length() > 0) { + if (port != null && !port.isEmpty()) { try { int iPort = Integer.parseInt(port); if (iPort < 0 || iPort > MAX_UNSIGNED_16_BIT_INT) { @@ -433,7 +433,7 @@ protected boolean isValidAuthority(String authority) { } String extra = authorityMatcher.group(PARSE_AUTHORITY_EXTRA); - if (extra != null && extra.trim().length() > 0) { + if (extra != null && !extra.trim().isEmpty()) { return false; } diff --git a/core/src/main/java/jenkins/security/ApiTokenProperty.java b/core/src/main/java/jenkins/security/ApiTokenProperty.java index 69904a0e4785..464fdcbdf16c 100644 --- a/core/src/main/java/jenkins/security/ApiTokenProperty.java +++ b/core/src/main/java/jenkins/security/ApiTokenProperty.java @@ -33,6 +33,7 @@ import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; +import hudson.model.userproperty.UserPropertyCategory; import hudson.security.ACL; import hudson.util.HttpResponses; import hudson.util.Secret; @@ -657,6 +658,11 @@ public HttpResponse doRevokeAllExcept(@AncestorInPath User u, return HttpResponses.ok(); } + + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Security.class); + } } /** diff --git a/core/src/main/java/jenkins/security/LastGrantedAuthoritiesProperty.java b/core/src/main/java/jenkins/security/LastGrantedAuthoritiesProperty.java index 52f74d452ffa..cb8b8accf295 100644 --- a/core/src/main/java/jenkins/security/LastGrantedAuthoritiesProperty.java +++ b/core/src/main/java/jenkins/security/LastGrantedAuthoritiesProperty.java @@ -6,6 +6,7 @@ import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; +import hudson.model.userproperty.UserPropertyCategory; import hudson.security.SecurityRealm; import java.io.IOException; import java.util.ArrayList; @@ -171,6 +172,11 @@ public boolean isEnabled() { public UserProperty newInstance(User user) { return null; } + + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Invisible.class); + } } private static final Logger LOGGER = Logger.getLogger(LastGrantedAuthoritiesProperty.class.getName()); diff --git a/core/src/main/java/jenkins/security/RedactSecretJsonInErrorMessageSanitizer.java b/core/src/main/java/jenkins/security/RedactSecretJsonInErrorMessageSanitizer.java index 733a6c89a1f2..1e201bcd3dbc 100644 --- a/core/src/main/java/jenkins/security/RedactSecretJsonInErrorMessageSanitizer.java +++ b/core/src/main/java/jenkins/security/RedactSecretJsonInErrorMessageSanitizer.java @@ -88,7 +88,6 @@ private Object copyAndSanitize(Object value) { } } - @SuppressWarnings("unchecked") private JSONObject copyAndSanitizeObject(JSONObject jsonObject) { Set redactedKeySet = retrieveRedactedKeys(jsonObject); JSONObject result = new JSONObject(); diff --git a/core/src/main/java/jenkins/security/ResourceDomainConfiguration.java b/core/src/main/java/jenkins/security/ResourceDomainConfiguration.java index 5c569ce40d50..cd552fc65130 100644 --- a/core/src/main/java/jenkins/security/ResourceDomainConfiguration.java +++ b/core/src/main/java/jenkins/security/ResourceDomainConfiguration.java @@ -150,8 +150,7 @@ private FormValidation checkUrl(String resourceRootUrlString, boolean allowOnlin // Send a request to /instance-identity/ at the resource root URL and check whether it is this Jenkins try { URLConnection urlConnection = new URI(resourceRootUrlString + "instance-identity/").toURL().openConnection(); - if (urlConnection instanceof HttpURLConnection) { - HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection; + if (urlConnection instanceof HttpURLConnection httpURLConnection) { int responseCode = httpURLConnection.getResponseCode(); if (responseCode == 200) { diff --git a/core/src/main/java/jenkins/security/seed/UserSeedChangeListener.java b/core/src/main/java/jenkins/security/seed/UserSeedChangeListener.java index 02753addb79d..e87506315a41 100644 --- a/core/src/main/java/jenkins/security/seed/UserSeedChangeListener.java +++ b/core/src/main/java/jenkins/security/seed/UserSeedChangeListener.java @@ -35,7 +35,7 @@ /** * Listener notified when a user was requested to changed their seed - * @since 2.160 and 2.150.2, but restricted (unavailable to plugins) before TODO + * @since 2.160 and 2.150.2, but restricted (unavailable to plugins) before 2.406 */ public abstract class UserSeedChangeListener implements ExtensionPoint { private static final Logger LOGGER = Logger.getLogger(SecurityListener.class.getName()); diff --git a/core/src/main/java/jenkins/security/seed/UserSeedProperty.java b/core/src/main/java/jenkins/security/seed/UserSeedProperty.java index d7420910cb64..968ee9320f58 100644 --- a/core/src/main/java/jenkins/security/seed/UserSeedProperty.java +++ b/core/src/main/java/jenkins/security/seed/UserSeedProperty.java @@ -31,6 +31,7 @@ import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; +import hudson.model.userproperty.UserPropertyCategory; import hudson.util.HttpResponses; import java.io.IOException; import java.security.SecureRandom; @@ -153,5 +154,10 @@ public synchronized HttpResponse doRenewSessionSeed(@AncestorInPath @NonNull Use public boolean isEnabled() { return !DISABLE_USER_SEED && !HIDE_USER_SEED_SECTION; } + + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Security.class); + } } } diff --git a/core/src/main/java/jenkins/util/TreeString.java b/core/src/main/java/jenkins/util/TreeString.java index 3bcdc95d90ca..58890d225893 100644 --- a/core/src/main/java/jenkins/util/TreeString.java +++ b/core/src/main/java/jenkins/util/TreeString.java @@ -64,7 +64,7 @@ public final class TreeString implements Serializable { } /* package */TreeString(final TreeString parent, final String label) { - assert parent == null || label.length() > 0; // if there's a parent, + assert parent == null || !label.isEmpty(); // if there's a parent, // label can't be empty. this.parent = parent; diff --git a/core/src/main/java/jenkins/util/URLClassLoader2.java b/core/src/main/java/jenkins/util/URLClassLoader2.java index 3fdedcbeada0..a6e5194e14f3 100644 --- a/core/src/main/java/jenkins/util/URLClassLoader2.java +++ b/core/src/main/java/jenkins/util/URLClassLoader2.java @@ -20,7 +20,7 @@ public class URLClassLoader2 extends URLClassLoader implements JenkinsClassLoade /** * @deprecated use {@link URLClassLoader2#URLClassLoader2(String, URL[])} */ - @Deprecated(since = "TODO") + @Deprecated(since = "2.459") public URLClassLoader2(URL[] urls) { super(urls); } @@ -28,7 +28,7 @@ public URLClassLoader2(URL[] urls) { /** * @deprecated use {@link URLClassLoader2#URLClassLoader2(String, URL[], ClassLoader)} */ - @Deprecated(since = "TODO") + @Deprecated(since = "2.459") public URLClassLoader2(URL[] urls, ClassLoader parent) { super(urls, parent); } @@ -37,7 +37,7 @@ public URLClassLoader2(URL[] urls, ClassLoader parent) { * Create a new {@link URLClassLoader2} with the given name and URLS and the {@link #getSystemClassLoader()} as its parent. * @param name name of this classloader. * @param urls the list of URLS to find classes in. - * @since TODO + * @since 2.459 */ public URLClassLoader2(String name, URL[] urls) { super(name, urls, getSystemClassLoader()); @@ -48,7 +48,7 @@ public URLClassLoader2(String name, URL[] urls) { * @param name name of this classloader. * @param urls the list of URLS to find classes in. * @param parent the parent to search for classes before we look in the {@code urls} - * @since TODO + * @since 2.459 */ public URLClassLoader2(String name, URL[] urls, ClassLoader parent) { super(name, urls, parent); diff --git a/core/src/main/java/jenkins/util/VirtualFile.java b/core/src/main/java/jenkins/util/VirtualFile.java index bf9fc49bd48d..6c754a50bbc4 100644 --- a/core/src/main/java/jenkins/util/VirtualFile.java +++ b/core/src/main/java/jenkins/util/VirtualFile.java @@ -46,6 +46,7 @@ import java.io.Serializable; import java.net.URI; import java.net.URL; +import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.OpenOption; @@ -375,7 +376,7 @@ public int zip(OutputStream outputStream, String includes, String excludes, bool Collection files = list(includes, excludes, useDefaultExcludes, openOptions); try (ZipOutputStream zos = new ZipOutputStream(outputStream)) { - zos.setEncoding(System.getProperty("file.encoding")); // TODO JENKINS-20663 make this overridable via query parameter + zos.setEncoding(Charset.defaultCharset().displayName()); // TODO JENKINS-20663 make this overridable via query parameter for (String relativePath : files) { VirtualFile virtualFile = this.child(relativePath); diff --git a/core/src/main/java/jenkins/widgets/BuildTimeTrend.java b/core/src/main/java/jenkins/widgets/BuildTimeTrend.java index 59ab879f05da..dd0f0434ecb3 100644 --- a/core/src/main/java/jenkins/widgets/BuildTimeTrend.java +++ b/core/src/main/java/jenkins/widgets/BuildTimeTrend.java @@ -25,7 +25,9 @@ package jenkins.widgets; import hudson.model.AbstractBuild; +import hudson.model.AbstractProject; import hudson.model.BallColor; +import hudson.model.Job; import hudson.model.Node; import hudson.model.Run; import jenkins.console.ConsoleUrlProvider; @@ -37,6 +39,10 @@ @Restricted(DoNotUse.class) // only for buildTimeTrend.jelly public class BuildTimeTrend extends RunListProgressiveRendering { + public boolean isAbstractProject(Job job) { + return job instanceof AbstractProject; + } + @Override protected void calculate(Run build, JSONObject element) { BallColor iconColor = build.getIconColor(); element.put("iconName", iconColor.getIconName()); @@ -46,6 +52,8 @@ public class BuildTimeTrend extends RunListProgressiveRendering { element.put("displayName", build.getDisplayName()); element.put("duration", build.getDuration()); element.put("durationString", build.getDurationString()); + element.put("timestampString", build.getTimestampString()); + element.put("timestampString2", build.getTimestampString2()); element.put("consoleUrl", ConsoleUrlProvider.getRedirectUrl(build)); if (build instanceof AbstractBuild) { AbstractBuild b = (AbstractBuild) build; diff --git a/core/src/main/java/jenkins/widgets/HistoryPageEntry.java b/core/src/main/java/jenkins/widgets/HistoryPageEntry.java index ac5e0a772692..98f0a7aac58e 100644 --- a/core/src/main/java/jenkins/widgets/HistoryPageEntry.java +++ b/core/src/main/java/jenkins/widgets/HistoryPageEntry.java @@ -57,8 +57,7 @@ public long getEntryId() { protected static long getEntryId(@NonNull Object entry) { if (entry instanceof QueueItem) { return ((QueueItem) entry).getId(); - } else if (entry instanceof Run) { - Run run = (Run) entry; + } else if (entry instanceof Run run) { return Long.MIN_VALUE + run.getNumber(); } else if (entry instanceof Number) { // Used for testing purposes because of JENKINS-30899 and JENKINS-30909 diff --git a/core/src/main/java/org/jenkins/ui/icon/Icon.java b/core/src/main/java/org/jenkins/ui/icon/Icon.java index e99822dac653..95524c8c4b74 100644 --- a/core/src/main/java/org/jenkins/ui/icon/Icon.java +++ b/core/src/main/java/org/jenkins/ui/icon/Icon.java @@ -279,7 +279,7 @@ public static String toNormalizedCSSSelector(String classNames) { // Trim all tokens first for (String classNameTok : classNameTokA) { String trimmedToken = classNameTok.trim(); - if (trimmedToken.length() > 0) { + if (!trimmedToken.isEmpty()) { classNameTokL.add(trimmedToken); } } diff --git a/core/src/main/java/org/jenkins/ui/symbol/Symbol.java b/core/src/main/java/org/jenkins/ui/symbol/Symbol.java index 9a07556d7c71..52c7faee0249 100644 --- a/core/src/main/java/org/jenkins/ui/symbol/Symbol.java +++ b/core/src/main/java/org/jenkins/ui/symbol/Symbol.java @@ -14,6 +14,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; +import java.util.regex.Matcher; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -72,13 +73,13 @@ public static String get(@NonNull SymbolRequest request) { .computeIfAbsent(identifier, key -> new ConcurrentHashMap<>()) .computeIfAbsent(name, key -> loadSymbol(identifier, key)); if ((tooltip != null && !tooltip.isBlank()) && (htmlTooltip == null || htmlTooltip.isBlank())) { - symbol = symbol.replaceAll(" - - + + + + + Jenkins diff --git a/core/src/main/resources/hudson/console/ExpandableDetailsNote/script.js b/core/src/main/resources/hudson/console/ExpandableDetailsNote/script.js index bd71b5fec807..f42f4113802d 100644 --- a/core/src/main/resources/hudson/console/ExpandableDetailsNote/script.js +++ b/core/src/main/resources/hudson/console/ExpandableDetailsNote/script.js @@ -1,11 +1,11 @@ (function () { Behaviour.specify( - "INPUT.reveal-expandable-detail", + "BUTTON.reveal-expandable-detail", "ExpandableDetailsNote", 0, function (e) { - var detail = e.nextSibling; - makeButton(e, function () { + e.addEventListener("click", () => { + const detail = e.nextSibling; detail.style.display = detail.style.display == "block" ? "none" : "block"; }); diff --git a/core/src/main/resources/hudson/console/ExpandableDetailsNote/style.css b/core/src/main/resources/hudson/console/ExpandableDetailsNote/style.css index 3015eb2ba7e8..b3636a127219 100644 --- a/core/src/main/resources/hudson/console/ExpandableDetailsNote/style.css +++ b/core/src/main/resources/hudson/console/ExpandableDetailsNote/style.css @@ -1,6 +1,6 @@ DIV.expandable-detail { display: none; - background-color: #d3d7cf; + background-color: var(--background); margin: 0.5em; padding: 0.5em; } diff --git a/core/src/main/resources/hudson/model/Computer/_scriptText.jelly b/core/src/main/resources/hudson/model/Computer/_scriptText.jelly index f87b23b69df5..f5aa6304ee2b 100644 --- a/core/src/main/resources/hudson/model/Computer/_scriptText.jelly +++ b/core/src/main/resources/hudson/model/Computer/_scriptText.jelly @@ -26,8 +26,8 @@ THE SOFTWARE. Called from doScriptText() to display the execution result. --> - + - + diff --git a/core/src/main/resources/hudson/model/Computer/index-top.jelly b/core/src/main/resources/hudson/model/Computer/index-top.jelly index 95bab4bf8759..37fd8a2f1945 100644 --- a/core/src/main/resources/hudson/model/Computer/index-top.jelly +++ b/core/src/main/resources/hudson/model/Computer/index-top.jelly @@ -1,5 +1,5 @@ - + diff --git a/core/src/main/resources/hudson/model/Computer/index.jelly b/core/src/main/resources/hudson/model/Computer/index.jelly index ccb8d5805218..39c6c974ad61 100644 --- a/core/src/main/resources/hudson/model/Computer/index.jelly +++ b/core/src/main/resources/hudson/model/Computer/index.jelly @@ -29,6 +29,7 @@ THE SOFTWARE. + diff --git a/core/src/main/resources/hudson/model/Job/buildTimeTrend.jelly b/core/src/main/resources/hudson/model/Job/buildTimeTrend.jelly index 18f874a6751f..7efb53f362a4 100644 --- a/core/src/main/resources/hudson/model/Job/buildTimeTrend.jelly +++ b/core/src/main/resources/hudson/model/Job/buildTimeTrend.jelly @@ -25,7 +25,7 @@ THE SOFTWARE. - + @@ -45,29 +45,36 @@ THE SOFTWARE. +

${%Build Time Trend}

-
+
+
+ + ${handler.setBuilds(it.builds)} + + + + + + + + + + + + + + + + + +
${%S}${%Build}${%Time Since}${%Duration}${%Agent}
+ +
[${%Build time graph}]
- - -
- - ${handler.setBuilds(it.builds)} - - - - - - - - - - -
${%Build}${%Duration}${%Agent}
-
diff --git a/core/src/main/resources/hudson/model/Job/buildTimeTrend_resources.css b/core/src/main/resources/hudson/model/Job/buildTimeTrend_resources.css index 13efe1c1e375..af8ba3705509 100644 --- a/core/src/main/resources/hudson/model/Job/buildTimeTrend_resources.css +++ b/core/src/main/resources/hudson/model/Job/buildTimeTrend_resources.css @@ -1,3 +1,10 @@ -img.build-time-graph { - float: right; +#buildTimeTrend { + display: flex; + gap: 15px; +} + +@media (max-width: 1300px) { + #buildTimeTrend { + flex-direction: column-reverse; + } } diff --git a/core/src/main/resources/hudson/model/Job/buildTimeTrend_resources.js b/core/src/main/resources/hudson/model/Job/buildTimeTrend_resources.js index 8a6cbfd49253..9ea25a3441de 100644 --- a/core/src/main/resources/hudson/model/Job/buildTimeTrend_resources.js +++ b/core/src/main/resources/hudson/model/Job/buildTimeTrend_resources.js @@ -2,30 +2,31 @@ * Public method to be called by progressiveRendering's callback */ window.buildTimeTrend_displayBuilds = function (data) { - var p = document.getElementById("trend"); - var isDistributedBuildsEnabled = - "true" === p.getAttribute("data-is-distributed-build-enabled"); - var rootURL = document.head.getAttribute("data-rooturl"); + const p = document.getElementById("trend"); + p.classList.remove("jenkins-hidden"); - for (var x = 0; data.length > x; x++) { - var e = data[x]; - var tr = document.createElement("tr"); + const showAgent = "true" === p.dataset.showAgent; + const rootURL = document.head.getAttribute("data-rooturl"); + + for (let x = 0; data.length > x; x++) { + const e = data[x]; + let tr = document.createElement("tr"); let td = document.createElement("td"); td.setAttribute("data", e.iconColorOrdinal); - - let link = document.createElement("a"); - link.classList.add("build-status-link"); - link.href = e.consoleUrl; - td.appendChild(link); + td.classList.add("jenkins-table__cell--tight", "jenkins-table__icon"); + let div = document.createElement("div"); + div.classList.add("jenkins-table__cell__button-wrapper"); let svg = generateSVGIcon(e.iconName); - link.appendChild(svg); + svg.setAttribute("tooltip", e.iconColorDescription); + div.appendChild(svg); + td.appendChild(div); tr.appendChild(td); td = document.createElement("td"); td.setAttribute("data", e.number); - link = document.createElement("a"); + let link = document.createElement("a"); link.href = e.number + "/"; link.classList.add("model-link", "inside"); link.innerText = escapeHTML(e.displayName); @@ -33,15 +34,20 @@ window.buildTimeTrend_displayBuilds = function (data) { td.appendChild(link); tr.appendChild(td); + td = document.createElement("td"); + td.setAttribute("data", e.timestampString2); + td.textContent = e.timestampString; + tr.appendChild(td); + td = document.createElement("td"); td.setAttribute("data", e.duration); td.innerText = escapeHTML(e.durationString); tr.appendChild(td); - if (isDistributedBuildsEnabled) { - var buildInfo = null; - var buildInfoStr = escapeHTML(e.builtOnStr || ""); + if (showAgent) { + let buildInfo = null; + let buildInfoStr = escapeHTML(e.builtOnStr || ""); if (e.builtOn) { buildInfo = document.createElement("a"); buildInfo.href = rootURL + "/computer/" + e.builtOn; @@ -58,6 +64,19 @@ window.buildTimeTrend_displayBuilds = function (data) { } tr.appendChild(td); } + + let tdConsole = document.createElement("td"); + tdConsole.classList.add("jenkins-table__cell--tight"); + let div2 = document.createElement("div"); + div2.classList.add("jenkins-table__cell__button-wrapper"); + link = document.createElement("a"); + link.classList.add("jenkins-button", "jenkins-button--tertiary"); + link.href = e.consoleUrl; + link.appendChild(generateSVGIcon("console")); + div2.appendChild(link); + tdConsole.appendChild(div2); + tr.appendChild(tdConsole); + p.appendChild(tr); Behaviour.applySubtree(tr); } @@ -132,7 +151,7 @@ window.displayBuilds = function (data) { var div2 = document.createElement("div"); div2.classList.add("jenkins-table__cell__button-wrapper"); var a3 = document.createElement("a"); - a3.classList.add("jenkins-button"); + a3.classList.add("jenkins-button", "jenkins-button--tertiary"); a3.href = e.consoleUrl; a3.innerHTML = p.dataset.consoleOutputIcon; div2.appendChild(a3); diff --git a/core/src/main/resources/hudson/model/Job/index.jelly b/core/src/main/resources/hudson/model/Job/index.jelly index 0fb537e267d7..d9b214900c7b 100644 --- a/core/src/main/resources/hudson/model/Job/index.jelly +++ b/core/src/main/resources/hudson/model/Job/index.jelly @@ -40,6 +40,9 @@ THE SOFTWARE.
+
+ +
@@ -52,7 +55,7 @@ THE SOFTWARE. - + diff --git a/core/src/main/resources/hudson/model/Label/index.jelly b/core/src/main/resources/hudson/model/Label/index.jelly index 34ede2f6c8ee..ad75b1dbf4c7 100644 --- a/core/src/main/resources/hudson/model/Label/index.jelly +++ b/core/src/main/resources/hudson/model/Label/index.jelly @@ -28,12 +28,13 @@ THE SOFTWARE. -

- ${it.name} -

- + + + + + - + diff --git a/core/src/main/resources/hudson/model/Messages.properties b/core/src/main/resources/hudson/model/Messages.properties index 2b1a6559fa58..d56c57ff5ee0 100644 --- a/core/src/main/resources/hudson/model/Messages.properties +++ b/core/src/main/resources/hudson/model/Messages.properties @@ -279,7 +279,7 @@ View.DeletePermission.Description=\ View.ConfigurePermission.Description=\ This permission allows users to change the configuration of views. View.ReadPermission.Description=\ - This permission allows users to see views (implied by generic read access). + This permission allows users to see views. View.MissingMode=No view type is specified View.DisplayNameNotUniqueWarning=The display name, "{0}", is already in use by another view and \ could cause confusion and delay. @@ -422,3 +422,5 @@ ManagementLink.Category.MISC=Other ManagementLink.Category.UNCATEGORIZED=Uncategorized FileParameterValue.IndexTitle=File Parameters + +UserPreferencesProperty.DisplayName=Preferences diff --git a/core/src/main/resources/hudson/model/Run/console.jelly b/core/src/main/resources/hudson/model/Run/console.jelly index 3609d2b7ee68..ad38828dad5a 100644 --- a/core/src/main/resources/hudson/model/Run/console.jelly +++ b/core/src/main/resources/hudson/model/Run/console.jelly @@ -28,7 +28,7 @@ THE SOFTWARE. Displays the console output --> - + @@ -84,4 +84,4 @@ THE SOFTWARE.
- +
diff --git a/core/src/main/resources/hudson/model/Run/consoleFull.jelly b/core/src/main/resources/hudson/model/Run/consoleFull.jelly index 6e4a820d9d33..feed99c66479 100644 --- a/core/src/main/resources/hudson/model/Run/consoleFull.jelly +++ b/core/src/main/resources/hudson/model/Run/consoleFull.jelly @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --> - + - +
diff --git a/core/src/main/resources/hudson/model/Run/index.jelly b/core/src/main/resources/hudson/model/Run/index.jelly index 0acdb74fb01f..b164817a164f 100644 --- a/core/src/main/resources/hudson/model/Run/index.jelly +++ b/core/src/main/resources/hudson/model/Run/index.jelly @@ -30,10 +30,20 @@ THE SOFTWARE. -
+ + + + + ${it.displayName} () + +
+ +
+ +
${%startedAgo(it.timestampString)}
@@ -48,11 +58,6 @@ THE SOFTWARE.
- ${it.displayName} () - -
- -
-
+ diff --git a/core/src/main/resources/hudson/model/Run/statusIcon.jelly b/core/src/main/resources/hudson/model/Run/statusIcon.jelly index e481fd48761d..548d5176bcea 100644 --- a/core/src/main/resources/hudson/model/Run/statusIcon.jelly +++ b/core/src/main/resources/hudson/model/Run/statusIcon.jelly @@ -28,7 +28,7 @@ THE SOFTWARE. Displays the console output --> - + @@ -37,4 +37,4 @@ THE SOFTWARE. - +
diff --git a/core/src/main/resources/hudson/model/User/configure.jelly b/core/src/main/resources/hudson/model/User/configure.jelly deleted file mode 100644 index 9b4100248559..000000000000 --- a/core/src/main/resources/hudson/model/User/configure.jelly +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/core/src/main/resources/hudson/model/User/index.jelly b/core/src/main/resources/hudson/model/User/index.jelly index db5a8f83022e..a85c46b1a945 100644 --- a/core/src/main/resources/hudson/model/User/index.jelly +++ b/core/src/main/resources/hudson/model/User/index.jelly @@ -27,13 +27,21 @@ THE SOFTWARE. -

- - - - ${it.fullName} -

- +
+
+

+ + + + ${it.fullName} +

+
+
+ +
+
+ +
${%Jenkins User ID}: ${it.id}
diff --git a/core/src/main/resources/hudson/model/User/sidepanel.jelly b/core/src/main/resources/hudson/model/User/sidepanel.jelly index 834061995daf..f8024b0c21b8 100644 --- a/core/src/main/resources/hudson/model/User/sidepanel.jelly +++ b/core/src/main/resources/hudson/model/User/sidepanel.jelly @@ -33,7 +33,6 @@ THE SOFTWARE. - diff --git a/core/src/main/resources/hudson/model/View/index.jelly b/core/src/main/resources/hudson/model/View/index.jelly index 3f20913e81cc..14632b8e60e8 100644 --- a/core/src/main/resources/hudson/model/View/index.jelly +++ b/core/src/main/resources/hudson/model/View/index.jelly @@ -23,7 +23,7 @@ THE SOFTWARE. --> - + @@ -44,9 +44,8 @@ THE SOFTWARE.
- + diff --git a/core/src/test/java/hudson/GetLocaleStaticHelpUrlTest.java b/core/src/test/java/hudson/GetLocaleStaticHelpUrlTest.java index 5fd822bc1c55..a61fc0d54656 100644 --- a/core/src/test/java/hudson/GetLocaleStaticHelpUrlTest.java +++ b/core/src/test/java/hudson/GetLocaleStaticHelpUrlTest.java @@ -36,6 +36,7 @@ import java.util.Enumeration; import java.util.Locale; import org.junit.jupiter.api.Test; +import org.jvnet.hudson.test.Issue; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.lang.Klass; @@ -191,6 +192,24 @@ public void getStaticHelpUrlAcceptZhResMore() { assertThatLocaleResourceIs(id, "help-id_zh_CN.html"); } + @Issue("JENKINS-73246") + @Test + public void getStaticHelpUrlAcceptEnFirst() { + // Accept-Language: en-US,en;q=0.9,de;q=0.8 + StaplerRequest req = mockStaplerRequest( + Locale.US, + Locale.ENGLISH, + Locale.GERMAN + ); + + Klass klass = mockKlass( + "help-id.html", + "help-id_de.html" + ); + URL id = Descriptor.getStaticHelpUrl(req, klass, "-id"); + assertThatLocaleResourceIs(id, "help-id.html"); + } + private StaplerRequest mockStaplerRequest(Locale... localeArr) { StaplerRequest req = mock(StaplerRequest.class); Enumeration locales = Collections.enumeration(Arrays.asList(localeArr)); diff --git a/core/src/test/java/hudson/UtilTest.java b/core/src/test/java/hudson/UtilTest.java index 3fd34ff5c2ad..ac08dccb5d22 100644 --- a/core/src/test/java/hudson/UtilTest.java +++ b/core/src/test/java/hudson/UtilTest.java @@ -248,7 +248,7 @@ public void testSymlink() throws Exception { Util.createSymlink(d, buf.toString(), "x", l); String log = baos.toString(Charset.defaultCharset()); - if (log.length() > 0) + if (!log.isEmpty()) System.err.println("log output: " + log); assertEquals(buf.toString(), Util.resolveSymlink(new File(d, "x"))); diff --git a/core/src/test/java/hudson/cli/ListJobsCommandTest.java b/core/src/test/java/hudson/cli/ListJobsCommandTest.java index 6be35fded558..8baa6814b95b 100644 --- a/core/src/test/java/hudson/cli/ListJobsCommandTest.java +++ b/core/src/test/java/hudson/cli/ListJobsCommandTest.java @@ -191,7 +191,7 @@ protected boolean matchesSafely(ByteArrayOutputStream item) { } catch (InterruptedException e) { throw new RuntimeException(e); } - Set jobs = new HashSet<>(Arrays.asList(item.toString(charset).split(System.getProperty("line.separator")))); + Set jobs = new HashSet<>(Arrays.asList(item.toString(charset).split(System.lineSeparator()))); return new HashSet<>(Arrays.asList(expected)).equals(jobs); } diff --git a/core/src/test/java/hudson/model/RunTest.java b/core/src/test/java/hudson/model/RunTest.java index 59b32ab915c5..04448da1f12a 100644 --- a/core/src/test/java/hudson/model/RunTest.java +++ b/core/src/test/java/hudson/model/RunTest.java @@ -197,7 +197,7 @@ public void getLogReturnsAnRightOrder() throws Exception { for (int i = 1; i < 10; i++) { assertEquals("dummy" + (10 + i), logLines.get(i)); } - int truncatedCount = 10 * ("dummyN".length() + System.getProperty("line.separator").length()) - 2; + int truncatedCount = 10 * ("dummyN".length() + System.lineSeparator().length()) - 2; assertEquals("[...truncated " + truncatedCount + " B...]", logLines.get(0)); } diff --git a/core/src/test/java/hudson/util/RetrierTest.java b/core/src/test/java/hudson/util/RetrierTest.java index 50abb7ded2b1..42242b44f4c7 100644 --- a/core/src/test/java/hudson/util/RetrierTest.java +++ b/core/src/test/java/hudson/util/RetrierTest.java @@ -160,7 +160,7 @@ public void failedActionWithExceptionAfterThreeAttemptsWithoutListenerTest() thr throw new IndexOutOfBoundsException("Exception allowed considered as failure"); }, // check the result and return true (boolean primitive type) if success - (currentAttempt, result) -> result == null ? false : result, + (currentAttempt, result) -> result != null && result, //name of the action ACTION ) diff --git a/core/src/test/java/hudson/util/SecretRewriterTest.java b/core/src/test/java/hudson/util/SecretRewriterTest.java index ff13cd915254..4c13761a4caf 100644 --- a/core/src/test/java/hudson/util/SecretRewriterTest.java +++ b/core/src/test/java/hudson/util/SecretRewriterTest.java @@ -54,7 +54,7 @@ private String roundtrip(String before) throws Exception { Files.writeString(path, before, Charset.defaultCharset()); sr.rewrite(path.toFile()); //assert after.replaceAll(System.getProperty("line.separator"), "\n").trim()==f.text.replaceAll(System.getProperty("line.separator"), "\n").trim() - return Files.readString(path, Charset.defaultCharset()).replaceAll(System.getProperty("line.separator"), "\n").trim(); + return Files.readString(path, Charset.defaultCharset()).replaceAll(System.lineSeparator(), "\n").trim(); } @SuppressWarnings("deprecation") diff --git a/core/src/test/java/jenkins/model/PeepholePermalinkTest.java b/core/src/test/java/jenkins/model/PeepholePermalinkTest.java index 8a2cb059b230..50a3934700cf 100644 --- a/core/src/test/java/jenkins/model/PeepholePermalinkTest.java +++ b/core/src/test/java/jenkins/model/PeepholePermalinkTest.java @@ -39,7 +39,7 @@ public void classLoadingDeadlock() throws Exception { PeepholePermalink.initialized(); Thread t = new Thread(() -> { assertThat("successfully loaded permalinks", - PermalinkProjectAction.Permalink.BUILTIN.stream().map(p -> p.getId()).collect(Collectors.toSet()), + PermalinkProjectAction.Permalink.BUILTIN.stream().map(PermalinkProjectAction.Permalink::getId).collect(Collectors.toSet()), containsInAnyOrder("lastBuild", "lastStableBuild", "lastSuccessfulBuild", "lastFailedBuild", "lastUnstableBuild", "lastUnsuccessfulBuild", "lastCompletedBuild")); }); t.start(); diff --git a/pom.xml b/pom.xml index c5f81fef70b9..dcf21e286330 100644 --- a/pom.xml +++ b/pom.xml @@ -28,7 +28,7 @@ THE SOFTWARE. org.jenkins-ci jenkins - 1.114 + 1.119 @@ -73,9 +73,9 @@ THE SOFTWARE. - 2.460 + 2.470 -SNAPSHOT - 2024-05-21T13:12:34Z + 2024-07-23T13:33:48Z github @@ -87,9 +87,9 @@ THE SOFTWARE. https://www.jenkins.io/changelog - 3248.v65ecb_254c298 + 3256.v88a_f6e922152 - 4.13 + 3107.v665000b_51092 Max Medium @@ -99,7 +99,7 @@ THE SOFTWARE. 1.29 false - 6.19 + 6.21 io.jenkins.plugins commons-text-api - 1.11.0-109.vfe16c66636eb_ + 1.12.0-119.v73ef73f2345d @@ -95,6 +95,11 @@ THE SOFTWARE. ant 497.v94e7d9fffa_b_9 + + org.jenkins-ci.plugins + bouncycastle-api + 2.30.1.78.1-248.ve27176eb_46cb_ + org.jenkins-ci.plugins @@ -111,23 +116,23 @@ THE SOFTWARE. org.jenkins-ci.plugins script-security - 1336.vf33a_a_9863911 + 1341.va_2819b_414686 org.jenkins-ci.plugins.workflow workflow-api - 1312.ve804c2f2d51e + 1322.v857eeeea_9902 org.jenkins-ci.plugins.workflow workflow-step-api - 657.v03b_e8115821b_ + 678.v3ee58b_469476 org.jenkins-ci.plugins.workflow workflow-support - 907.v6713a_ed8a_573 + 920.v59f71ce16f04 @@ -142,7 +147,7 @@ THE SOFTWARE. ${project.groupId} jenkins-test-harness - 2206.v84d5d81e76db_ + 2225.2229.vc4c7fcb_6673c test @@ -211,19 +216,19 @@ THE SOFTWARE. org.jenkins-ci.plugins cloudbees-folder - 6.940.v7fa_03b_f14759 + 6.942.vb_43318a_156b_2 test org.jenkins-ci.plugins credentials - 1337.v60b_d7b_c7b_c9f + 1371.vfee6b_095f0a_3 test org.jenkins-ci.plugins junit - 1265.v65b_14fa_f12f0 + 1279.v72cf99b_25c43 test @@ -241,13 +246,13 @@ THE SOFTWARE. org.jenkins-ci.plugins matrix-project - 830.v7ea_da_561b_a_34 + 832.va_66e270d2946 test org.jenkins-ci.plugins structs - 337.v1b_04ea_4df7c8 + 338.v848422169819 test @@ -321,7 +326,7 @@ THE SOFTWARE. org.jenkins-ci.main remoting - 4.12 + 3085.vc4c6977c075a jar ${project.build.outputDirectory}/old-remoting remoting-unsupported.jar @@ -329,7 +334,7 @@ THE SOFTWARE. io.jenkins.plugins design-library - 304.v44f7d19e8537 + 307.vecc0205ca_707 hpi ${project.build.outputDirectory}/plugins design-library.jpi diff --git a/test/src/test/java/hudson/PluginManagerTest.java b/test/src/test/java/hudson/PluginManagerTest.java index 336f4af6f7c5..91a236db0266 100644 --- a/test/src/test/java/hudson/PluginManagerTest.java +++ b/test/src/test/java/hudson/PluginManagerTest.java @@ -578,8 +578,7 @@ private void dynamicLoadAndDisable(String plugin) throws IOException, Interrupte Thread.sleep(100); done = true; for (UpdateCenterJob job : r.jenkins.getUpdateCenter().getJobs()) { - if (job instanceof UpdateCenter.DownloadJob) { - UpdateCenter.DownloadJob j = (UpdateCenter.DownloadJob) job; + if (job instanceof UpdateCenter.DownloadJob j) { assertFalse(j.status instanceof UpdateCenter.DownloadJob.Failure); done &= !(j.status instanceof UpdateCenter.DownloadJob.Pending || j.status instanceof UpdateCenter.DownloadJob.Installing); diff --git a/test/src/test/java/hudson/cli/Security3315Test.java b/test/src/test/java/hudson/cli/Security3315Test.java index 83d207a49c66..c48129cdfccf 100644 --- a/test/src/test/java/hudson/cli/Security3315Test.java +++ b/test/src/test/java/hudson/cli/Security3315Test.java @@ -34,7 +34,7 @@ public static List escapeHatchValues() { public Security3315Test(String allowWs) { this.allowWs = allowWs == null ? null : Boolean.valueOf(allowWs); - this.escapeHatch = new FlagRule<>(() -> CLIAction.ALLOW_WEBSOCKET, v -> { CLIAction.ALLOW_WEBSOCKET = v; }, this.allowWs); + this.escapeHatch = new FlagRule<>(() -> CLIAction.ALLOW_WEBSOCKET, v -> CLIAction.ALLOW_WEBSOCKET = v, this.allowWs); } @Test diff --git a/test/src/test/java/hudson/console/ConsoleAnnotatorTest.java b/test/src/test/java/hudson/console/ConsoleAnnotatorTest.java index 60b08b0936de..3e6d0ec82196 100644 --- a/test/src/test/java/hudson/console/ConsoleAnnotatorTest.java +++ b/test/src/test/java/hudson/console/ConsoleAnnotatorTest.java @@ -76,7 +76,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen // make sure raw console output doesn't include the garbage TextPage raw = (TextPage) r.createWebClient().goTo(b.getUrl() + "consoleText", "text/plain"); System.out.println(raw.getContent()); - String nl = System.getProperty("line.separator"); + String nl = System.lineSeparator(); assertTrue(raw.getContent().contains(nl + "---" + nl + "ooo" + nl + "ooo" + nl)); // there should be two 'ooo's @@ -96,7 +96,7 @@ public ConsoleAnnotator newInstance(FreeStyleBuild context) { } public static class DemoAnnotator extends ConsoleAnnotator { - private static final String ANNOTATE_TEXT = "ooo" + System.getProperty("line.separator"); + private static final String ANNOTATE_TEXT = "ooo" + System.lineSeparator(); @Override public ConsoleAnnotator annotate(FreeStyleBuild build, MarkupText text) { diff --git a/test/src/test/java/hudson/model/DirectoryBrowserSupportTest.java b/test/src/test/java/hudson/model/DirectoryBrowserSupportTest.java index 7b1bbdb7c9bd..e73cbec70359 100644 --- a/test/src/test/java/hudson/model/DirectoryBrowserSupportTest.java +++ b/test/src/test/java/hudson/model/DirectoryBrowserSupportTest.java @@ -1114,33 +1114,6 @@ public void windows_cannotViewAbsolutePath() throws Exception { MatcherAssert.assertThat(page.getWebResponse().getStatusCode(), equalTo(404)); } - @Test - @Issue("SECURITY-2481") - public void windows_canViewAbsolutePath_withEscapeHatch() throws Exception { - Assume.assumeTrue("can only be tested this on Windows", Functions.isWindows()); - - String originalValue = System.getProperty(DirectoryBrowserSupport.ALLOW_ABSOLUTE_PATH_PROPERTY_NAME); - System.setProperty(DirectoryBrowserSupport.ALLOW_ABSOLUTE_PATH_PROPERTY_NAME, "true"); - try { - Path targetTmpPath = Files.createTempFile("sec2481", "tmp"); - String content = "random data provided as fixed value"; - Files.writeString(targetTmpPath, content, StandardCharsets.UTF_8); - - JenkinsRule.WebClient wc = j.createWebClient().withThrowExceptionOnFailingStatusCode(false); - Page page = wc.goTo("userContent/" + targetTmpPath.toAbsolutePath() + "/*view*", null); - - MatcherAssert.assertThat(page.getWebResponse().getStatusCode(), equalTo(200)); - MatcherAssert.assertThat(page.getWebResponse().getContentAsString(), containsString(content)); - } finally { - if (originalValue == null) { - System.clearProperty(DirectoryBrowserSupport.ALLOW_ABSOLUTE_PATH_PROPERTY_NAME); - } else { - System.setProperty(DirectoryBrowserSupport.ALLOW_ABSOLUTE_PATH_PROPERTY_NAME, originalValue); - } - } - - } - @Test @Issue("SECURITY-1807") public void tmpNotListed() throws Exception { diff --git a/test/src/test/java/hudson/model/DownloadService2Test.java b/test/src/test/java/hudson/model/DownloadService2Test.java index 0b4fe687d3eb..73a15c64be6d 100644 --- a/test/src/test/java/hudson/model/DownloadService2Test.java +++ b/test/src/test/java/hudson/model/DownloadService2Test.java @@ -60,7 +60,7 @@ private static void assertRoots(String expected, String file) throws Exception { URL resource = DownloadService2Test.class.getResource(file); assertNotNull(file, resource); JSONObject json = JSONObject.fromObject(DownloadService.loadJSONHTML(resource)); - @SuppressWarnings("unchecked") Set keySet = json.keySet(); + Set keySet = json.keySet(); assertEquals(expected, new TreeSet<>(keySet).toString()); } diff --git a/test/src/test/java/hudson/model/DownloadServiceTest.java b/test/src/test/java/hudson/model/DownloadServiceTest.java index f5fc53730029..cb9337c72096 100644 --- a/test/src/test/java/hudson/model/DownloadServiceTest.java +++ b/test/src/test/java/hudson/model/DownloadServiceTest.java @@ -34,7 +34,7 @@ public void testLoadJSON() throws Exception { private static void assertRoots(String expected, URL resource) throws Exception { assertNotNull(resource); JSONObject json = JSONObject.fromObject(DownloadService.loadJSON(resource)); - @SuppressWarnings("unchecked") Set keySet = json.keySet(); + Set keySet = json.keySet(); assertEquals(expected, new TreeSet<>(keySet).toString()); } diff --git a/test/src/test/java/hudson/model/ParametersDefinitionPropertyTest.java b/test/src/test/java/hudson/model/ParametersDefinitionPropertyTest.java index 0f06cd43a7f6..54d3b3a0c847 100644 --- a/test/src/test/java/hudson/model/ParametersDefinitionPropertyTest.java +++ b/test/src/test/java/hudson/model/ParametersDefinitionPropertyTest.java @@ -24,11 +24,19 @@ package hudson.model; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; +import hudson.security.FullControlOnceLoggedInAuthorizationStrategy; +import java.net.URL; import java.util.Locale; import java.util.logging.Level; import net.sf.json.JSONObject; +import org.htmlunit.HttpMethod; +import org.htmlunit.WebRequest; +import org.htmlunit.WebResponse; import org.junit.Rule; import org.junit.Test; import org.jvnet.hudson.test.Issue; @@ -92,4 +100,27 @@ public ParameterDefinition newInstance(StaplerRequest req, JSONObject formData) } + @Issue("JENKINS-66105") + @Test + public void statusCodes() throws Exception { + r.jenkins.setSecurityRealm(r.createDummySecurityRealm()); + r.jenkins.setAuthorizationStrategy(new FullControlOnceLoggedInAuthorizationStrategy()); + FreeStyleProject p = r.createFreeStyleProject("p"); + ParametersDefinitionProperty pdp = new ParametersDefinitionProperty(new StringParameterDefinition("K")); + p.addProperty(pdp); + p.setConcurrentBuild(true); + p.setAssignedLabel(Label.get("nonexistent")); // force it to stay in queue + JenkinsRule.WebClient wc = r.createWebClient(); + wc.withBasicApiToken("dev"); + assertThat("initially 201 Created queue item", buildWithParameters(wc, "v1").getStatusCode(), is(201)); + WebResponse rsp = buildWithParameters(wc, "v1"); + assertThat("then 303 See Other → 200 OK", rsp.getStatusCode(), is(200)); + assertThat("offers advice on API", rsp.getContentAsString(), containsString("api/json?tree=")); + assertThat("201 Created queue item for different key", buildWithParameters(wc, "v2").getStatusCode(), is(201)); + } + + private WebResponse buildWithParameters(JenkinsRule.WebClient wc, String value) throws Exception { + return wc.getPage(new WebRequest(new URL(wc.getContextPath() + "job/p/buildWithParameters?K=" + value), HttpMethod.POST)).getWebResponse(); + } + } diff --git a/test/src/test/java/hudson/model/ProjectTest.java b/test/src/test/java/hudson/model/ProjectTest.java index 82d9266e0e62..e3f2d84493e3 100644 --- a/test/src/test/java/hudson/model/ProjectTest.java +++ b/test/src/test/java/hudson/model/ProjectTest.java @@ -644,15 +644,13 @@ public void testDoDisable() throws Exception { JenkinsRule.WebClient wc = j.createWebClient(); wc.withBasicCredentials(user.getId(), "password"); - HtmlPage p = wc.goTo(project.getUrl()); - List forms = p.getForms(); - for (HtmlForm form : forms) { - if ("disable".equals(form.getAttribute("action"))) { - j.submit(form); - } - } - assertTrue("Project should be disabled.", project.isDisabled()); + HtmlPage p = wc.getPage(project, "configure"); + HtmlForm form = p.getFormByName("config"); + form.getInputByName("enable").click(); + j.submit(form); + + assertTrue("Project should be disabled.", project.isDisabled()); } @Test diff --git a/test/src/test/java/hudson/model/RunTest.java b/test/src/test/java/hudson/model/RunTest.java index c59245c78c2c..b6a145857020 100644 --- a/test/src/test/java/hudson/model/RunTest.java +++ b/test/src/test/java/hudson/model/RunTest.java @@ -157,7 +157,7 @@ private void ensureXssIsPrevented(FreeStyleProject upProject, String validationP HtmlPage htmlPage = wc.goTo(upProject.getUrl()); // trigger the tooltip display - htmlPage.executeJavaScript("document.querySelector('#buildHistory table .build-badge svg')._tippy.show()"); + htmlPage.executeJavaScript("document.querySelector('#jenkins-build-history .app-builds-container__item__inner__controls svg')._tippy.show()"); wc.waitForBackgroundJavaScript(500); ScriptResult result = htmlPage.executeJavaScript("document.querySelector('.tippy-content').innerHTML;"); Object jsResult = result.getJavaScriptResult(); diff --git a/test/src/test/java/hudson/model/SlaveTest.java b/test/src/test/java/hudson/model/SlaveTest.java index b66130bfc4ea..f7177b9d08fc 100644 --- a/test/src/test/java/hudson/model/SlaveTest.java +++ b/test/src/test/java/hudson/model/SlaveTest.java @@ -160,7 +160,7 @@ public void shouldNotEscapeJnlpSlavesResources() throws Exception { private void assertJnlpJarUrlFails(@NonNull Slave slave, @NonNull String url) throws Exception { // Raw access to API Slave.JnlpJar jnlpJar = slave.getComputer().getJnlpJars(url); - assertThrows(MalformedURLException.class, () -> jnlpJar.getURL()); + assertThrows(MalformedURLException.class, jnlpJar::getURL); } private void assertJnlpJarUrlIsAllowed(@NonNull Slave slave, @NonNull String url) throws Exception { diff --git a/test/src/test/java/hudson/model/UserPropertyTest.java b/test/src/test/java/hudson/model/UserPropertyTest.java index 0d2b7d5b1374..91c977d4ec28 100644 --- a/test/src/test/java/hudson/model/UserPropertyTest.java +++ b/test/src/test/java/hudson/model/UserPropertyTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; +import static org.htmlunit.html.HtmlFormUtil.submit; import static org.junit.Assert.assertNotNull; import java.io.File; @@ -35,12 +36,17 @@ public class UserPropertyTest { @Rule public JenkinsRule j = new JenkinsRule(); + public User configRoundtrip(User u) throws Exception { + submit(j.createWebClient().goTo(u.getUrl()+"/account/").getFormByName("config")); + return u; + } + @Test @Issue("JENKINS-9062") public void test() throws Exception { User u = User.get("foo"); u.addProperty(new UserProperty1()); - j.configRoundtrip(u); + configRoundtrip(u); for (UserProperty p : u.getAllProperties()) assertNotNull(p); } @@ -82,7 +88,7 @@ public void nestedUserReference() throws Exception { List fileLines = Files.readAllLines(testFile.toPath(), StandardCharsets.US_ASCII); assertThat(fileLines, hasSize(1)); - j.configRoundtrip(user); + configRoundtrip(user); user = User.get("nestedUserReference", false, Collections.emptyMap()); assertThat("nested reference should exist after user configuration change", user, nestedUserSet()); diff --git a/test/src/test/java/hudson/model/UserTest.java b/test/src/test/java/hudson/model/UserTest.java index 4f5d6e8f4365..b27adbdc15e7 100644 --- a/test/src/test/java/hudson/model/UserTest.java +++ b/test/src/test/java/hudson/model/UserTest.java @@ -64,12 +64,14 @@ import jenkins.model.IdStrategy; import jenkins.model.Jenkins; import jenkins.security.ApiTokenProperty; +import org.htmlunit.FailingHttpStatusCodeException; import org.htmlunit.WebAssert; import org.htmlunit.WebRequest; import org.htmlunit.WebResponse; import org.htmlunit.html.HtmlForm; import org.htmlunit.html.HtmlPage; import org.htmlunit.util.WebConnectionWrapper; +import org.jenkinsci.plugins.matrixauth.PermissionEntry; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -403,20 +405,23 @@ public void testDoConfigSubmit() throws Exception { User user = realm.createAccount("John Smith", "password"); User user2 = realm.createAccount("John Smith2", "password"); user2.save(); - auth.add(Jenkins.ADMINISTER, user.getId()); - auth.add(Jenkins.READ, user2.getId()); + auth.add(Jenkins.ADMINISTER, PermissionEntry.user(user.getId())); + auth.add(Jenkins.READ, PermissionEntry.user(user2.getId())); SecurityContextHolder.getContext().setAuthentication(user.impersonate2()); - HtmlForm form = j.createWebClient().withBasicCredentials(user.getId(), "password").goTo(user2.getUrl() + "/configure").getFormByName("config"); + HtmlForm form = j.createWebClient().withBasicCredentials(user.getId(), "password").goTo(user2.getUrl() + "/account/").getFormByName("config"); form.getInputByName("_.fullName").setValue("Alice Smith"); j.submit(form); assertEquals("User should have full name Alice Smith.", "Alice Smith", user2.getFullName()); SecurityContextHolder.getContext().setAuthentication(user2.impersonate2()); - assertThrows("User should not have permission to configure another user.", AccessDeniedException3.class, () -> user.doConfigSubmit(null, null)); - form = j.createWebClient().withBasicCredentials(user2.getId(), "password").goTo(user2.getUrl() + "/configure").getFormByName("config"); + try (JenkinsRule.WebClient webClient = j.createWebClient().withBasicCredentials(user2.getId(), "password")) { + FailingHttpStatusCodeException failingHttpStatusCodeException = assertThrows("User should not have permission to configure another user.", FailingHttpStatusCodeException.class, () -> webClient.goTo(user.getUrl() + "/account/")); + assertThat(failingHttpStatusCodeException.getStatusCode(), is(403)); + form = webClient.goTo(user2.getUrl() + "/account/").getFormByName("config"); + form.getInputByName("_.fullName").setValue("John"); + j.submit(form); + } - form.getInputByName("_.fullName").setValue("John"); - j.submit(form); - assertEquals("User should be albe to configure himself.", "John", user2.getFullName()); + assertEquals("User should be able to configure himself.", "John", user2.getFullName()); } @@ -771,7 +776,7 @@ public WebResponse getResponse(WebRequest request) throws IOException { return r; } }; - wc.login("alice").goTo("me/configure"); + wc.login("alice").goTo("me/account/"); assertThat(failingResources, empty()); } diff --git a/test/src/test/java/hudson/model/queue/BuildKeepsRunningWhenFaultySubTasksTest.java b/test/src/test/java/hudson/model/queue/BuildKeepsRunningWhenFaultySubTasksTest.java index c296c2bd6871..7bb9b4d442c6 100644 --- a/test/src/test/java/hudson/model/queue/BuildKeepsRunningWhenFaultySubTasksTest.java +++ b/test/src/test/java/hudson/model/queue/BuildKeepsRunningWhenFaultySubTasksTest.java @@ -107,6 +107,7 @@ public Label getAssignedLabel() { return null; } + @Deprecated @Override public Node getLastBuiltOn() { return null; diff --git a/test/src/test/java/hudson/scm/AbstractScmTagActionTest.java b/test/src/test/java/hudson/scm/AbstractScmTagActionTest.java index 4fe53f261657..1df03bfacd64 100644 --- a/test/src/test/java/hudson/scm/AbstractScmTagActionTest.java +++ b/test/src/test/java/hudson/scm/AbstractScmTagActionTest.java @@ -66,7 +66,7 @@ private String buildAndExtractTooltipAttribute(FreeStyleProject p) throws Except HtmlPage page = wc.getPage(p); - DomElement buildHistory = page.getElementById("buildHistory"); + DomElement buildHistory = page.getElementById("buildHistoryPage"); DomNodeList imgs = buildHistory.getElementsByTagName("img"); HtmlImage tagImage = (HtmlImage) imgs.stream() .filter(i -> i.getAttribute("class").contains("icon-save")) diff --git a/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmFIPSTest.java b/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmFIPSTest.java index 155e9cab1adc..ab1352807117 100644 --- a/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmFIPSTest.java +++ b/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmFIPSTest.java @@ -25,25 +25,30 @@ package hudson.security; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertThrows; +import hudson.logging.LogRecorder; +import hudson.logging.LogRecorderManager; import hudson.model.User; import hudson.security.HudsonPrivateSecurityRealm.Details; +import java.lang.reflect.Method; +import java.util.List; import java.util.logging.Level; +import java.util.logging.LogRecord; +import jenkins.model.Jenkins; import org.hamcrest.Matcher; +import org.hamcrest.Matchers; import org.htmlunit.FailingHttpStatusCodeException; -import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; -import org.junit.rules.TestRule; -import org.jvnet.hudson.test.FlagRule; import org.jvnet.hudson.test.For; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.JenkinsRule.WebClient; -import org.jvnet.hudson.test.LoggerRule; +import org.jvnet.hudson.test.RealJenkinsRule; @For(HudsonPrivateSecurityRealm.class) @@ -52,18 +57,18 @@ public class HudsonPrivateSecurityRealmFIPSTest { // the jbcrypt encoded for of "a" without the quotes private static final String JBCRYPT_ENCODED_PASSWORD = "#jbcrypt:$2a$06$m0CrhHm10qJ3lXRY.5zDGO3rS2KdeeWLuGmsfGlMfOxih58VYVfxe"; - @ClassRule - // do not use the FIPS140 class here as that initializes the field before we set the property! - public static TestRule flagRule = FlagRule.systemProperty("jenkins.security.FIPS140.COMPLIANCE", "true"); + private static final String LOG_RECORDER_NAME = "HPSR_LOG_RECORDER"; @Rule - public LoggerRule lr = new LoggerRule().record(HudsonPrivateSecurityRealm.class, Level.WARNING).capture(5); - - @Rule - public JenkinsRule j = new JenkinsRule(); + public RealJenkinsRule rjr = new RealJenkinsRule().includeTestClasspathPlugins(false) + .javaOptions("-Xmx256M", "-Djenkins.security.FIPS140.COMPLIANCE=true"); @Test - public void generalLogin() throws Exception { + public void generalLogin() throws Throwable { + rjr.then(HudsonPrivateSecurityRealmFIPSTest::generalLoginStep); + } + + private static void generalLoginStep(JenkinsRule j) throws Exception { HudsonPrivateSecurityRealm securityRealm = new HudsonPrivateSecurityRealm(false, false, null); j.jenkins.setSecurityRealm(securityRealm); @@ -75,37 +80,50 @@ public void generalLogin() throws Exception { String hashedPassword = u1.getProperty(Details.class).getPassword(); assertThat(hashedPassword, startsWith("$PBKDF2$HMACSHA512:210000:")); - WebClient wc = j.createWebClient(); - wc.login("user", "password"); - - assertThrows(FailingHttpStatusCodeException.class, () -> wc.login("user", "wrongPass")); + try (WebClient wc = j.createWebClient()) { + wc.login("user", "password"); + assertThrows(FailingHttpStatusCodeException.class, () -> wc.login("user", "wrongPass")); + } } @Test - public void userCreationWithHashedPasswords() throws Exception { + public void userCreationWithHashedPasswords() throws Throwable { + rjr.then(HudsonPrivateSecurityRealmFIPSTest::userCreationWithHashedPasswordsStep); + } + + private static void userCreationWithHashedPasswordsStep(JenkinsRule j) throws Exception { + setupLogRecorder(); HudsonPrivateSecurityRealm securityRealm = new HudsonPrivateSecurityRealm(false, false, null); j.jenkins.setSecurityRealm(securityRealm); // "password" after it has gone through the KDF securityRealm.createAccountWithHashedPassword("user_hashed", "$PBKDF2$HMACSHA512:210000:ffbb207b847010af98cdd2b09c79392c$f67c3b985daf60db83a9088bc2439f7b77016d26c1439a9877c4f863c377272283ce346edda4578a5607ea620a4beb662d853b800f373297e6f596af797743a6"); - WebClient wc = j.createWebClient(); - // login should succeed - wc.login("user_hashed", "password"); - - assertThrows(FailingHttpStatusCodeException.class, () -> wc.login("user_hashed", "password2")); - assertThat(lr, not(hasIncorrectHashingLogEntry())); + try (WebClient wc = j.createWebClient()) { + // login should succeed + wc.login("user_hashed", "password"); + assertThrows(FailingHttpStatusCodeException.class, () -> wc.login("user_hashed", "password2")); + } + assertThat(getLogRecords(), not(hasItem(incorrectHashingLogEntry()))); } @Test - public void userLoginAfterEnablingFIPS() throws Exception { + public void userLoginAfterEnablingFIPS() throws Throwable { + rjr.then(HudsonPrivateSecurityRealmFIPSTest::userLoginAfterEnablingFIPSStep); + } + + private static void userLoginAfterEnablingFIPSStep(JenkinsRule j) throws Exception { + setupLogRecorder(); HudsonPrivateSecurityRealm securityRealm = new HudsonPrivateSecurityRealm(false, false, null); j.jenkins.setSecurityRealm(securityRealm); User u1 = securityRealm.createAccount("user", "a"); u1.setFullName("A User"); // overwrite the password property using an password created using an incorrect algorithm - u1.addProperty(Details.fromHashedPassword(JBCRYPT_ENCODED_PASSWORD)); + Method m = Details.class.getDeclaredMethod("fromHashedPassword", String.class); + m.setAccessible(true); + Details d = (Details) m.invoke(null, JBCRYPT_ENCODED_PASSWORD); + u1.addProperty(d); u1.save(); assertThat(u1.getProperty(Details.class).getPassword(), is(JBCRYPT_ENCODED_PASSWORD)); @@ -113,11 +131,16 @@ public void userLoginAfterEnablingFIPS() throws Exception { try (WebClient wc = j.createWebClient()) { assertThrows(FailingHttpStatusCodeException.class, () -> wc.login("user", "a")); } - assertThat(lr, hasIncorrectHashingLogEntry()); + assertThat(getLogRecords(), hasItem(incorrectHashingLogEntry())); } @Test - public void userCreationWithJBCryptPasswords() throws Exception { + public void userCreationWithJBCryptPasswords() throws Throwable { + rjr.then(HudsonPrivateSecurityRealmFIPSTest::userCreationWithJBCryptPasswordsStep); + + } + + private static void userCreationWithJBCryptPasswordsStep(JenkinsRule j) throws Exception { HudsonPrivateSecurityRealm securityRealm = new HudsonPrivateSecurityRealm(false, false, null); IllegalArgumentException illegalArgumentException = assertThrows(IllegalArgumentException.class, @@ -126,8 +149,21 @@ public void userCreationWithJBCryptPasswords() throws Exception { is("The hashed password was hashed with an incorrect algorithm. Jenkins is expecting $PBKDF2")); } - private static Matcher hasIncorrectHashingLogEntry() { - return LoggerRule.recorded(is( - "A password appears to be stored (or is attempting to be stored) that was created with a different hashing/encryption algorithm, check the FIPS-140 state of the system has not changed inadvertently")); + private static Matcher incorrectHashingLogEntry() { + return Matchers.hasProperty("message", + is("A password appears to be stored (or is attempting to be stored) that was created with a different hashing/encryption algorithm, check the FIPS-140 state of the system has not changed inadvertently")); + } + + private static List getLogRecords() { + return Jenkins.get().getLog().getLogRecorder(LOG_RECORDER_NAME).getLogRecords(); + } + + private static void setupLogRecorder() { + LogRecorderManager lrm = Jenkins.get().getLog(); + LogRecorder lr = new LogRecorder(LOG_RECORDER_NAME); + LogRecorder.Target target = new LogRecorder.Target(HudsonPrivateSecurityRealm.class.getName(), Level.WARNING); + lr.setLoggers(List.of(target)); + + lrm.getRecorders().add(lr); } } diff --git a/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java b/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java index d0f58f92d5ec..92745bf5f9b0 100644 --- a/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java +++ b/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java @@ -651,7 +651,7 @@ public void changingPassword_mustInvalidateAllSessions() throws Exception { wc_anotherTab.login(alice.getId()); assertUserConnected(wc_anotherTab, alice.getId()); - HtmlPage configurePage = wc.goTo(alice.getUrl() + "/configure"); + HtmlPage configurePage = wc.goTo(alice.getUrl() + "/security/"); HtmlPasswordInput password1 = configurePage.getElementByName("user.password"); HtmlPasswordInput password2 = configurePage.getElementByName("user.password2"); @@ -683,7 +683,7 @@ public void notChangingPassword_hasNoImpactOnSeed() throws Exception { wc_anotherTab.login(alice.getId()); assertUserConnected(wc_anotherTab, alice.getId()); - HtmlPage configurePage = wc.goTo(alice.getUrl() + "/configure"); + HtmlPage configurePage = wc.goTo(alice.getUrl() + "/security/"); // not changing password this time HtmlForm form = configurePage.getFormByName("config"); j.submit(form); @@ -713,7 +713,7 @@ public void changingPassword_withSeedDisable_hasNoImpact() throws Exception { wc_anotherTab.login(alice.getId()); assertUserConnected(wc_anotherTab, alice.getId()); - HtmlPage configurePage = wc.goTo(alice.getUrl() + "/configure"); + HtmlPage configurePage = wc.goTo(alice.getUrl() + "/security/"); HtmlPasswordInput password1 = configurePage.getElementByName("user.password"); HtmlPasswordInput password2 = configurePage.getElementByName("user.password2"); diff --git a/test/src/test/java/hudson/slaves/JNLPLauncherRealTest.java b/test/src/test/java/hudson/slaves/JNLPLauncherRealTest.java index 544e8383de8c..557231f5d140 100644 --- a/test/src/test/java/hudson/slaves/JNLPLauncherRealTest.java +++ b/test/src/test/java/hudson/slaves/JNLPLauncherRealTest.java @@ -49,13 +49,14 @@ public class JNLPLauncherRealTest { private static final String STATIC_AGENT_NAME = "static"; - @Rule public RealJenkinsRule rr = new RealJenkinsRule().includeTestClasspathPlugins(false).withColor(PrefixedOutputStream.Color.BLUE); + @Rule public RealJenkinsRule rr = new RealJenkinsRule().withColor(PrefixedOutputStream.Color.BLUE); @Rule public InboundAgentRule iar = new InboundAgentRule(); @Issue("JEP-230") @Test public void smokes() throws Throwable { - /* Since RealJenkinsRuleInit.jpi will load detached plugins, to reproduce a failure use: + /* Since RealJenkinsRuleInit.jpi will load detached and test scope plugins, to reproduce a failure use: + rr.includeTestClasspathPlugins(false); FileUtils.touch(new File(rr.getHome(), "plugins/instance-identity.jpi.disabled")); */ then(false); diff --git a/test/src/test/java/hudson/tasks/MavenTest.java b/test/src/test/java/hudson/tasks/MavenTest.java index dbf745b672d9..bd366adce71d 100644 --- a/test/src/test/java/hudson/tasks/MavenTest.java +++ b/test/src/test/java/hudson/tasks/MavenTest.java @@ -66,7 +66,6 @@ import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.ToolInstallations; -import org.jvnet.hudson.test.recipes.WithTimeout; import org.kohsuke.stapler.jelly.JellyFacet; /** @@ -191,7 +190,7 @@ private void verify() throws Exception { assertNotNull(isp.installers.get(MavenInstaller.class)); } - @Test @WithTimeout(500) public void sensitiveParameters() throws Exception { + @Test public void sensitiveParameters() throws Exception { FreeStyleProject project = j.createFreeStyleProject(); ParametersDefinitionProperty pdb = new ParametersDefinitionProperty( new StringParameterDefinition("string", "defaultValue", "string description"), diff --git a/test/src/test/java/hudson/util/FormFieldValidatorTest.java b/test/src/test/java/hudson/util/FormFieldValidatorTest.java index bdbb76946288..6e1b52c45c58 100644 --- a/test/src/test/java/hudson/util/FormFieldValidatorTest.java +++ b/test/src/test/java/hudson/util/FormFieldValidatorTest.java @@ -25,13 +25,19 @@ package hudson.util; +import static org.hamcrest.CoreMatchers.allOf; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; + import hudson.model.AbstractProject; import hudson.model.FreeStyleProject; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Builder; import hudson.tasks.Publisher; +import hudson.tasks.Recorder; import java.io.IOException; +import java.util.concurrent.atomic.AtomicInteger; import org.htmlunit.ScriptResult; import org.htmlunit.WebResponseListener; import org.htmlunit.html.HtmlPage; @@ -42,6 +48,7 @@ import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.TestExtension; import org.kohsuke.stapler.DataBoundConstructor; +import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; import org.xml.sax.SAXException; @@ -134,7 +141,7 @@ public boolean isApplicable(Class jobType) { @Issue("JENKINS-3382") public void negative() throws Exception { BrokenFormValidatorBuilder.DescriptorImpl d = new BrokenFormValidatorBuilder.DescriptorImpl(); - Publisher.all().add(d); + Recorder.all().add(d); try { FreeStyleProject p = j.createFreeStyleProject(); p.getPublishersList().add(new BrokenFormValidatorBuilder()); @@ -152,4 +159,120 @@ public void negative() throws Exception { Publisher.all().remove(d); } } + + @Issue("JENKINS-73404") + @Test + public void testValidationforComponents() throws Exception { + FreeStyleProject p = j.createFreeStyleProject(); + p.getBuildersList().add(new ValidatingDescribable()); + try (JenkinsRule.WebClient wc = j.createWebClient()) { + HtmlPage page = wc.getPage(p, "configure"); + assertThat(page.asNormalizedText(), allOf( + containsString("FormValidation: Password (empty)"), + containsString("FormValidation: Password (populated)"), + containsString("FormValidation: Textarea"), + containsString("FormValidation: SecretTextarea (empty)"), + containsString("FormValidation: SecretTextarea (populated)"))); + + } + + } + + public static class ValidatingDescribable extends Builder { + + private Secret emptyPassword; + // give the secret some data so that it is hidden and not a regular field! + private Secret populatedPassword = Secret.fromString("secret!"); + private String textarea; + private Secret emptySecretTextarea; + private Secret populatedSecretTextarea = Secret.fromString("sensitive!");; + + @DataBoundConstructor + public ValidatingDescribable() { + } + + public Secret getEmptyPassword() { + return emptyPassword; + } + + @DataBoundSetter + public void setEmptyPassword(Secret emptyPassword) { + this.emptyPassword = emptyPassword; + } + + public Secret getPopulatedPassword() { + return populatedPassword; + } + + @DataBoundSetter + public void setPopulatedPassword(Secret populatedPassword) { + this.populatedPassword = populatedPassword; + } + + public String getTextarea() { + return textarea; + } + + @DataBoundSetter + public void setTextarea(String textarea) { + this.textarea = textarea; + } + + public Secret getEmptySecretTextarea() { + return emptySecretTextarea; + } + + @DataBoundSetter + public void setEmptySecretTextarea(Secret emptySecretTextarea) { + this.emptySecretTextarea = emptySecretTextarea; + } + + public Secret getPopulatedSecretTextarea() { + return populatedSecretTextarea; + } + + @DataBoundSetter + public void setPopulatedSecretTextarea(Secret populatedSecretTextarea) { + this.populatedSecretTextarea = populatedSecretTextarea; + } + + @TestExtension + public static class DescriptorImpl extends BuildStepDescriptor { + // not used for the test class but useful for interactive debugging to check the validation has been called + AtomicInteger i = new AtomicInteger(); + + @Override + public String getDisplayName() { + return "Validation Testing"; + } + + public FormValidation doCheckEmptyPassword(@QueryParameter String value) { + return FormValidation.ok("FormValidation: Password (empty)" + i.getAndIncrement()); + } + + public FormValidation doCheckPopulatedPassword(@QueryParameter String value) { + return FormValidation.ok("FormValidation: Password (populated)" + i.getAndIncrement()); + } + + public FormValidation doCheckTextarea(@QueryParameter String value) { + return FormValidation.ok("FormValidation: Textarea" + i.getAndIncrement()); + } + + public FormValidation doCheckEmptySecretTextarea(@QueryParameter String value) { + return FormValidation.ok("FormValidation: SecretTextarea (empty)" + i.getAndIncrement()); + } + + public FormValidation doCheckPopulatedSecretTextarea(@QueryParameter String value) { + return FormValidation.ok("FormValidation: SecretTextarea (populated)" + i.getAndIncrement()); + } + + @Override + public boolean isApplicable(Class jobType) { + return true; + } + + } + + } + } diff --git a/test/src/test/java/jenkins/ClassPathTest.java b/test/src/test/java/jenkins/ClassPathTest.java index 01b29253e0cc..4629a8f65faf 100644 --- a/test/src/test/java/jenkins/ClassPathTest.java +++ b/test/src/test/java/jenkins/ClassPathTest.java @@ -26,9 +26,7 @@ import java.io.File; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -46,7 +44,7 @@ public class ClassPathTest { @Rule public ErrorCollector errors = new ErrorCollector(); - private static final Set KNOWN_VIOLATIONS = Collections.unmodifiableSet(new HashSet<>(Arrays.asList( + private static final Set KNOWN_VIOLATIONS = Set.of( // TODO duplicated in [jline-2.14.6.jar, jansi-1.11.jar] "org/fusesource/hawtjni/runtime/Callback.class", "org/fusesource/hawtjni/runtime/JNIEnv.class", @@ -75,7 +73,7 @@ public class ClassPathTest { "org/fusesource/jansi/internal/Kernel32$SMALL_RECT.class", "org/fusesource/jansi/internal/Kernel32.class", "org/fusesource/jansi/internal/WindowsSupport.class", - "org/fusesource/jansi/WindowsAnsiOutputStream.class"))); + "org/fusesource/jansi/WindowsAnsiOutputStream.class"); @Issue("JENKINS-46754") @Test diff --git a/test/src/test/java/jenkins/management/AdministrativeMonitorsDecoratorTest.java b/test/src/test/java/jenkins/management/AdministrativeMonitorsDecoratorTest.java index 37d28638e65b..691b9d2c8868 100644 --- a/test/src/test/java/jenkins/management/AdministrativeMonitorsDecoratorTest.java +++ b/test/src/test/java/jenkins/management/AdministrativeMonitorsDecoratorTest.java @@ -24,15 +24,22 @@ package jenkins.management; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; import hudson.ExtensionList; import hudson.model.AdministrativeMonitor; import hudson.model.User; +import hudson.security.ACL; +import hudson.security.Permission; import jenkins.model.Jenkins; import org.jenkinsci.Symbol; import org.junit.Rule; import org.junit.Test; +import org.jvnet.hudson.test.FlagRule; import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.MockAuthorizationStrategy; @@ -43,6 +50,9 @@ public class AdministrativeMonitorsDecoratorTest { @Rule public JenkinsRule j = new JenkinsRule(); + @Rule + public final FlagRule managePermissionRule = FlagRule.systemProperty("jenkins.security.ManagePermission", "true"); + @Test public void ensureAdminMonitorsAreNotRunPerNonAdminPage() throws Exception { j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); @@ -131,4 +141,80 @@ public boolean isSecurity() { return true; } } + + @Test + public void ensureAdminMonitorsCanBeSeenByManagers() { + j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); + var managerLogin = "manager"; + var systemReadLogin = "system-reader"; + var managerUser = User.getById(managerLogin, true); + var systemReadUser = User.getById(systemReadLogin, true); + + j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy() + .grant(Jenkins.MANAGE, Jenkins.READ).everywhere().to(managerLogin) + .grant(Jenkins.READ, Jenkins.SYSTEM_READ).everywhere().to(systemReadLogin) + ); + + try (var ignored = ACL.as2(managerUser.impersonate2())) { + assertThat(Jenkins.get().getActiveAdministrativeMonitors(), hasItem(instanceOf(ManagerAdministrativeMonitor.class))); + } + try (var ignored = ACL.as2(systemReadUser.impersonate2())) { + assertThat(Jenkins.get().getActiveAdministrativeMonitors(), not(hasItem(instanceOf(ManagerAdministrativeMonitor.class)))); + } + } + + @TestExtension("ensureAdminMonitorsCanBeSeenByManagers") + public static class ManagerAdministrativeMonitor extends AdministrativeMonitor { + @Override + public Permission getRequiredPermission() { + return Jenkins.MANAGE; + } + + @Override + public boolean isActivated() { + return true; + } + } + + @Test + public void ensureAdminMonitorsCanBeSeenByManagersOrSystemReaders() { + j.jenkins.setSecurityRealm(j.createDummySecurityRealm()); + var managerLogin = "manager"; + var systemReadLogin = "system-reader"; + var managerUser = User.getById(managerLogin, true); + var systemReadUser = User.getById(systemReadLogin, true); + + j.jenkins.setAuthorizationStrategy(new MockAuthorizationStrategy() + .grant(Jenkins.MANAGE, Jenkins.READ).everywhere().to(managerLogin) + .grant(Jenkins.READ, Jenkins.SYSTEM_READ).everywhere().to(systemReadLogin) + ); + + try (var ignored = ACL.as2(managerUser.impersonate2())) { + assertThat(Jenkins.get().getActiveAdministrativeMonitors(), hasItem(instanceOf(ManagerOrSystemReaderAdministrativeMonitor.class))); + } + try (var ignored = ACL.as2(systemReadUser.impersonate2())) { + assertThat(Jenkins.get().getActiveAdministrativeMonitors(), hasItem(instanceOf(ManagerOrSystemReaderAdministrativeMonitor.class))); + } + } + + @TestExtension("ensureAdminMonitorsCanBeSeenByManagersOrSystemReaders") + public static class ManagerOrSystemReaderAdministrativeMonitor extends AdministrativeMonitor { + + private static final Permission[] REQUIRED_ANY_PERMISSIONS = {Jenkins.MANAGE, Jenkins.SYSTEM_READ}; + + @Override + public void checkRequiredPermission() { + Jenkins.get().checkAnyPermission(REQUIRED_ANY_PERMISSIONS); + } + + @Override + public boolean hasRequiredPermission() { + return Jenkins.get().hasAnyPermission(REQUIRED_ANY_PERMISSIONS); + } + + @Override + public boolean isActivated() { + return true; + } + } } diff --git a/test/src/test/java/jenkins/model/GlobalComputerRetentionCheckIntervalConfigurationTest.java b/test/src/test/java/jenkins/model/GlobalComputerRetentionCheckIntervalConfigurationTest.java new file mode 100644 index 000000000000..9e7cf9f4ff81 --- /dev/null +++ b/test/src/test/java/jenkins/model/GlobalComputerRetentionCheckIntervalConfigurationTest.java @@ -0,0 +1,146 @@ +package jenkins.model; + +import static org.junit.Assert.assertEquals; + +import hudson.model.Descriptor; +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.util.logging.Level; +import net.sf.json.JSONObject; +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.LoggerRule; +import org.kohsuke.stapler.Stapler; + + +/** + * Ensure interval bounds are enforced when re-configuring and loading from disk. Also ensure default value handling. + * + * @author Jakob Ackermann + */ +public class GlobalComputerRetentionCheckIntervalConfigurationTest { + @Rule + public JenkinsRule j = new JenkinsRule(); + @Rule + public LoggerRule logging = new LoggerRule(); + + private File getConfig(GlobalComputerRetentionCheckIntervalConfiguration c) { + return new File(j.jenkins.getRootDir(), c.getId() + ".xml"); + } + + private void recordWarnings() { + logging.record(GlobalComputerRetentionCheckIntervalConfiguration.class, Level.INFO).capture(100); + } + + @Test + public void bootWithMissingCfg() { + recordWarnings(); + GlobalComputerRetentionCheckIntervalConfiguration c = new GlobalComputerRetentionCheckIntervalConfiguration(); + c.load(); + assertEquals("default", 60, c.getComputerRetentionCheckInterval()); + assertEquals("no fallback message", logging.getRecords().size(), 0); + } + + private void writeConfig(GlobalComputerRetentionCheckIntervalConfiguration c, int interval) throws IOException { + String bad = "" + + "\n" + + "\n" + + " " + interval + "\n" + + ""; + Files.writeString(getConfig(c).toPath(), bad, StandardCharsets.UTF_8); + } + + private void checkUsesFallbackAfterLoadOf(int interval) throws IOException { + recordWarnings(); + GlobalComputerRetentionCheckIntervalConfiguration c = new GlobalComputerRetentionCheckIntervalConfiguration(); + writeConfig(c, interval); + c.load(); + assertEquals("uses default", 60, c.getComputerRetentionCheckInterval()); + assertEquals("prints one fallback message", 1, logging.getRecords().size()); + assertEquals("fallback message content", "computerRetentionCheckInterval must be greater than zero, falling back to 60s", logging.getRecords().get(0).getMessage()); + } + + @Test + public void bootWithNegative() throws IOException { + checkUsesFallbackAfterLoadOf(-1); + } + + @Test + public void bootWithZero() throws IOException { + checkUsesFallbackAfterLoadOf(0); + } + + @Test + public void bootWithPositive() throws IOException { + recordWarnings(); + GlobalComputerRetentionCheckIntervalConfiguration c = new GlobalComputerRetentionCheckIntervalConfiguration(); + writeConfig(c, 1); + c.load(); + assertEquals("uses custom value", 1, c.getComputerRetentionCheckInterval()); + assertEquals("no fallback message", 0, logging.getRecords().size()); + } + + @Test + public void bootWithTooLargeValue() throws IOException { + recordWarnings(); + GlobalComputerRetentionCheckIntervalConfiguration c = new GlobalComputerRetentionCheckIntervalConfiguration(); + writeConfig(c, 1337); + c.load(); + assertEquals("uses default", 60, c.getComputerRetentionCheckInterval()); + assertEquals("prints one fallback message", 1, logging.getRecords().size()); + assertEquals("fallback message content", "computerRetentionCheckInterval is limited to 60s", logging.getRecords().get(0).getMessage()); + } + + @Test + public void saveCycle() { + recordWarnings(); + GlobalComputerRetentionCheckIntervalConfiguration c = new GlobalComputerRetentionCheckIntervalConfiguration(); + + JSONObject json = new JSONObject(); + json.element("computerRetentionCheckInterval", 5); + try { + c.configure(Stapler.getCurrentRequest(), json); + } catch (Descriptor.FormException e) { + throw new RuntimeException(e); + } + assertEquals("stores value", 5, c.getComputerRetentionCheckInterval()); + + GlobalComputerRetentionCheckIntervalConfiguration c2 = new GlobalComputerRetentionCheckIntervalConfiguration(); + c2.load(); + assertEquals("round trip value", 5, c2.getComputerRetentionCheckInterval()); + assertEquals("no fallback message", 0, logging.getRecords().size()); + } + + private void checkSaveInvalidValueOf(int interval, String message) { + recordWarnings(); + GlobalComputerRetentionCheckIntervalConfiguration c = new GlobalComputerRetentionCheckIntervalConfiguration(); + + JSONObject json = new JSONObject(); + json.element("computerRetentionCheckInterval", interval); + try { + c.configure(Stapler.getCurrentRequest(), json); + throw new RuntimeException("expected .configure() to throw"); + } catch (Descriptor.FormException e) { + assertEquals(e.getMessage(), message); + } + assertEquals("does not store value", 60, c.getComputerRetentionCheckInterval()); + + GlobalComputerRetentionCheckIntervalConfiguration c2 = new GlobalComputerRetentionCheckIntervalConfiguration(); + c2.load(); + assertEquals("does not persist value", 60, c2.getComputerRetentionCheckInterval()); + assertEquals("no fallback message", 0, logging.getRecords().size()); + } + + @Test + public void saveInvalidValueTooLow() { + checkSaveInvalidValueOf(0, "java.lang.IllegalArgumentException: interval must be greater than zero"); + } + + @Test + public void saveInvalidValueTooHigh() { + checkSaveInvalidValueOf(1337, "java.lang.IllegalArgumentException: interval must be below or equal 60s"); + } +} diff --git a/test/src/test/java/jenkins/security/ApiCrumbExclusionTest.java b/test/src/test/java/jenkins/security/ApiCrumbExclusionTest.java index 59f89e8f4977..c746fc7cc4d5 100644 --- a/test/src/test/java/jenkins/security/ApiCrumbExclusionTest.java +++ b/test/src/test/java/jenkins/security/ApiCrumbExclusionTest.java @@ -108,7 +108,7 @@ private void makeRequestAndFail(int expectedCode) { } private void checkWeCanChangeMyDescription(int expectedCode) throws IOException, SAXException { - HtmlPage page = wc.goTo("me/configure"); + HtmlPage page = wc.goTo("me/account/"); HtmlForm form = page.getFormByName("config"); form.getTextAreaByName("_.description").setText("random description: " + Math.random()); diff --git a/test/src/test/java/jenkins/security/ApiTokenPropertyTest.java b/test/src/test/java/jenkins/security/ApiTokenPropertyTest.java index 30361ed8658c..162ac231b664 100644 --- a/test/src/test/java/jenkins/security/ApiTokenPropertyTest.java +++ b/test/src/test/java/jenkins/security/ApiTokenPropertyTest.java @@ -80,7 +80,7 @@ public void basics() throws Exception { assertEquals(u, wc.executeOnServer(User::current)); // Make sure the UI shows the token to the user - HtmlPage config = wc.goTo(u.getUrl() + "/configure"); + HtmlPage config = wc.goTo(u.getUrl() + "/security/"); HtmlForm form = config.getFormByName("config"); assertEquals(token, form.getInputByName("_.apiToken").getValue()); @@ -126,7 +126,7 @@ public void adminsShouldBeUnableToSeeTokensByDefault() throws Exception { // Make sure the UI does not show the token to another user WebClient wc = createClientForUser("bar"); - HtmlPage config = wc.goTo(u.getUrl() + "/configure"); + HtmlPage config = wc.goTo(u.getUrl() + "/security/"); HtmlForm form = config.getFormByName("config"); assertEquals(Messages.ApiTokenProperty_ChangeToken_TokenIsHidden(), form.getInputByName("_.apiToken").getValue()); } diff --git a/test/src/test/java/jenkins/security/BasicHeaderApiTokenAuthenticatorTest.java b/test/src/test/java/jenkins/security/BasicHeaderApiTokenAuthenticatorTest.java index 873194dfb089..940715b0fe6a 100644 --- a/test/src/test/java/jenkins/security/BasicHeaderApiTokenAuthenticatorTest.java +++ b/test/src/test/java/jenkins/security/BasicHeaderApiTokenAuthenticatorTest.java @@ -70,7 +70,7 @@ public void legacyToken_regularCase() throws Throwable { // default SecurityListener will save the user when adding the LastGrantedAuthoritiesProperty // and so the user is persisted wc.login("user1"); - HtmlPage page = wc.goTo("user/user1/configure"); + HtmlPage page = wc.goTo("user/user1/security/"); String tokenValue = ((HtmlTextInput) page.getDocumentElement().querySelector("#apiToken")).getText(); token.set(tokenValue); } @@ -118,7 +118,7 @@ public void legacyToken_withoutLastGrantedAuthorities() throws Throwable { { JenkinsRule.WebClient wc = j.createWebClient(); wc.login("user1"); - HtmlPage page = wc.goTo("user/user1/configure"); + HtmlPage page = wc.goTo("user/user1/security/"); String tokenValue = ((HtmlTextInput) page.getDocumentElement().querySelector("#apiToken")).getText(); token.set(tokenValue); } diff --git a/test/src/test/java/jenkins/security/LastGrantedAuthoritiesPropertyTest.java b/test/src/test/java/jenkins/security/LastGrantedAuthoritiesPropertyTest.java index 4d29e609860f..5c1c7318c3a9 100644 --- a/test/src/test/java/jenkins/security/LastGrantedAuthoritiesPropertyTest.java +++ b/test/src/test/java/jenkins/security/LastGrantedAuthoritiesPropertyTest.java @@ -43,7 +43,7 @@ public void basicFlow() throws Exception { assertAuthorities(u.impersonate2(), "alice:authenticated:development:us"); // visiting the configuration page shouldn't change authorities - HtmlPage pg = wc.goTo("user/alice/configure"); + HtmlPage pg = wc.goTo("user/alice/account/"); j.submit(pg.getFormByName("config")); p = u.getProperty(LastGrantedAuthoritiesProperty.class); diff --git a/test/src/test/java/jenkins/security/Security3245Test.java b/test/src/test/java/jenkins/security/Security3245Test.java index 9c9a37b46581..2202632b26e6 100644 --- a/test/src/test/java/jenkins/security/Security3245Test.java +++ b/test/src/test/java/jenkins/security/Security3245Test.java @@ -30,9 +30,9 @@ public class Security3245Test { @Issue("SECURITY-3245") @Test - public void captionCannotAttributeEscape() throws Exception { + public void captionCannotElementEscape() throws Exception { FreeStyleProject p = j.createFreeStyleProject("p"); - p.getBuildersList().add(new ExpandableDetailsNoteTestAction("' onclick=alert(1) foo='bar", "

")); + p.getBuildersList().add(new ExpandableDetailsNoteTestAction("", "

")); FreeStyleBuild build = j.buildAndAssertSuccess(p); AtomicBoolean alerts = new AtomicBoolean(); @@ -40,12 +40,9 @@ public void captionCannotAttributeEscape() throws Exception { wc.setAlertHandler((pr, s) -> alerts.set(true)); final HtmlPage page = wc.goTo(build.getUrl() + "console"); String content = page.getWebResponse().getContentAsString(); - assertThat(content, containsString("")); - - // Execute JavaScript code to simulate click event - String jsCode = "document.querySelector('.reveal-expandable-detail').dispatchEvent(new MouseEvent('click'));"; - page.executeJavaScript(jsCode); - + assertThat(content, containsString("")); + // check that alert was not executed Assert.assertFalse("Alert not expected", alerts.get()); } } diff --git a/test/src/test/java/jenkins/security/SecurityContextExecutorServiceTest.java b/test/src/test/java/jenkins/security/SecurityContextExecutorServiceTest.java index 76f64ab67096..ac9df83a2f55 100644 --- a/test/src/test/java/jenkins/security/SecurityContextExecutorServiceTest.java +++ b/test/src/test/java/jenkins/security/SecurityContextExecutorServiceTest.java @@ -106,7 +106,7 @@ public void testRunnableAgainstAllContexts() throws Exception { @Test @PresetData(PresetData.DataSet.NO_ANONYMOUS_READACCESS) public void testCallableAgainstAllContexts() throws Exception { - Callable c = () -> SecurityContextHolder.getContext(); + Callable c = SecurityContextHolder::getContext; SecurityContextHolder.setContext(systemContext); Future result = wrappedService.submit(c); // Assert the context inside the callable thread was set to ACL.SYSTEM2 @@ -127,7 +127,7 @@ public void testCallableAgainstAllContexts() throws Exception { @PresetData(PresetData.DataSet.NO_ANONYMOUS_READACCESS) public void testCallableCollectionAgainstAllContexts() throws Exception { Collection> callables = new ArrayList<>(); - Callable c = () -> SecurityContextHolder.getContext(); + Callable c = SecurityContextHolder::getContext; callables.add(c); callables.add(c); callables.add(c); diff --git a/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsRestartTest.java b/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsRestartTest.java index ea1dec6081ae..d76d382e10c1 100644 --- a/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsRestartTest.java +++ b/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsRestartTest.java @@ -103,7 +103,7 @@ public void roundtripWithRestart() throws Throwable { WebClient restWc = j.createWebClient().withBasicCredentials(u.getId(), tokenValue.get()); checkUserIsConnected(restWc, u.getId()); - HtmlPage config = wc.goTo(u.getUrl() + "/configure"); + HtmlPage config = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, config.getWebResponse().getStatusCode()); assertThat(config.getWebResponse().getContentAsString(), containsString(tokenUuid.get())); assertThat(config.getWebResponse().getContentAsString(), containsString(tokenName)); @@ -113,7 +113,7 @@ public void roundtripWithRestart() throws Throwable { restWc.goToXml("whoAmI/api/xml"); } - HtmlPage configWithStats = wc.goTo(u.getUrl() + "/configure"); + HtmlPage configWithStats = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, configWithStats.getWebResponse().getStatusCode()); HtmlSpan useCounterSpan = configWithStats.getDocumentElement().getOneHtmlElementByAttribute("span", "class", "token-use-counter"); assertThat(useCounterSpan.getTextContent(), containsString("" + NUM_CALL_WITH_TOKEN)); @@ -131,7 +131,7 @@ public void roundtripWithRestart() throws Throwable { WebClient wc = j.createWebClient().login(u.getId()); checkUserIsConnected(wc, u.getId()); - HtmlPage config = wc.goTo(u.getUrl() + "/configure"); + HtmlPage config = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, config.getWebResponse().getStatusCode()); assertThat(config.getWebResponse().getContentAsString(), containsString(tokenUuid.get())); assertThat(config.getWebResponse().getContentAsString(), containsString(TOKEN_NAME)); @@ -144,7 +144,7 @@ public void roundtripWithRestart() throws Throwable { WebClient restWc = j.createWebClient().withBasicCredentials(u.getId(), tokenValue.get()); checkUserIsNotConnected(restWc); - HtmlPage configWithoutToken = wc.goTo(u.getUrl() + "/configure"); + HtmlPage configWithoutToken = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, configWithoutToken.getWebResponse().getStatusCode()); assertThat(configWithoutToken.getWebResponse().getContentAsString(), not(containsString(tokenUuid.get()))); assertThat(configWithoutToken.getWebResponse().getContentAsString(), not(containsString(TOKEN_NAME))); diff --git a/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsTest.java b/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsTest.java index 68185e6efac3..0eb010e77d77 100644 --- a/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsTest.java +++ b/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsTest.java @@ -91,7 +91,7 @@ public void roundtrip() throws Exception { WebClient restWc = j.createWebClient().withBasicCredentials(u.getId(), tokenValue); checkUserIsConnected(restWc, u.getId()); - HtmlPage config = wc.goTo(u.getUrl() + "/configure"); + HtmlPage config = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, config.getWebResponse().getStatusCode()); assertThat(config.getWebResponse().getContentAsString(), containsString(tokenUuid)); assertThat(config.getWebResponse().getContentAsString(), containsString(tokenName)); @@ -102,7 +102,7 @@ public void roundtrip() throws Exception { restWc.goToXml("whoAmI/api/xml"); } - HtmlPage configWithStats = wc.goTo(u.getUrl() + "/configure"); + HtmlPage configWithStats = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, configWithStats.getWebResponse().getStatusCode()); HtmlSpan useCounterSpan = configWithStats.getDocumentElement().getOneHtmlElementByAttribute("span", "class", "token-use-counter"); assertThat(useCounterSpan.getTextContent(), containsString("" + NUM_CALL_WITH_TOKEN)); @@ -112,7 +112,7 @@ public void roundtrip() throws Exception { // token is no more valid checkUserIsNotConnected(restWc); - HtmlPage configWithoutToken = wc.goTo(u.getUrl() + "/configure"); + HtmlPage configWithoutToken = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, configWithoutToken.getWebResponse().getStatusCode()); assertThat(configWithoutToken.getWebResponse().getContentAsString(), not(containsString(tokenUuid))); assertThat(configWithoutToken.getWebResponse().getContentAsString(), not(containsString(tokenName))); diff --git a/test/src/test/java/jenkins/security/seed/UserSeedPropertyTest.java b/test/src/test/java/jenkins/security/seed/UserSeedPropertyTest.java index d87761ad391c..a9a3c8830a53 100644 --- a/test/src/test/java/jenkins/security/seed/UserSeedPropertyTest.java +++ b/test/src/test/java/jenkins/security/seed/UserSeedPropertyTest.java @@ -256,7 +256,7 @@ public void userSeedSection_isCorrectlyDisplayed() throws Exception { User alice = User.getById(ALICE, false); assertNotNull(alice); - HtmlPage htmlPage = wc.goTo(alice.getUrl() + "/configure"); + HtmlPage htmlPage = wc.goTo(alice.getUrl() + "/security/"); htmlPage.getDocumentElement().getOneHtmlElementByAttribute("div", "class", "user-seed-panel"); } @@ -280,7 +280,7 @@ public void userSeedSection_isCorrectlyHidden_withSpecificSetting() throws Excep User alice = User.getById(ALICE, false); assertNotNull(alice); - HtmlPage htmlPage = wc.goTo(alice.getUrl() + "/configure"); + HtmlPage htmlPage = wc.goTo(alice.getUrl() + "/security/"); assertThrows("Seed section should not be displayed", ElementNotFoundException.class, () -> htmlPage.getDocumentElement().getOneHtmlElementByAttribute("div", "class", "user-seed-panel")); } finally { diff --git a/test/src/test/java/jenkins/security/stapler/StaplerDispatchValidatorTest.java b/test/src/test/java/jenkins/security/stapler/StaplerDispatchValidatorTest.java index c5b523073f89..0483b2825e43 100644 --- a/test/src/test/java/jenkins/security/stapler/StaplerDispatchValidatorTest.java +++ b/test/src/test/java/jenkins/security/stapler/StaplerDispatchValidatorTest.java @@ -109,15 +109,6 @@ public void canViewPagesThatRedirectToViews() throws Exception { } } - @Test - public void canViewCompressedViews() throws Exception { - String[] urls = {"groovy/compress", "jelly/compress"}; - for (String url : urls) { - HtmlPage root = j.createWebClient().goTo(url); - assertEquals("Fragment", root.getElementById("frag").asNormalizedText()); - } - } - @Test public void cannotViewFragment() throws Exception { String[] urls = {"annotated/frag", "groovy/frag", "jelly/frag", "whitelist/frag"}; diff --git a/test/src/test/java/jenkins/widgets/BuildTimeTrendTest.java b/test/src/test/java/jenkins/widgets/BuildTimeTrendTest.java index cd729ed55668..38823a27a99a 100644 --- a/test/src/test/java/jenkins/widgets/BuildTimeTrendTest.java +++ b/test/src/test/java/jenkins/widgets/BuildTimeTrendTest.java @@ -74,7 +74,7 @@ public void withAbstractJob_OnBuiltInNode() throws Exception { wc.withThrowExceptionOnFailingStatusCode(false); HtmlPage page = wc.getPage(p, "buildTimeTrend"); - HtmlTable table = page.getDocumentElement().querySelector("table[data-is-distributed-build-enabled=false]"); + HtmlTable table = page.getDocumentElement().querySelector("table[data-show-agent=false]"); assertNotNull(table); } @@ -91,7 +91,7 @@ public void withAbstractJob_OnAgentNode() throws Exception { wc.withThrowExceptionOnFailingStatusCode(false); HtmlPage page = wc.getPage(p, "buildTimeTrend"); - DomNodeList anchors = page.getDocumentElement().querySelectorAll("table[data-is-distributed-build-enabled=true] td a"); + DomNodeList anchors = page.getDocumentElement().querySelectorAll("table[data-show-agent=true] td a"); Optional anchor = anchors.stream() .filter(a -> a.getTextContent().equals(agent.getNodeName())) .findFirst(); @@ -115,7 +115,7 @@ public void withAbstractJob_OnBoth() throws Exception { wc.withThrowExceptionOnFailingStatusCode(false); HtmlPage page = wc.getPage(p, "buildTimeTrend"); - DomNodeList anchors = page.getDocumentElement().querySelectorAll("table[data-is-distributed-build-enabled=true] td a"); + DomNodeList anchors = page.getDocumentElement().querySelectorAll("table[data-show-agent=true] td a"); Optional anchor = anchors.stream() .filter(a -> a.getTextContent().equals(agent.getNodeName())) .findFirst(); @@ -123,7 +123,7 @@ public void withAbstractJob_OnBoth() throws Exception { assertTrue(anchor.isPresent()); String builtInNode = hudson.model.Messages.Hudson_Computer_DisplayName(); - DomNodeList tds = page.getDocumentElement().querySelectorAll("table[data-is-distributed-build-enabled=true] td"); + DomNodeList tds = page.getDocumentElement().querySelectorAll("table[data-show-agent=true] td"); Optional td = tds.stream() .filter(t -> t.getTextContent().equals(builtInNode)) .findFirst(); @@ -142,7 +142,7 @@ public void withNonAbstractJob_withoutAgents() throws Exception { wc.withThrowExceptionOnFailingStatusCode(false); HtmlPage page = wc.getPage(p, "buildTimeTrend"); - DomNodeList tds = page.getDocumentElement().querySelectorAll("table[data-is-distributed-build-enabled=false] td"); + DomNodeList tds = page.getDocumentElement().querySelectorAll("table[data-show-agent=false] td"); Optional td = tds.stream() .filter(t -> t.getTextContent().equals("#1")) .findFirst(); @@ -168,7 +168,7 @@ public void withNonAbstractJob_withAgents() throws Exception { wc.withThrowExceptionOnFailingStatusCode(false); HtmlPage page = wc.getPage(p, "buildTimeTrend"); - DomNodeList tds = page.getDocumentElement().querySelectorAll("table[data-is-distributed-build-enabled=true] td"); + DomNodeList tds = page.getDocumentElement().querySelectorAll("table[data-show-agent=false] td"); Optional td = tds.stream() .filter(t -> t.getTextContent().equals("#1")) .findFirst(); diff --git a/test/src/test/java/lib/form/SecretTextareaTest.java b/test/src/test/java/lib/form/SecretTextareaTest.java index a0d68fbe1132..5ecfeae1f8da 100644 --- a/test/src/test/java/lib/form/SecretTextareaTest.java +++ b/test/src/test/java/lib/form/SecretTextareaTest.java @@ -37,7 +37,7 @@ import java.io.IOException; import org.htmlunit.html.HtmlElement; import org.htmlunit.html.HtmlForm; -import org.htmlunit.html.HtmlHiddenInput; +import org.htmlunit.html.HtmlTextArea; import org.htmlunit.html.HtmlTextInput; import org.junit.Before; import org.junit.Rule; @@ -120,8 +120,8 @@ private static void clickSecretUpdateButton(HtmlForm configForm) throws IOExcept } private static String getHiddenSecretValue(HtmlForm configForm) { - HtmlHiddenInput hiddenSecret = configForm.getInputByName("_.secret"); - return hiddenSecret == null ? null : hiddenSecret.getValue(); + HtmlTextArea hiddenSecret = configForm.getTextAreaByName("_.secret"); + return hiddenSecret == null ? null : hiddenSecret.getTextContent(); } public static class TestBuilder extends Builder { @@ -144,7 +144,7 @@ private static TestBuilder fromStringWithDescription(String secret, String descr @DataBoundConstructor public TestBuilder(Secret secret) { - this.secret = secret; + this.secret = fixEmptySecret(secret); } public Secret getSecret() { @@ -160,6 +160,13 @@ public void setDescription(String description) { this.description = description; } + private static Secret fixEmptySecret(Secret possiblyEmpty) { + if (possiblyEmpty == null || possiblyEmpty.getPlainText().isEmpty()) { + return null; + } + return possiblyEmpty; + } + @TestExtension public static class DescriptorImpl extends BuildStepDescriptor { @NonNull diff --git a/test/src/test/java/org/jenkins/ui/symbol/SymbolJenkinsTest.java b/test/src/test/java/org/jenkins/ui/symbol/SymbolJenkinsTest.java index 1609e5ff0e3c..49aaa9cd4f52 100644 --- a/test/src/test/java/org/jenkins/ui/symbol/SymbolJenkinsTest.java +++ b/test/src/test/java/org/jenkins/ui/symbol/SymbolJenkinsTest.java @@ -7,6 +7,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.jupiter.api.DisplayName; +import org.jvnet.hudson.test.Issue; import org.jvnet.hudson.test.JenkinsRule; import org.jvnet.hudson.test.RealJenkinsRule; @@ -15,6 +16,22 @@ public class SymbolJenkinsTest { public RealJenkinsRule rjr = new RealJenkinsRule() .addPlugins("plugins/design-library.jpi", "plugins/prism-api.jpi", "plugins/bootstrap5-api.jpi"); + @Test + @Issue("JENKINS-73243") + @DisplayName("When resolving a symbol where the tooltip contains '$' no error is thrown") + public void dollarInToolTipSucceeds() throws Throwable { + rjr.then(SymbolJenkinsTest::_dollarInTooltipSucceeds); + } + + private static void _dollarInTooltipSucceeds(JenkinsRule j) { + String symbol = Symbol.get(new SymbolRequest.Builder() + .withName("add") + .withTooltip("$test") + .build() + ); + assertThat(symbol, containsString("tooltip=\"$test\"")); + } + @Test @DisplayName("When resolving a symbol from a missing plugin, the placeholder is generated instead") public void missingSymbolFromPluginDefaultsToPlaceholder() throws Throwable { diff --git a/test/src/test/resources/hudson/util/FormFieldValidatorTest/ValidatingDescribable/config.jelly b/test/src/test/resources/hudson/util/FormFieldValidatorTest/ValidatingDescribable/config.jelly new file mode 100644 index 000000000000..c560072d1ed4 --- /dev/null +++ b/test/src/test/resources/hudson/util/FormFieldValidatorTest/ValidatingDescribable/config.jelly @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/test/src/test/resources/jenkins/security/stapler/StaplerDispatchValidatorTest/Jelly/compress.jelly b/test/src/test/resources/jenkins/security/stapler/StaplerDispatchValidatorTest/Jelly/compress.jelly deleted file mode 100644 index 8ef1c236f51c..000000000000 --- a/test/src/test/resources/jenkins/security/stapler/StaplerDispatchValidatorTest/Jelly/compress.jelly +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - diff --git a/war/package.json b/war/package.json index 8316c78911ae..5f42845e5b66 100644 --- a/war/package.json +++ b/war/package.json @@ -23,32 +23,32 @@ "lint": "yarn lint:js && yarn lint:css" }, "devDependencies": { - "@babel/cli": "7.24.5", - "@babel/core": "7.24.5", - "@babel/preset-env": "7.24.5", - "@eslint/js": "9.3.0", + "@babel/cli": "7.24.8", + "@babel/core": "7.24.9", + "@babel/preset-env": "7.24.8", + "@eslint/js": "9.7.0", "babel-loader": "9.1.3", "clean-webpack-plugin": "4.0.0", "css-loader": "7.1.2", "css-minimizer-webpack-plugin": "7.0.0", - "eslint": "9.3.0", + "eslint": "9.7.0", "eslint-config-prettier": "9.1.0", "eslint-formatter-checkstyle": "8.40.0", - "globals": "15.3.0", + "globals": "15.8.0", "handlebars-loader": "1.7.3", "mini-css-extract-plugin": "2.9.0", - "postcss": "8.4.38", + "postcss": "8.4.39", "postcss-loader": "8.1.1", - "postcss-preset-env": "9.5.14", + "postcss-preset-env": "9.6.0", "postcss-scss": "4.0.9", - "prettier": "3.2.5", - "sass": "1.77.2", - "sass-loader": "14.2.1", + "prettier": "3.3.3", + "sass": "1.77.8", + "sass-loader": "15.0.0", "style-loader": "4.0.0", - "stylelint": "16.5.0", + "stylelint": "16.7.0", "stylelint-checkstyle-reporter": "1.0.0", - "stylelint-config-standard": "36.0.0", - "webpack": "5.91.0", + "stylelint-config-standard": "36.0.1", + "webpack": "5.93.0", "webpack-cli": "5.1.4", "webpack-remove-empty-scripts": "1.0.4" }, @@ -65,5 +65,5 @@ "defaults", "not IE 11" ], - "packageManager": "yarn@4.2.2" + "packageManager": "yarn@4.3.1" } diff --git a/war/pom.xml b/war/pom.xml index 6db85f2fe20d..02b0efeb0f3e 100644 --- a/war/pom.xml +++ b/war/pom.xml @@ -46,8 +46,8 @@ THE SOFTWARE. localhost 8080 - 2.12.1-101.v85b_e08b_780dd - 20.13.1 + 2.13.1-117.v2f1a_b_66ff91d + 20.16.0 1.22.19 @@ -136,6 +136,51 @@ THE SOFTWARE. jenkins + + + org.apache.maven.plugins + maven-enforcer-plugin + + + display-info + + + + 11 + + + 11 + + org.jenkins-ci:commons-jelly + org.jenkins-ci.main:cli + org.jenkins-ci.main:jenkins-core + org.jenkins-ci.main:websocket-jetty10 + org.jenkins-ci.main:websocket-spi + org.kohsuke.stapler:stapler + org.kohsuke.stapler:stapler-groovy + org.kohsuke.stapler:stapler-jelly + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 11 + 11 + + + + org.apache.maven.plugins + maven-javadoc-plugin + + 11 + + maven-war-plugin @@ -239,28 +284,28 @@ THE SOFTWARE. org.jenkins-ci.plugins matrix-project - 830.v7ea_da_561b_a_34 + 832.va_66e270d2946 hpi
org.jenkins-ci.plugins script-security - 1336.vf33a_a_9863911 + 1341.va_2819b_414686 hpi org.jenkins-ci.plugins junit - 1265.v65b_14fa_f12f0 + 1279.v72cf99b_25c43 hpi org.jenkins-ci.plugins.workflow workflow-api - 1312.ve804c2f2d51e + 1322.v857eeeea_9902 hpi @@ -289,7 +334,7 @@ THE SOFTWARE. org.jenkins-ci.plugins.workflow workflow-support - 907.v6713a_ed8a_573 + 920.v59f71ce16f04 hpi @@ -307,7 +352,13 @@ THE SOFTWARE. 5.5.0-1 hpi
- + + + io.jenkins.plugins + eddsa-api + 0.3.0-4.v84c6f0f4969e + hpi + io.jenkins.plugins @@ -344,7 +395,7 @@ THE SOFTWARE. org.jenkins-ci.plugins.workflow workflow-step-api - 657.v03b_e8115821b_ + 678.v3ee58b_469476 hpi @@ -358,14 +409,14 @@ THE SOFTWARE. org.jenkins-ci.plugins structs - 337.v1b_04ea_4df7c8 + 338.v848422169819 hpi org.jenkins-ci.plugins bouncycastle-api - 2.30.1.77-225.v26ea_c9455fd9 + 2.30.1.78.1-248.ve27176eb_46cb_ hpi @@ -393,14 +444,14 @@ THE SOFTWARE. org.jenkins-ci.modules sshd - 3.322.v159e91f6a_550 + 3.330.vc866a_8389b_58 hpi org.jenkins-ci.plugins trilead-api - 2.142.v748523a_76693 + 2.147.vb_73cc728a_32e hpi @@ -442,21 +493,21 @@ THE SOFTWARE. io.jenkins.plugins commons-lang3-api - 3.13.0-62.v7d18e55f51e2 + 3.14.0-76.vda_5591261cfe hpi io.jenkins.plugins commons-text-api - 1.11.0-109.vfe16c66636eb_ + 1.12.0-119.v73ef73f2345d hpi io.jenkins.plugins gson-api - 2.10.1-15.v0d99f670e0a_7 + 2.11.0-41.v019fcf6125dc hpi @@ -668,30 +719,6 @@ THE SOFTWARE. - - org.apache.maven.plugins - maven-enforcer-plugin - - - - enforce-versions - - enforce - - - - - 3.1.0 - - - - [1.8.0-101,] - - - - - - org.apache.maven.plugins maven-antrun-plugin diff --git a/war/src/main/java/executable/Main.java b/war/src/main/java/executable/Main.java index 410392f96202..8a8cf67a87a5 100644 --- a/war/src/main/java/executable/Main.java +++ b/war/src/main/java/executable/Main.java @@ -76,7 +76,7 @@ public class Main { * This list must remain synchronized with the one in {@code * JavaVersionRecommendationAdminMonitor}. */ - private static final NavigableSet SUPPORTED_JAVA_VERSIONS = new TreeSet<>(List.of(11, 17, 21)); + private static final NavigableSet SUPPORTED_JAVA_VERSIONS = new TreeSet<>(List.of(17, 21)); /** * Sets custom session cookie name. diff --git a/war/src/main/js/components/dropdowns/hetero-list.js b/war/src/main/js/components/dropdowns/hetero-list.js index 2b216bc20168..0eab2b9ea324 100644 --- a/war/src/main/js/components/dropdowns/hetero-list.js +++ b/war/src/main/js/components/dropdowns/hetero-list.js @@ -77,11 +77,10 @@ function generateButtons() { function insert(instance, template) { let nc = document.createElement("div"); - nc.className = "repeated-chunk"; + nc.className = "repeated-chunk fade-in"; nc.setAttribute("name", template.name); nc.setAttribute("descriptorId", template.descriptorId); nc.innerHTML = template.html; - nc.style.opacity = "0"; instance.hide(); @@ -150,18 +149,9 @@ function generateButtons() { if (withDragDrop) { registerSortableDragDrop(nc); } - - new YAHOO.util.Anim( - nc, - { - opacity: { to: 1 }, - }, - 0.2, - YAHOO.util.Easing.easeIn, - ).animate(); - Behaviour.applySubtree(nc, true); ensureVisible(nc); + nc.classList.remove("fade-in"); layoutUpdateCallback.call(); }, true, diff --git a/war/src/main/js/components/dropdowns/jumplists.js b/war/src/main/js/components/dropdowns/jumplists.js index 3297da22e9ea..f831f452bafe 100644 --- a/war/src/main/js/components/dropdowns/jumplists.js +++ b/war/src/main/js/components/dropdowns/jumplists.js @@ -31,7 +31,7 @@ function generateJumplistAccessors() { */ function generateDropdowns() { behaviorShim.specify( - "li.children, #menuSelector, .jenkins-menu-dropdown-chevron", + "li.children, .jenkins-jumplist-link, #menuSelector, .jenkins-menu-dropdown-chevron", "-dropdown-", 1000, (element) => diff --git a/war/src/main/js/components/dropdowns/templates.js b/war/src/main/js/components/dropdowns/templates.js index 9b97c8cd7f66..713bf8b6ce0f 100644 --- a/war/src/main/js/components/dropdowns/templates.js +++ b/war/src/main/js/components/dropdowns/templates.js @@ -60,7 +60,7 @@ function menuItem(options) { ${label} ${ itemOptions.badge != null - ? `${badgeText}` + ? `${badgeText}` : `` } ${ diff --git a/war/src/main/js/filter-build-history.js b/war/src/main/js/filter-build-history.js deleted file mode 100644 index 06a83a5b503d..000000000000 --- a/war/src/main/js/filter-build-history.js +++ /dev/null @@ -1,590 +0,0 @@ -import debounce from "lodash/debounce"; - -const buildHistoryContainer = document.getElementById("buildHistory"); -const pageSearchInputContainer = buildHistoryContainer.querySelector( - ".build-search-row .jenkins-search", -); -const pageSearchInput = buildHistoryContainer.querySelector( - ".build-search-row input", -); -const buildHistoryPage = document.getElementById("buildHistoryPage"); -const properties = document.getElementById("properties"); -const ajaxUrl = buildHistoryPage.getAttribute("page-ajax"); -const nextBuild = properties.getAttribute("page-next-build"); -const noBuildsBanner = document.getElementById("no-builds"); - -const sidePanel = document.getElementById("side-panel"); -const buildHistoryPageNav = document.getElementById("buildHistoryPageNav"); - -const pageOne = buildHistoryPageNav.querySelector(".pageOne"); -const pageUp = buildHistoryPageNav.querySelector(".pageUp"); -const pageDown = buildHistoryPageNav.querySelector(".pageDown"); - -const leftRightPadding = 4; -const updateBuildsRefreshInterval = 5000; - -function updateBuilds(params) { - if (isPageVisible()) { - fetch(ajaxUrl + toQueryString(params), { - headers: { - n: buildHistoryContainer.headers[1], - }, - }).then((rsp) => { - if (rsp.ok) { - rsp.text().then((responseText) => { - var dataTable = getDataTable(buildHistoryContainer); - var rows = dataTable.rows; - - // Check there are no existing rows (except the search bar) before showing the no builds banner - if ( - rows.length <= 1 && - responseText === '
' - ) { - noBuildsBanner.style.display = "block"; - if ( - typeof params === "object" && - "search" in params && - params.search !== "" - ) { - pageSearchInputContainer.classList.remove("jenkins-hidden"); - } else { - pageSearchInputContainer.classList.add("jenkins-hidden"); - } - } else { - noBuildsBanner.style.display = "none"; - pageSearchInputContainer.classList.remove("jenkins-hidden"); - } - - //delete rows with transitive data - var firstBuildRow = 0; - if (rows[firstBuildRow].classList.contains("build-search-row")) { - firstBuildRow++; - } - while ( - rows.length > 1 && - rows[firstBuildRow].classList.contains("transitive") - ) { - rows[firstBuildRow].remove(); - } - - // insert new rows - var div = document.createElement("div"); - div.innerHTML = responseText; - Behaviour.applySubtree(div); - - var pivot = rows[firstBuildRow]; - var newDataTable = getDataTable(div); - var newRows = newDataTable.rows; - while (newRows.length > 0) { - if (pivot !== undefined) { - // The data table has rows. Insert before a "pivot" row (first row). - pivot.parentNode.insertBefore(newRows[0], pivot); - } else { - // The data table has no rows. In this case, we just add all new rows directly to the - // table, one after the other i.e. we don't insert before a "pivot" row (first row). - dataTable - .getElementsByTagName("tbody")[0] - .appendChild(newRows[0]); - } - } - - if (newDataTable.classList.contains("hasPageData")) { - buildHistoryPage.setAttribute( - "page-entry-newest", - newDataTable.getAttribute("page-entry-newest"), - ); - } - - // next update - buildHistoryContainer.headers = ["n", rsp.headers.get("n")]; - checkAllRowCellOverflows(); - createRefreshTimeout(params); - }); - } - }); - } else { - createRefreshTimeout(params); - } -} - -var buildRefreshTimeout; -function createRefreshTimeout(params) { - cancelRefreshTimeout(); - buildRefreshTimeout = window.setTimeout( - () => updateBuilds(params), - updateBuildsRefreshInterval, - ); -} - -function cancelRefreshTimeout() { - if (buildRefreshTimeout) { - window.clearTimeout(buildRefreshTimeout); - buildRefreshTimeout = undefined; - } -} - -function hasPageUp() { - return buildHistoryPage.getAttribute("page-has-up") === "true"; -} -function hasPageDown() { - return buildHistoryPage.getAttribute("page-has-down") === "true"; -} -function getNewestEntryId() { - return buildHistoryPage.getAttribute("page-entry-newest"); -} -function getOldestEntryId() { - return buildHistoryPage.getAttribute("page-entry-oldest"); -} - -function getDataTable(buildHistoryDiv) { - return buildHistoryDiv.querySelector("table.pane"); -} - -function updatePageParams(dataTable) { - buildHistoryPage.setAttribute( - "page-has-up", - dataTable.getAttribute("page-has-up"), - ); - buildHistoryPage.setAttribute( - "page-has-down", - dataTable.getAttribute("page-has-down"), - ); - buildHistoryPage.setAttribute( - "page-entry-newest", - dataTable.getAttribute("page-entry-newest"), - ); - buildHistoryPage.setAttribute( - "page-entry-oldest", - dataTable.getAttribute("page-entry-oldest"), - ); -} -function togglePageUpDown() { - buildHistoryPageNav.classList.remove("hasUpPage"); - buildHistoryPageNav.classList.remove("hasDownPage"); - if (hasPageUp()) { - buildHistoryPageNav.classList.add("hasUpPage"); - } - if (hasPageDown()) { - buildHistoryPageNav.classList.add("hasDownPage"); - } -} - -function checkRowCellOverflows(row) { - if (!row) { - return; - } - - if (row.classList.contains("overflow-checked")) { - // already done. - return; - } - - function markSingleline() { - row.classList.add("single-line"); - row.classList.remove("multi-line"); - } - function markMultiline() { - row.classList.remove("single-line"); - row.classList.add("multi-line"); - } - function indentMultiline(element) { - element.classList.add("indent-multiline"); - } - - function blockWrap(el1, el2) { - var div = document.createElement("div"); - - div.classList.add("block"); - div.classList.add("wrap"); - el1.classList.add("wrapped"); - el2.classList.add("wrapped"); - - el1.parentNode.insertBefore(div, el1); - el1.parentNode.removeChild(el1); - el2.parentNode.removeChild(el2); - div.appendChild(el1); - div.appendChild(el2); - - return div; - } - function blockUnwrap(element) { - element.querySelectorAll(".wrapped").forEach(function (wrappedEl) { - wrappedEl.parentNode.removeChild(wrappedEl); - element.parentNode.insertBefore(wrappedEl, element); - wrappedEl.classList.remove("wrapped"); - }); - element.parentNode.removeChild(element); - } - - var buildName = row.querySelector(".build-name"); - var buildDetails = row.querySelector(".build-details"); - - if (!buildName || !buildDetails) { - return; - } - - var buildControls = row.querySelector(".build-controls"); - var desc = row.querySelector(".desc"); - - function resetCellOverflows() { - markSingleline(); - - // undo block wraps - row.querySelectorAll(".block.wrap").forEach(function (blockWrap) { - blockUnwrap(blockWrap); - }); - - buildName.classList.remove("block"); - buildName.removeAttribute("style"); - buildDetails.classList.remove("block"); - buildDetails.removeAttribute("style"); - if (buildControls) { - buildControls.classList.remove("block"); - buildDetails.removeAttribute("style"); - } - } - - // Undo everything from the previous poll. - resetCellOverflows(); - - // Mark the text as multiline, if it has more than one line - if (desc) { - markMultiline(); - } - - var rowWidth = buildHistoryContainer.clientWidth; - var usableRowWidth = rowWidth - leftRightPadding * 2; - var nameOverflowParams = getElementOverflowParams(buildName); - var detailsOverflowParams = getElementOverflowParams(buildDetails); - - var controlsOverflowParams; - if (buildControls) { - controlsOverflowParams = getElementOverflowParams(buildControls); - } - - function fitToControlsHeight(element) { - if (buildControls) { - if (element.clientHeight < buildControls.clientHeight) { - element.style.height = buildControls.clientHeight.toString() + "px"; - } - } - } - - function setBuildControlWidths() { - if (buildControls) { - var buildBadge = buildControls.querySelector(".build-badge"); - - if (buildBadge) { - var buildControlsWidth = buildControls.clientWidth; - var buildBadgeWidth; - - var buildStop = buildControls.querySelector(".build-stop"); - if (buildStop) { - buildStop.style.width = "24px"; - // Minus 24 for the buildStop width, - // minus 4 for left+right padding in the controls container - buildBadgeWidth = buildControlsWidth - 24 - leftRightPadding; - if (buildControls.classList.contains("indent-multiline")) { - buildBadgeWidth = buildBadgeWidth - 20; - } - buildBadge.style.width = buildBadgeWidth + "px"; - } else { - buildBadge.style.width = "100%"; - } - } - controlsOverflowParams = getElementOverflowParams(buildControls); - } - } - setBuildControlWidths(); - - var controlsRepositioned = false; - - if (nameOverflowParams.isOverflowed || detailsOverflowParams.isOverflowed) { - // At least one of the cells (name or details) needs to move to a row of its own. - - markMultiline(); - - if (buildControls) { - // We have build controls. Lets see can we find a combination that allows the build controls - // to sit beside either the build name or the build details. - - var badgesOverflowing = false; - var nameLessThanHalf = true; - var detailsLessThanHalf = true; - var buildBadge = buildControls.querySelector(".build-badge"); - if (buildBadge) { - var badgeOverflowParams = getElementOverflowParams(buildBadge); - - if (badgeOverflowParams.isOverflowed) { - // The badges are also overflowing. In this case, we will only attempt to - // put the controls on the same line as the name or details (see below) - // if the name or details is using less than half the width of the build history - // widget. - badgesOverflowing = true; - nameLessThanHalf = - nameOverflowParams.scrollWidth < usableRowWidth / 2; - detailsLessThanHalf = - detailsOverflowParams.scrollWidth < usableRowWidth / 2; - } - } - function expandLeftWithRight( - leftCellOverFlowParams, - rightCellOverflowParams, - ) { - // Float them left and right... - leftCellOverFlowParams.element.style.float = "left"; - rightCellOverflowParams.element.style.float = "right"; - - if ( - !leftCellOverFlowParams.isOverflowed && - !rightCellOverflowParams.isOverflowed - ) { - // If neither left nor right are overflowed, just leave as is and let them float left and right. - return; - } - if ( - leftCellOverFlowParams.isOverflowed && - !rightCellOverflowParams.isOverflowed - ) { - leftCellOverFlowParams.element.style.width = - leftCellOverFlowParams.scrollWidth + "px"; - return; - } - if ( - !leftCellOverFlowParams.isOverflowed && - rightCellOverflowParams.isOverflowed - ) { - rightCellOverflowParams.element.style.width = - rightCellOverflowParams.scrollWidth + "px"; - return; - } - } - - if ( - (!badgesOverflowing || nameLessThanHalf) && - nameOverflowParams.scrollWidth + controlsOverflowParams.scrollWidth <= - usableRowWidth - ) { - // Build name and controls can go on one row (first row). Need to move build details down - // to a row of its own (second row) by making it a block element, forcing it to wrap. If there - // are controls, we move them up to position them after the build name by inserting before the - // build details. - buildDetails.classList.add("block"); - buildControls.parentNode.removeChild(buildControls); - buildDetails.parentNode.insertBefore(buildControls, buildDetails); - var wrap = blockWrap(buildName, buildControls); - wrap.classList.add("build-name-controls"); - indentMultiline(buildDetails); - nameOverflowParams = getElementOverflowParams(buildName); // recalculate - expandLeftWithRight(nameOverflowParams, controlsOverflowParams); - setBuildControlWidths(); - fitToControlsHeight(buildName); - } else if ( - (!badgesOverflowing || detailsLessThanHalf) && - detailsOverflowParams.scrollWidth + - controlsOverflowParams.scrollWidth <= - usableRowWidth - ) { - // Build details and controls can go on one row. Need to make the - // build name (first field) a block element, forcing the details and controls to wrap - // onto the next row (creating a second row). - buildName.classList.add("block"); - wrap = blockWrap(buildDetails, buildControls); - indentMultiline(wrap); - wrap.classList.add("build-details-controls"); - detailsOverflowParams = getElementOverflowParams(buildDetails); // recalculate - expandLeftWithRight(detailsOverflowParams, controlsOverflowParams); - setBuildControlWidths(); - fitToControlsHeight(buildDetails); - } else { - // No suitable combo fits on a row. All need to go on rows of their own. - buildName.classList.add("block"); - buildDetails.classList.add("block"); - buildControls.classList.add("block"); - indentMultiline(buildDetails); - indentMultiline(buildControls); - nameOverflowParams = getElementOverflowParams(buildName); // recalculate - detailsOverflowParams = getElementOverflowParams(buildDetails); // recalculate - setBuildControlWidths(); - } - controlsRepositioned = true; - } else { - buildName.classList.add("block"); - buildDetails.classList.add("block"); - indentMultiline(buildDetails); - } - } - - if (buildControls && !controlsRepositioned) { - buildBadge = buildControls.querySelector(".build-badge"); - if (buildBadge) { - badgeOverflowParams = getElementOverflowParams(buildBadge); - - if (badgeOverflowParams.isOverflowed) { - markMultiline(); - indentMultiline(buildControls); - buildControls.classList.add("block"); - controlsRepositioned = true; - setBuildControlWidths(); - } - } - } - - if ( - !nameOverflowParams.isOverflowed && - !detailsOverflowParams.isOverflowed && - !controlsRepositioned - ) { - fitToControlsHeight(buildName); - fitToControlsHeight(buildDetails); - } - - row.classList.add("overflow-checked"); -} - -function checkAllRowCellOverflows() { - if (isRunAsTest) { - return; - } - - var dataTable = getDataTable(buildHistoryContainer); - var rows = dataTable.rows; - - for (var i = 0; i < rows.length; i++) { - var row = rows[i]; - checkRowCellOverflows(row); - } -} - -function loadPage(params, focusOnSearch) { - var searchString = pageSearchInput.value; - - if (searchString !== "") { - if (params === undefined) { - params = {}; - } - params.search = searchString; - } - - fetch(ajaxUrl + toQueryString(params)).then((rsp) => { - if (rsp.ok) { - rsp.text().then((responseText) => { - pageSearchInputContainer.classList.remove("jenkins-search--loading"); - buildHistoryContainer.classList.remove("jenkins-pane--loading"); - - if (responseText === '
') { - noBuildsBanner.style.display = "block"; - if ( - typeof params === "object" && - "search" in params && - params.search !== "" - ) { - pageSearchInputContainer.classList.remove("jenkins-hidden"); - } else { - pageSearchInputContainer.classList.add("jenkins-hidden"); - } - } else { - noBuildsBanner.style.display = "none"; - pageSearchInputContainer.classList.remove("jenkins-hidden"); - } - - var dataTable = getDataTable(buildHistoryContainer); - var tbody = dataTable.getElementsByTagName("tbody")[0]; - var rows = tbody.getElementsByClassName("build-row"); - - // Delete all build rows - while (rows.length > 0) { - rows[0].remove(); - } - - // insert new rows - var div = document.createElement("div"); - div.innerHTML = responseText; - Behaviour.applySubtree(div); - - var newDataTable = getDataTable(div); - var newRows = newDataTable.rows; - while (newRows.length > 0) { - tbody.appendChild(newRows[0]); - } - - checkAllRowCellOverflows(); - updatePageParams(newDataTable); - togglePageUpDown(); - if (!hasPageUp()) { - createRefreshTimeout(params); - } - - if (focusOnSearch) { - pageSearchInput.focus(); - } - }); - } - }); -} - -const handleFilter = function () { - loadPage({}, true); -}; - -const debouncedFilter = debounce(handleFilter, 300); - -document.addEventListener("DOMContentLoaded", function () { - // Apply correct styling upon filter bar text change, call API after wait - if (pageSearchInput !== null) { - pageSearchInput.addEventListener("input", function () { - pageSearchInputContainer.classList.add("jenkins-search--loading"); - buildHistoryContainer.classList.add("jenkins-pane--loading"); - noBuildsBanner.style.display = "none"; - - debouncedFilter(); - }); - } - - if (isRunAsTest) { - return; - } - - // If the build history pane is collapsed, just return immediately and don't set up - // the build history refresh. - if (buildHistoryContainer.classList.contains("collapsed")) { - return; - } - - buildHistoryContainer.headers = ["n", nextBuild]; - - createRefreshTimeout(); - checkAllRowCellOverflows(); - - // Show/hide the nav as the mouse moves into the sidepanel and build history. - sidePanel.addEventListener("mouseover", function () { - buildHistoryPageNav.classList.add("mouseOverSidePanel"); - }); - sidePanel.addEventListener("mouseout", function () { - buildHistoryPageNav.classList.remove("mouseOverSidePanel"); - }); - buildHistoryContainer.addEventListener("mouseover", function () { - buildHistoryPageNav.classList.add("mouseOverSidePanelBuildHistory"); - }); - buildHistoryContainer.addEventListener("mouseout", function () { - buildHistoryPageNav.classList.remove("mouseOverSidePanelBuildHistory"); - }); - - pageOne.addEventListener("click", function () { - loadPage(); - }); - pageUp.addEventListener("click", function () { - loadPage({ "newer-than": getNewestEntryId() }); - }); - pageDown.addEventListener("click", function () { - if (hasPageDown()) { - cancelRefreshTimeout(); - loadPage({ "older-than": getOldestEntryId() }); - } else { - // wrap back around to the top - loadPage(); - } - }); - - togglePageUpDown(); -}); diff --git a/war/src/main/js/pages/project/builds-card.js b/war/src/main/js/pages/project/builds-card.js new file mode 100644 index 000000000000..bea375d337d8 --- /dev/null +++ b/war/src/main/js/pages/project/builds-card.js @@ -0,0 +1,142 @@ +import debounce from "lodash/debounce"; +import behaviorShim from "@/util/behavior-shim"; + +// Card/item controls +const buildHistoryPage = document.getElementById("buildHistoryPage"); +const pageSearch = buildHistoryPage.querySelector(".jenkins-search"); +const pageSearchInput = buildHistoryPage.querySelector("input"); +const ajaxUrl = buildHistoryPage.getAttribute("page-ajax"); +const card = document.querySelector("#jenkins-builds"); +const contents = card.querySelector("#jenkins-build-history"); +const container = card.querySelector(".app-builds-container"); +const noBuilds = card.querySelector("#no-builds"); + +// Pagination controls +const paginationControls = document.querySelector("#controls"); +const paginationPrevious = document.querySelector("#up"); +const paginationNext = document.querySelector("#down"); + +// Refresh variables +let buildRefreshTimeout; +const updateBuildsRefreshInterval = 5000; + +/** + * Refresh the 'Builds' card + * @param {QueryParameters} options + */ +function load(options = {}) { + /** @type {QueryParameters} */ + const params = Object.assign({}, options, { search: pageSearchInput.value }); + + // Avoid fetching if the page isn't active + if (document.hidden) { + return; + } + + fetch(ajaxUrl + toQueryString(params)).then((rsp) => { + if (rsp.ok) { + rsp.text().then((responseText) => { + container.classList.remove("app-builds-container--loading"); + pageSearch.classList.remove("jenkins-search--loading"); + + // Show the 'No builds' text if there are no builds + if (responseText.trim() === "") { + contents.innerHTML = ""; + noBuilds.style.display = "block"; + updateCardControls({ + pageHasUp: false, + pageHasDown: false, + pageEntryNewest: false, + pageEntryOldest: false, + }); + return; + } + + // Show the refreshed builds list + contents.innerHTML = responseText; + noBuilds.style.display = "none"; + behaviorShim.applySubtree(contents); + + // Show the card controls + const div = document.createElement("div"); + div.innerHTML = responseText; + const innerChild = div.children[0]; + updateCardControls({ + pageHasUp: innerChild.dataset.pageHasUp === "true", + pageHasDown: innerChild.dataset.pageHasDown === "true", + pageEntryNewest: innerChild.dataset.pageEntryNewest, + pageEntryOldest: innerChild.dataset.pageEntryOldest, + }); + }); + } else { + console.error("Failed to load 'Builds' card, response from API is:", rsp); + } + }); +} + +/** + * Shows/hides the card's pagination controls depending on the passed parameter + * @param {CardControlsOptions} parameters + */ +function updateCardControls(parameters) { + paginationControls.classList.toggle( + "jenkins-hidden", + !parameters.pageHasUp && !parameters.pageHasDown, + ); + paginationPrevious.classList.toggle( + "app-builds-container__button--disabled", + !parameters.pageHasUp, + ); + paginationNext.classList.toggle( + "app-builds-container__button--disabled", + !parameters.pageHasDown, + ); + + // We only want the list to refresh if the user is on the first page of results + if (!parameters.pageHasUp) { + createRefreshTimeout(); + } else { + cancelRefreshTimeout(); + } + + buildHistoryPage.dataset.pageEntryNewest = parameters.pageEntryNewest; + buildHistoryPage.dataset.pageEntryOldest = parameters.pageEntryOldest; +} + +paginationPrevious.addEventListener("click", () => { + load({ "newer-than": buildHistoryPage.dataset.pageEntryNewest }); +}); + +paginationNext.addEventListener("click", () => { + cancelRefreshTimeout(); + load({ "older-than": buildHistoryPage.dataset.pageEntryOldest }); +}); + +function createRefreshTimeout() { + cancelRefreshTimeout(); + buildRefreshTimeout = window.setTimeout( + () => load(), + updateBuildsRefreshInterval, + ); +} + +function cancelRefreshTimeout() { + if (buildRefreshTimeout) { + window.clearTimeout(buildRefreshTimeout); + buildRefreshTimeout = undefined; + } +} + +const debouncedLoad = debounce(() => { + load(); +}, 150); + +document.addEventListener("DOMContentLoaded", function () { + pageSearchInput.addEventListener("input", function () { + container.classList.add("app-builds-container--loading"); + pageSearch.classList.add("jenkins-search--loading"); + debouncedLoad(); + }); + + load(); +}); diff --git a/war/src/main/js/pages/project/builds-card.types.js b/war/src/main/js/pages/project/builds-card.types.js new file mode 100644 index 000000000000..4745f088bd43 --- /dev/null +++ b/war/src/main/js/pages/project/builds-card.types.js @@ -0,0 +1,16 @@ +/** + * @typedef QueryParameters + * @type {object} + * @property {string | undefined} search + * @property {string | undefined} older-than + * @property {string | undefined} newer-than + */ + +/** + * @typedef CardControlsOptions + * @type {object} + * @property {boolean} pageHasUp + * @property {boolean} pageHasDown + * @property {string | undefined} pageEntryNewest + * @property {string | undefined} pageEntryOldest + */ diff --git a/war/src/main/resources/images/symbols/error.svg b/war/src/main/resources/images/symbols/error.svg new file mode 100644 index 000000000000..1c236a7a2cf1 --- /dev/null +++ b/war/src/main/resources/images/symbols/error.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/war/src/main/resources/images/symbols/expand.svg b/war/src/main/resources/images/symbols/expand.svg new file mode 100644 index 000000000000..0ad346df7f67 --- /dev/null +++ b/war/src/main/resources/images/symbols/expand.svg @@ -0,0 +1 @@ + diff --git a/war/src/main/resources/images/symbols/flask.svg b/war/src/main/resources/images/symbols/flask.svg new file mode 100644 index 000000000000..9c4c478d820d --- /dev/null +++ b/war/src/main/resources/images/symbols/flask.svg @@ -0,0 +1 @@ +Flask \ No newline at end of file diff --git a/war/src/main/resources/images/symbols/menu.svg b/war/src/main/resources/images/symbols/menu.svg new file mode 100644 index 000000000000..fadc2bab3081 --- /dev/null +++ b/war/src/main/resources/images/symbols/menu.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/war/src/main/resources/images/symbols/paper-plane-outline.svg b/war/src/main/resources/images/symbols/paper-plane-outline.svg new file mode 100644 index 000000000000..5ff87689259a --- /dev/null +++ b/war/src/main/resources/images/symbols/paper-plane-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/war/src/main/resources/images/symbols/weather-icon-health-00to19.svg b/war/src/main/resources/images/symbols/weather-icon-health-00to19.svg index 73e2f674a987..9e11cbcbb9eb 100644 --- a/war/src/main/resources/images/symbols/weather-icon-health-00to19.svg +++ b/war/src/main/resources/images/symbols/weather-icon-health-00to19.svg @@ -1,5 +1,5 @@ - - - - + + + + diff --git a/war/src/main/resources/images/symbols/weather-icon-health-20to39.svg b/war/src/main/resources/images/symbols/weather-icon-health-20to39.svg index f11877eb60db..1766284038bb 100644 --- a/war/src/main/resources/images/symbols/weather-icon-health-20to39.svg +++ b/war/src/main/resources/images/symbols/weather-icon-health-20to39.svg @@ -1,8 +1,8 @@ - - - - - - + + + + + + diff --git a/war/src/main/resources/images/symbols/weather-icon-health-60to79.svg b/war/src/main/resources/images/symbols/weather-icon-health-60to79.svg index bd4ed3d4c452..c6caf30230ce 100644 --- a/war/src/main/resources/images/symbols/weather-icon-health-60to79.svg +++ b/war/src/main/resources/images/symbols/weather-icon-health-60to79.svg @@ -1,8 +1,8 @@ - - - - - - - + + + + + + + diff --git a/war/src/main/scss/abstracts/_theme.scss b/war/src/main/scss/abstracts/_theme.scss index 673ba34dcfb4..cc21f1e8ab90 100644 --- a/war/src/main/scss/abstracts/_theme.scss +++ b/war/src/main/scss/abstracts/_theme.scss @@ -39,7 +39,7 @@ $semantics: ( --font-size-base: 1rem; // 16px --font-size-sm: 0.875rem; // 14px --font-size-xs: 0.75rem; // 12px - --font-size-monospace: 0.95em; + --font-size-monospace: 1em; // Line height --line-height-base: 1.5; @@ -52,9 +52,9 @@ $semantics: ( --dark-grey: #4d545d; // branding - --secondary: hsl(240, 10%, 50%); - --focus-input-border: #063f61; - --focus-input-glow: #{color.change(#0b6aa2, $alpha: 0.25)}; + --secondary: rgb(96, 125, 159); + --focus-input-border: var(--accent-color); + --focus-input-glow: color-mix(in sRGB, var(--accent-color) 15%, transparent); // Deprecated --focus-btn-primary: #{color.change(#0b6aa2, $alpha: 0.5)}; @@ -174,8 +174,8 @@ $semantics: ( --table-header-foreground: var(--text-color); --table-body-background: var(--background); --table-body-foreground: var(--text-color); - --table-border-radius: 10px; - --table-row-border-radius: 4px; + --table-border-radius: 0.75rem; + --table-row-border-radius: 0.3125rem; // Deprecated --even-row-color: var(--very-light-grey); @@ -197,7 +197,7 @@ $semantics: ( --link-text-decoration: none; --link-text-decoration--hover: underline; --link-text-decoration--active: underline; - --link-font-weight: 500; + --link-font-weight: 450; // Tooltips --tooltip-backdrop-filter: contrast(0.6) brightness(2.4) saturate(2) @@ -244,7 +244,7 @@ $semantics: ( --pane-link-color--visited: black; // Cards - --card-background: transparent; + --card-background: var(--background); --card-background--hover: transparent; --card-background--active: transparent; --card-border-color: hsla(240, 25%, 75%, 0.25); @@ -277,10 +277,22 @@ $semantics: ( --task-link-bg-color--hover: var(--very-light-grey); // Form - --section-padding: 1.75rem; - --input-color: var(--white); - --input-border: #c3ccd1; - --input-border-hover: #5c7889; + --section-padding: 1.625rem; + --input-color: color-mix( + in sRGB, + var(--text-color-secondary) 1.5%, + var(--background) + ); + --input-border: color-mix( + in sRGB, + var(--text-color-secondary) 25%, + transparent + ); + --input-border-hover: color-mix( + in sRGB, + var(--text-color-secondary) 50%, + transparent + ); --input-hidden-password-bg-color: #f9f9f9; --form-item-max-width: min(65vw, 1600px); --form-item-max-width--medium: min(50vw, 1400px); @@ -294,9 +306,9 @@ $semantics: ( --form-item-max-width--small: 100%; } - --form-label-font-weight: 500; - --form-input-padding: 0.5rem; - --form-input-border-radius: 6px; + --form-label-font-weight: 450; + --form-input-padding: 0.625rem; + --form-input-border-radius: 0.625rem; --form-input-glow: 0 0 0 10px transparent; --form-input-glow--focus: 0 0 0 5px var(--focus-input-glow); --pre-background: rgba(0, 0, 0, 0.05); diff --git a/war/src/main/scss/base/_style.scss b/war/src/main/scss/base/_style.scss index b4a6effefdb0..e586248d18a8 100644 --- a/war/src/main/scss/base/_style.scss +++ b/war/src/main/scss/base/_style.scss @@ -155,7 +155,7 @@ pre { background-color: var(--pre-background); color: var(--pre-color); font-family: var(--font-family-mono); - font-weight: 500; + font-weight: 400; line-height: 1.66; a { @@ -449,189 +449,6 @@ div.listview-jobs { display: block; } -/* ========================= build history ========================= */ -#buildHistory a:visited { - color: fuchsia; -} - -#buildHistory tr.no-wrap td.middle-align { - padding: 0; -} - -#buildHistory .desc { - position: relative; - padding: 0; - margin-top: 5px; - white-space: normal; - color: var(--text-color-secondary); - word-break: break-word; -} - -#buildHistory .build-row-cell { - position: relative; -} - -#buildHistory .build-rss-links { - display: flex; - justify-content: end; -} - -#buildHistory .build-rss-links a { - display: inline-flex; - align-items: center; - margin-right: 0.5rem; -} - -#buildHistory .build-rss-all-icon, -#buildHistory .build-rss-failed-icon { - margin-right: 0.25rem; - - svg { - width: 16px; - height: 16px; - } -} - -#buildHistoryPage { - position: relative; - - .build-search-row, - .build-search-no-results-row { - &:hover { - background: transparent !important; - } - - td { - padding: 0 8px 8px; - } - } - - .build-search-no-results-row { - border: none !important; - width: 100% !important; - background: transparent; - - td { - padding-top: 0 !important; - } - } -} - -#buildHistoryPageNav { - position: absolute; - right: -28px; - top: 96px; - border-radius: 6px; - background: var(--input-color); - border: 2px solid var(--input-border); - visibility: hidden; - z-index: 0; - opacity: 0; - transition: 0.2s ease; - - // Invisible pseudo element on the left so #buildHistoryPageNav - // doesn't disappear when moving cursor over gap - &::before { - content: ""; - position: absolute; - top: 0; - left: -8px; - bottom: 0; - width: 8px; - background: transparent; - z-index: -1; - } - - .buildHistoryPageNav__item { - position: relative; - display: flex; - align-items: center; - justify-content: center; - flex-direction: column; - padding: 0 8px; - height: 30px; - cursor: pointer; - transition: opacity 0.2s ease; - - &:hover { - opacity: 0.5; - } - - &:active { - opacity: 0.25; - } - - &:not(:last-child) { - border-bottom: 2px solid rgba(0, 0, 0, 0.05); - } - - &-page-one-top { - width: 12px; - height: 2px; - background: currentColor; - margin: 2px 0; - border-radius: 2px; - } - - svg { - fill: currentColor; - width: 12px; - height: 12px; - } - } -} - -#buildHistoryPageNav.mouseOverSidePanel { - visibility: visible; - right: -32px; - opacity: 1; -} - -.build-row.model-link-active { - background: var(--light-grey) !important; -} - -.build-row-cell { - font-size: var(--font-size-xs); -} - -.build-row-cell .pane.build-name { - width: 25%; - font-weight: 500; - vertical-align: top; -} - -.build-row-cell .pane.build-details { - width: 50%; -} - -.build-row-cell .pane.build-controls { - width: 25%; - text-align: right; -} - -.build-row-cell .pane.build-details.block { - width: 100%; -} - -.pane.build-name a, -.pane.build-name a:visited { - color: var(--pane-link-color); - text-decoration: underline; -} - -.pane.build-details a, -.pane.build-details a:visited { - color: var(--pane-link-color--visited); - opacity: 0.6; - text-decoration: none; -} - -.pane.build-details a:hover { - opacity: 1; - text-decoration: underline; -} - /* ================ Element overflow calculation helper styles ================ */ .force-wrap, @@ -778,7 +595,7 @@ table.fingerprint-in-build td { } .radioBlock-container { - margin-bottom: calc(var(--section-padding) / 3); + margin-bottom: 0.875rem; &:last-of-type { margin-bottom: var(--section-padding); @@ -787,6 +604,7 @@ table.fingerprint-in-build td { .optionalBlock-container > .form-container, .radioBlock-container > .form-container, +.jenkins-radio__children, .dropdownList-container { position: relative; padding-left: 32px; @@ -1063,6 +881,18 @@ body.no-sticker #bottom-sticker { } /* see the Icon class for the definition of these CSS classes */ +.icon-xs, +svg.icon-xs { + width: 12px; + height: 12px; + vertical-align: middle; + + svg { + width: 12px; + height: 12px; + } +} + .icon-sm, svg.icon-sm { width: 16px; diff --git a/war/src/main/scss/base/_typography.scss b/war/src/main/scss/base/_typography.scss index 2b35478325fa..0dceec4624a6 100644 --- a/war/src/main/scss/base/_typography.scss +++ b/war/src/main/scss/base/_typography.scss @@ -49,7 +49,7 @@ h5, h6, .h6 { line-height: var(--line-height-heading); - font-weight: 650; + font-weight: 600; display: block; margin-top: 0; margin-bottom: var(--section-padding); @@ -62,12 +62,12 @@ h1, h2, .h2 { - font-size: 1.35rem; + font-size: 1.375rem; } h3, .h3 { - font-size: 1.2rem; + font-size: 1.1875rem; } h4, @@ -77,12 +77,12 @@ h4, h5, .h5 { - font-size: 0.8rem; + font-size: 0.8125rem; } h6, .h6 { - font-size: 0.6rem; + font-size: 0.625rem; } .jenkins-description { diff --git a/war/src/main/scss/components/_app-bar.scss b/war/src/main/scss/components/_app-bar.scss index 0cff962e7967..b1b30048ca70 100644 --- a/war/src/main/scss/components/_app-bar.scss +++ b/war/src/main/scss/components/_app-bar.scss @@ -9,7 +9,7 @@ justify-content: center; flex-direction: column; width: 100%; - min-height: 36px; + min-height: 2.25rem; } .jenkins-app-bar__controls { @@ -17,20 +17,14 @@ align-items: center; justify-content: center; margin-left: var(--section-padding); - min-height: 36px; - gap: 1rem; + min-height: 2.25rem; + gap: 0.75rem; .jenkins-search { min-width: 260px; } } - &--border { - margin-bottom: var(--section-padding); - padding-bottom: var(--section-padding); - border-bottom: 2px solid var(--panel-border-color); - } - &--sticky { position: sticky; top: 40px; @@ -69,6 +63,11 @@ margin: 0; font-size: 1.5rem; } + + &__subtitle { + color: var(--text-color-secondary); + margin-left: 0.5ch; + } } .jenkins-build-caption { diff --git a/war/src/main/scss/components/_breadcrumbs.scss b/war/src/main/scss/components/_breadcrumbs.scss index dda12847140e..f50677846430 100644 --- a/war/src/main/scss/components/_breadcrumbs.scss +++ b/war/src/main/scss/components/_breadcrumbs.scss @@ -26,7 +26,7 @@ justify-content: center; color: var(--text-color); font-weight: 500; - font-size: 0.85rem; + font-size: 0.875rem; padding: 0.2rem 0.4rem; & > a { diff --git a/war/src/main/scss/components/_buttons.scss b/war/src/main/scss/components/_buttons.scss index 5108aca2c6eb..4812949af07c 100644 --- a/war/src/main/scss/components/_buttons.scss +++ b/war/src/main/scss/components/_buttons.scss @@ -14,15 +14,14 @@ border: none; outline: none; margin: 0; - padding: 0.5rem 0.85rem; - font-size: 0.8125rem; - font-weight: 500; + padding: 0.5rem 0.9rem; + font-size: 0.875rem; text-decoration: none !important; background: transparent; color: var(--text-color) !important; border-radius: 0.66rem; cursor: pointer; - min-height: 36px; + min-height: 2.25rem; white-space: nowrap; gap: 1ch; transition: var(--standard-transition); @@ -32,8 +31,8 @@ } svg { - width: 1.1rem; - height: 1.1rem; + width: 1.125rem; + height: 1.125rem; } &:disabled { @@ -45,7 +44,6 @@ .jenkins-button--primary { color: var(--button-color--primary) !important; - font-weight: 600; &::before { background: var(--accent-color) !important; diff --git a/war/src/main/scss/components/_cards.scss b/war/src/main/scss/components/_cards.scss new file mode 100644 index 000000000000..be86bb390337 --- /dev/null +++ b/war/src/main/scss/components/_cards.scss @@ -0,0 +1,97 @@ +$card-padding: 1rem; + +.jenkins-card { + position: relative; + border-radius: 1rem; + margin-bottom: calc(var(--section-padding) / 2); + background: var(--card-background); + + &__title { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 $card-padding; + height: 50px; + font-size: var(--font-size-sm) !important; + font-weight: 500; + width: 100%; + z-index: 1; + } + + &__controls { + display: flex; + align-items: center; + justify-content: center; + gap: 0.4rem; + margin-right: -0.2rem; + } + + &:not(:hover) { + .jenkins-card__unveil { + color: var(--text-color-secondary) !important; + } + } + + &:hover { + .jenkins-card__reveal { + color: var(--text-color) !important; + } + } + + &__content { + display: flex; + flex-direction: column; + padding: 0 $card-padding $card-padding; + color: var(--text-color-secondary); + + &:empty { + display: none; + } + } + + &::after { + content: ""; + position: absolute; + inset: 0; + border-radius: inherit; + border: var(--card-border-width) solid var(--card-border-color); + z-index: 1; + pointer-events: none; + } + + .jenkins-card__reveal { + display: flex; + align-items: center; + justify-content: center; + margin-block: -0.5rem; + min-height: 0; + padding: 0; + width: 26px; + height: 26px; + border-radius: 0.33rem; + color: var(--text-color-secondary) !important; + transition: + scale var(--standard-transition), + opacity var(--standard-transition); + + svg { + width: 1rem; + height: 1rem; + transition: color var(--standard-transition); + } + + &::before, + &::after { + opacity: 0; + } + + &:hover { + opacity: 0.75; + } + + &:active { + scale: 95%; + opacity: 0.5; + } + } +} diff --git a/war/src/main/scss/components/_dialogs.scss b/war/src/main/scss/components/_dialogs.scss index a53831e5acb1..3de2d0c883a0 100644 --- a/war/src/main/scss/components/_dialogs.scss +++ b/war/src/main/scss/components/_dialogs.scss @@ -19,8 +19,8 @@ $jenkins-dialog-padding: 1.3rem; } &__title { - font-size: 1.1rem; - font-weight: 600; + font-size: 1.125rem; + font-weight: 500; padding: 0 $jenkins-dialog-padding; color: var(--text-color); } @@ -58,7 +58,7 @@ $jenkins-dialog-padding: 1.3rem; &__subtitle { font-size: 1rem; - font-weight: 600; + font-weight: 500; color: var(--text-color-secondary); padding: 0; margin: 0 0 1rem; diff --git a/war/src/main/scss/components/_dropdowns.scss b/war/src/main/scss/components/_dropdowns.scss index 586a07fc5adf..7268773f8fab 100644 --- a/war/src/main/scss/components/_dropdowns.scss +++ b/war/src/main/scss/components/_dropdowns.scss @@ -92,7 +92,7 @@ $dropdown-padding: 0.4rem; color: var(--text-color-secondary) !important; margin: $dropdown-padding 0.55rem; font-size: 0.8125rem; - font-weight: 600; + font-weight: 500; opacity: 0.8; &:not(:first-of-type) { @@ -133,7 +133,7 @@ $dropdown-padding: 0.4rem; margin: 0; padding: $dropdown-padding 1.75rem $dropdown-padding 0.6rem; font-size: 0.8125rem; - font-weight: 500; + font-weight: 450; text-decoration: none !important; background: transparent; color: var(--text-color) !important; @@ -254,3 +254,18 @@ $dropdown-padding: 0.4rem; border-radius: 50%; } } + +.jenkins-jumplist-link { + appearance: none; + border: none; + background: none; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + + svg { + width: 1.25rem; + height: 1.25rem; + } +} diff --git a/war/src/main/scss/components/_index.scss b/war/src/main/scss/components/_index.scss index 3048d06ae2c5..f3167bd091f9 100644 --- a/war/src/main/scss/components/_index.scss +++ b/war/src/main/scss/components/_index.scss @@ -2,8 +2,9 @@ @use "alert"; @use "badges"; @use "breadcrumbs"; -@use "buttons-deprecated"; @use "buttons"; +@use "buttons-deprecated"; +@use "cards"; @use "content-blocks"; @use "dialogs"; @use "dropdowns"; diff --git a/war/src/main/scss/components/_progress-bar.scss b/war/src/main/scss/components/_progress-bar.scss index 1e1faf37d630..2a92b570a226 100644 --- a/war/src/main/scss/components/_progress-bar.scss +++ b/war/src/main/scss/components/_progress-bar.scss @@ -10,7 +10,6 @@ var(--text-color-secondary) 25%, transparent ); - margin-top: 2px; display: block; opacity: 1 !important; diff --git a/war/src/main/scss/components/_section.scss b/war/src/main/scss/components/_section.scss index a637deb6181e..9a53a7238339 100644 --- a/war/src/main/scss/components/_section.scss +++ b/war/src/main/scss/components/_section.scss @@ -30,8 +30,8 @@ .jenkins-section__title { margin: 0 0 var(--section-padding) 0; - font-size: 1.1rem; - font-weight: 600; + font-size: 1rem; + font-weight: 500; } .jenkins-section__items { @@ -106,17 +106,17 @@ } dt { - font-size: 0.925rem; - font-weight: 600; + font-size: 0.9375rem; + font-weight: 500; margin: 0.1rem 0 0.2rem; color: var(--text-color); } dd { color: var(--text-color-secondary); - font-weight: 500; + font-weight: 450; line-height: 1.6; margin: 0 0.66rem 0 0; - font-size: 0.925rem; + font-size: 0.9375rem; } } diff --git a/war/src/main/scss/components/_side-panel-tasks.scss b/war/src/main/scss/components/_side-panel-tasks.scss index df5a362315d0..1ae9168ce235 100644 --- a/war/src/main/scss/components/_side-panel-tasks.scss +++ b/war/src/main/scss/components/_side-panel-tasks.scss @@ -8,7 +8,7 @@ $background-outset: 0.7rem; display: flex; flex-direction: column; margin: var(--section-padding); - gap: 5px; + gap: 0.125rem; /* stylelint-disable-next-line media-query-no-invalid */ @media (min-width: breakpoints.$tablet-breakpoint) { @@ -63,11 +63,11 @@ $background-outset: 0.7rem; align-items: center; justify-content: flex-start; padding: 0.55rem $background-outset; - gap: 0.75rem; + gap: 0.65rem; width: 100%; cursor: pointer; - font-weight: 500 !important; - font-size: 0.9rem; + font-weight: 450 !important; + font-size: 0.875rem; color: var(--text-color) !important; background: transparent; outline: none; @@ -101,11 +101,11 @@ $background-outset: 0.7rem; } &--active { - font-weight: 600 !important; + font-weight: 500 !important; cursor: default; svg * { - stroke-width: 38px; + stroke-width: 35px; } &::before { diff --git a/war/src/main/scss/components/_side-panel-widgets.scss b/war/src/main/scss/components/_side-panel-widgets.scss index 6772890bbffa..6771da8d1d92 100644 --- a/war/src/main/scss/components/_side-panel-widgets.scss +++ b/war/src/main/scss/components/_side-panel-widgets.scss @@ -49,6 +49,11 @@ } } +#side-panel .pane-header-details { + font-weight: normal; + font-size: var(--font-size-xs); +} + #side-panel .pane-content { font-size: var(--font-size-xs); } @@ -87,168 +92,59 @@ /** * Executors */ -#executors th.pane { - text-align: left; -} - -/** - * Build history - */ -.build-row { - padding: 3px 4px; -} - -.build-row.model-link-active { - background: var(--very-light-grey) !important; -} - -.build-row-cell { - font-size: var(--font-size-xs); -} - -.build-row-cell .pane.build-name { - width: 32%; - font-weight: 500; - vertical-align: top; -} - -.build-row-cell .pane.build-details { - width: 50%; -} - -.build-row-cell .pane.build-controls { - width: 18%; - text-align: right; -} - -.build-row-cell .pane.build-details.block { - width: 100%; -} - -.build-row.multi-line .build-row-cell .pane.build-name.block { - width: 100%; -} - -.build-row-cell .pane.build-controls.block { - width: 100%; -} - -.build-row-cell .pane.build-name .build-icon, -.build-row-cell .pane.build-name .display-name { - display: inline-block; -} - -.build-row-cell .pane.build-name .build-icon { - position: absolute; - margin-top: 2px; - z-index: 1; -} - -.build-row-cell .build-stop { - display: inline-block; - width: 30%; -} - -.build-row-cell .build-badge { - display: inline-block; - text-align: right; - width: 70%; - padding: 2px 0; -} - -.build-row-cell .build-badge > span { - display: inline-block; - max-width: 256px; - padding: 0 1px; - overflow: hidden; -} - -.build-row-cell .build-badge > span + span { - margin: 0 0 0 2px !important; -} - -@media (width >= 1170px) { - .build-row-cell .build-badge > span { - max-width: 296px; +#executors { + th.pane { + text-align: left; } -} - -.build-row .build-name-controls .pane.build-name, -.build-row .build-details-controls .pane.build-details { - width: 70%; -} - -.build-row .build-row-cell .pane, -#side-panel .build-row .build-row-cell .pane { - padding: 0 2px; /* Sync changes with func expandControlsTo50Percent in hudson-behavior.js */ - display: inline-block; - overflow: hidden; -} -.build-row.multi-line .build-row-cell .block { - display: block; - overflow: auto; -} - -.build-row.multi-line .build-row-cell .indent-multiline { - margin-top: 5px; -} - -.build-row.multi-line .build-row-cell .left-bar { - position: absolute; - top: 31px; - bottom: 10px; - left: 17px; - border-left: 1px solid var(--medium-grey); -} + .pane-header { + align-items: center; + } -.build-row-cell .pane.build-name .display-name { - margin-left: 20px; - word-break: break-all; -} + .computer-caption { + display: flex; + gap: 5px; + padding: 0.5rem 1rem; -.build-row-cell .indent-multiline { - padding-left: 20px !important; /* Sync changes with func expandControlsTo50Percent in hudson-behavior.js */ -} + & > div { + margin-left: auto; + align-self: end; + } + } -.build-row.overflow-checked .build-row-cell { - visibility: visible; -} + .executors-cell { + padding: 0 1rem; + } -.jenkins-pane { - &__information { - text-align: center; - line-height: 80px; - background-color: var(--panel-header-bg-color); - margin-top: 10px; - font-weight: 600; - border-radius: var(--form-input-border-radius); + .executors-collapsed { + padding: 0 1rem 0.5rem; } - .build-row { - transition: opacity 0.2s ease; + .executor-row { + display: flex; + padding: 0 0 0.5rem; + align-items: center; + } - &-cell { - padding: 4px 8px; - } + .executor-type { + width: 16px; + margin-right: 1ch; } - &--loading .build-row { - opacity: 0.5; + .executor-cell { + width: 100%; } -} -.jenkins-pane__header--build-history { - display: grid; - grid-template-columns: auto 1fr auto; - font-weight: 500 !important; + .executor-cell-table .pane { + margin: 0 !important; + padding: 0 !important; - .build-health-link { - margin: -9px -15px; + & > div { + margin-right: 15px; + } } - .jenkins-table__cell--tight { - width: auto; - margin-right: 1rem; + .executor-stop { + width: 16px; } } diff --git a/war/src/main/scss/components/_spinner.scss b/war/src/main/scss/components/_spinner.scss index a538e89c355c..af5732ca8320 100644 --- a/war/src/main/scss/components/_spinner.scss +++ b/war/src/main/scss/components/_spinner.scss @@ -2,8 +2,8 @@ position: relative; display: inline-flex; align-items: center; - font-size: 0.85rem; - font-weight: 600; + font-size: 0.875rem; + font-weight: 500; margin: 0; &::before, diff --git a/war/src/main/scss/components/_table.scss b/war/src/main/scss/components/_table.scss index 73b033f0c1b6..f247407a8f3b 100644 --- a/war/src/main/scss/components/_table.scss +++ b/war/src/main/scss/components/_table.scss @@ -3,14 +3,25 @@ .jenkins-table { --table-padding: 0.55rem; + position: relative; width: 100%; background: var(--table-background); - border-radius: calc(var(--table-border-radius) + 2px); - border: 5px solid var(--table-background); - border-bottom-width: 3px; + border-radius: calc(var(--table-border-radius) + 4px); + border: 4px solid var(--table-background); + border-bottom-width: 2px; border-spacing: 0 2px; + background-clip: padding-box; margin-bottom: var(--section-padding); + &::before { + content: ""; + position: absolute; + inset: -4px -4px -2px; + border: var(--card-border-width) solid var(--table-border-color); + border-radius: inherit; + pointer-events: none; + } + * { -webkit-border-horizontal-spacing: 0; -webkit-border-vertical-spacing: 0; @@ -21,11 +32,11 @@ & > th { color: var(--table-header-foreground); text-align: left; - padding-top: calc((var(--table-padding) * 1.7) - 7.5px); - padding-bottom: calc((var(--table-padding) * 1.7) - 2.5px); + padding-top: calc(var(--table-padding) * 0.9); + padding-bottom: calc((var(--table-padding) * 0.9) + 2px); padding-left: 1.6rem; - font-weight: 600; - font-size: 0.85rem; + font-weight: 500; + font-size: 0.875rem; &[align="center"] { text-align: center; @@ -69,7 +80,6 @@ background: var(--table-body-background); vertical-align: middle; padding: var(--table-padding) 0 var(--table-padding) 1.6rem; - font-weight: 500; height: 3rem; &:first-of-type { @@ -157,11 +167,12 @@ .jenkins-button { margin: -10px 0; padding: 0.5rem 0.75rem; + min-height: 1.75rem; // Increase the size of symbols compared to regular buttons svg { - width: 1.375rem !important; - height: 1.375rem !important; + width: 1.5rem !important; + height: 1.5rem !important; } } @@ -170,8 +181,8 @@ svg, .build-status-icon__wrapper, img { - width: 1.375rem !important; - height: 1.375rem !important; + width: 1.5rem !important; + height: 1.5rem !important; } } @@ -192,6 +203,15 @@ height: 1.3rem !important; } } + + .jenkins-button { + padding: 0.4rem 0.6rem; + + svg { + width: 1.3rem !important; + height: 1.3rem !important; + } + } } &--auto-width { @@ -215,6 +235,15 @@ height: 1rem !important; } } + + .jenkins-button { + padding: 0.3rem 0.5rem; + + svg { + width: 1rem !important; + height: 1rem !important; + } + } } &__button, diff --git a/war/src/main/scss/components/_tabs.scss b/war/src/main/scss/components/_tabs.scss index 565d62e2f81a..0e54d9646a99 100644 --- a/war/src/main/scss/components/_tabs.scss +++ b/war/src/main/scss/components/_tabs.scss @@ -3,14 +3,24 @@ } .tabBar { + position: relative; display: inline-flex; align-items: center; flex-wrap: wrap; background: var(--tabs-background); border-radius: var(--tabs-border-radius); - padding: 2.5px; + padding: 2px; margin-bottom: var(--section-padding); + &::before { + content: ""; + position: absolute; + inset: 0; + border: var(--card-border-width) solid var(--tabs-border-color); + border-radius: inherit; + pointer-events: none; + } + .tab { float: left; } @@ -23,13 +33,13 @@ justify-content: center; min-width: 3rem; text-decoration: none; - margin: 2.5px; + margin: 2px; padding: 0.4rem 1.2rem; border-radius: 100px; background: var(--tabs-item-background); color: var(--tabs-item-foreground); - font-weight: 600; - font-size: 0.85rem; + font-weight: 500; + font-size: 0.875rem; transition: var(--standard-transition); cursor: pointer; diff --git a/war/src/main/scss/components/_tooltips.scss b/war/src/main/scss/components/_tooltips.scss index 80a030b8c9c3..d864f98bd941 100644 --- a/war/src/main/scss/components/_tooltips.scss +++ b/war/src/main/scss/components/_tooltips.scss @@ -3,7 +3,7 @@ padding: 0.45rem 0.8rem; border-radius: 0.66rem; box-shadow: var(--tooltip-box-shadow); - font-weight: 550; + font-weight: 500; font-size: 0.75rem; line-height: 1.6; max-width: min(50vw, 1000px) !important; diff --git a/war/src/main/scss/form/_checkbox.scss b/war/src/main/scss/form/_checkbox.scss index 8d23d9e3977d..d9cd5f18c951 100644 --- a/war/src/main/scss/form/_checkbox.scss +++ b/war/src/main/scss/form/_checkbox.scss @@ -140,6 +140,7 @@ box-shadow: 0 0 0 10px transparent, inset 0 0 0 2px var(--input-border); + background: var(--input-color); } &::after { diff --git a/war/src/main/scss/form/_codemirror.scss b/war/src/main/scss/form/_codemirror.scss index 67520192c0e5..a34165e8ba57 100644 --- a/war/src/main/scss/form/_codemirror.scss +++ b/war/src/main/scss/form/_codemirror.scss @@ -42,6 +42,16 @@ .CodeMirror-selected { background-color: var(--selection-color) !important; } + + .CodeMirror-lines { + padding: var(--form-input-padding); + } + + .CodeMirror-gutter-text { + padding: var(--form-input-padding) calc(var(--form-input-padding) * 0.5) + var(--form-input-padding) var(--form-input-padding); + color: var(--text-color-secondary); + } } .jenkins-codemirror-resizer { diff --git a/war/src/main/scss/form/_layout.scss b/war/src/main/scss/form/_layout.scss index 0214d596c112..8983245875e2 100644 --- a/war/src/main/scss/form/_layout.scss +++ b/war/src/main/scss/form/_layout.scss @@ -45,7 +45,7 @@ font-weight: var(--form-label-font-weight); margin-top: 0; margin-bottom: 0.5rem; - padding-inline: 0 0; + padding-inline: 0; } .jenkins-form-description { @@ -93,7 +93,7 @@ background: var(--text-color); color: transparent; mask-image: url("data:image/svg+xml,%3C%3Fxml version='1.0' encoding='UTF-8'%3F%3E%3Csvg width='262px' height='482px' viewBox='0 0 262 482' version='1.1' xmlns='http://www.w3.org/2000/svg'%3E%3Cg stroke='none' stroke-width='1' fill='none' fill-rule='evenodd'%3E%3Cpath d='M69.9217381,109.622622 L69.9347383,109.509526 L69.9838606,109.158807 L70.0463523,108.766768 C70.2927563,107.286617 70.7336,105.509397 71.3554148,103.600821 C73.4488365,97.1753443 76.974163,91.0239622 81.9750299,85.3670497 C84.5508811,82.453282 87.4853512,79.7201177 90.8001215,77.1662697 C100.73686,69.5111158 114.003751,65.6584363 131.476234,65.4354882 C133.731084,65.4096204 135.996257,65.4453704 138.232058,65.5407008 L139.478148,65.6000218 C140.992957,65.679511 142.536904,65.7906863 144.04662,65.9294921 L145.210323,66.0424992 C145.886163,66.1116384 146.60564,66.1925244 147.313561,66.2795642 L148.414194,66.420922 L149.377674,66.5545415 L150.375686,66.7050246 L151.398071,66.8714663 L152.049055,66.9841252 L152.731845,67.1083183 L153.642724,67.2845248 L154.549432,67.4714994 C155.036905,67.5756456 155.574038,67.6978797 156.090422,67.8232778 L156.917997,68.0311744 C158.666031,68.484436 160.136789,68.9816723 161.141416,69.4394425 C170.146558,73.5618171 177.044937,78.1235016 182.224862,83.4639805 C188.857993,90.3027083 191.999176,97.8308192 191.999176,107.499034 C191.999176,119.466025 188.796962,127.918279 181.370643,136.250976 C181.093904,136.561492 180.816698,136.867422 180.538309,137.169526 L180.089688,137.652102 L179.736214,138.026258 L179.002023,138.784568 L178.579132,139.213445 L178.134441,139.655368 L177.707007,140.071619 L177.021999,140.726828 L176.298991,141.400731 L175.788688,141.867317 L175.318979,142.286805 L174.54297,142.970055 L173.990783,143.446079 L173.448394,143.905722 L172.625948,144.588916 L171.799887,145.262466 L170.811596,146.050172 L169.864089,146.789794 L169.222049,147.28309 L168.549302,147.793886 L167.493519,148.583956 L166.782836,149.108414 L165.65246,149.931951 L164.484527,150.770371 L163.266904,151.632649 L161.555386,152.827104 L160.682666,153.429152 L159.298283,154.375903 L157.864408,155.346877 L155.333592,157.040637 L153.750968,158.088827 L151.524574,159.551762 L148.580787,161.468911 L144.800696,163.908618 C105.775292,188.991858 87.997951,218.376069 87.997951,257.047472 L87.997951,283.286279 L88.0016284,283.748414 C88.3121212,301.66652 103.883328,316 122.998363,316 C142.328557,316 157.998775,301.353568 157.998775,283.286279 L157.998775,257.047472 L158.001383,256.432449 C158.064604,248.820487 159.375708,243.378146 162.208358,238.456376 C165.925109,231.998468 172.860638,225.357973 183.865352,218.206756 L186.747913,216.348707 L189.667785,214.457346 L192.470459,212.628123 L195.158954,210.857753 L197.739048,209.141153 L199.612339,207.881962 L201.424999,206.651521 L203.184757,205.444126 L204.893987,204.257626 L206.014818,203.471391 L207.63679,202.320739 L208.708154,201.551674 L209.751591,200.795045 L210.776652,200.043916 L211.783987,199.29767 L212.774236,198.555696 L213.748026,197.81739 L214.705977,197.082156 L215.983535,196.08689 L217.035512,195.253661 L217.94273,194.524595 L218.836751,193.796023 L219.718133,193.067399 L220.587422,192.33819 L221.445157,191.607874 L222.291869,190.87594 L223.128081,190.141889 L224.349696,189.048475 L225.176062,188.294328 L225.979581,187.549096 L227.15568,186.436436 L227.953672,185.666523 L228.73078,184.904536 L229.501513,184.136777 L230.633743,182.986693 L231.403964,182.189294 L232.15663,181.397931 L232.905389,180.598844 L233.650817,179.791592 L234.393505,178.975725 L235.134055,178.150785 C253.063009,158.033696 262,134.778085 262,107.499034 C262,81.4013251 252.315995,58.3143983 234.08637,39.5197386 C222.737894,27.8195118 209.350637,18.7642961 192.813373,11.0878005 L191.857565,10.6472715 C176.144833,3.48753386 154.016249,-0.255558118 130.568693,0.0135609187 C97.385459,0.43694412 69.212387,9.00946009 46.2762841,26.6791815 C39.5211589,31.8836333 33.4271839,37.5663685 28.0119541,43.6920026 C17.038175,56.105392 9.16079603,69.8997291 4.39056696,84.5413054 C2.80350137,89.4125897 1.62984552,94.1870463 0.865737279,98.781619 L0.782196688,99.2931802 L0.614828552,100.383438 L0.559658337,100.765066 L0.426811303,101.749189 L0.318522027,102.638537 L0.226704214,103.487005 L0.123646908,104.617718 L0.0652556787,105.43714 L0.0342145373,105.994277 C-0.81250758,124.122996 14.1596716,139.394013 33.4714881,140.181654 L33.9656162,140.198367 L34.5332314,140.20872 C53.0445487,140.409453 68.5022596,127.170521 69.8964399,109.989591 L69.9217381,109.622622 Z' fill='currentColor' fill-rule='nonzero'%3E%3C/path%3E%3Ccircle fill='currentColor' cx='123' cy='434' r='48'%3E%3C/circle%3E%3C/g%3E%3C/svg%3E"); - mask-size: 50% 50%; + mask-size: 45% 45%; mask-position: center; mask-repeat: no-repeat; } @@ -102,7 +102,7 @@ content: ""; position: absolute; inset: 0; - background: var(--text-color); + background: var(--text-color-secondary); opacity: 0.1; border-radius: inherit; transition: var(--standard-transition); @@ -112,7 +112,8 @@ content: ""; position: absolute; inset: 0; - border: 1px solid rgba(125, 125, 125, 0.35); + border: 1px solid + color-mix(in sRGB, var(--text-color-secondary), transparent); box-shadow: var(--form-input-glow); border-radius: inherit; opacity: 0.1; diff --git a/war/src/main/scss/form/_radio.scss b/war/src/main/scss/form/_radio.scss index 68f95df38f4b..a673e86d6daf 100644 --- a/war/src/main/scss/form/_radio.scss +++ b/war/src/main/scss/form/_radio.scss @@ -1,3 +1,11 @@ +$jenkins-radio-size: 1.375rem; +$jenkins-radio-border-size: 0.125rem; +$jenkins-radio-border-hover-size: 0.3125rem; +$jenkins-radio-border-active-size: 0.5rem; +$jenkins-radio-border-checked-size: 0.4rem; +$jenkins-radio-glow-size: 0.625rem; +$jenkins-radio-glow-active-size: 0.3125rem; + .jenkins-radio-help-wrapper { display: flex; align-items: center; @@ -5,69 +13,59 @@ } .jenkins-radio { - margin-top: 3px; - &:not(:last-of-type) { - margin-bottom: calc(var(--section-padding) / 3); + margin-bottom: 0.875rem; } &__input { position: absolute; opacity: 0; - margin-top: 10px; + margin-top: 0.625rem; - &:hover { - & + label { - &::before { + &:not(:checked) { + &:hover { + & + label::before { box-shadow: - 0 0 0 10px transparent, - inset 0 0 0 5px var(--input-border-hover); + 0 0 0 $jenkins-radio-glow-size transparent, + inset 0 0 0 $jenkins-radio-border-hover-size + var(--input-border-hover); } } - } - &:not(:disabled) { + &:focus-visible, &:focus, &:active { - & + label { - &::before { - transition: box-shadow var(--elastic-transition); - box-shadow: - 0 0 0 5px var(--focus-input-glow), - inset 0 0 0 5px var(--focus-input-border); - } - } - } - - &:checked { - &:focus, - &:active { - & + label { - &::before { - box-shadow: - 0 0 0 5px var(--focus-input-glow), - inset 0 0 0 8px var(--focus-input-border); - } - } + & + label::before { + box-shadow: + 0 0 0 $jenkins-radio-glow-active-size var(--focus-input-glow), + inset 0 0 0 $jenkins-radio-border-active-size + var(--focus-input-border); } } } &:checked { & + label { - &:active, - &:focus { - &::before { - box-shadow: - 0 0 0 5px var(--focus-input-glow), - inset 0 0 0 12px var(--focus-input-border); - } + cursor: default; + + &::before { + box-shadow: + 0 0 0 $jenkins-radio-glow-size transparent, + inset 0 0 0 $jenkins-radio-border-checked-size + var(--focus-input-border); } } - & + label { - &::before { - box-shadow: inset 0 0 0 8px var(--focus-input-border); + &:not(:disabled) { + &:focus-visible, + &:focus, + &:active { + & + label::before { + box-shadow: + 0 0 0 $jenkins-radio-glow-active-size var(--focus-input-glow), + inset 0 0 0 $jenkins-radio-border-active-size + var(--focus-input-border); + } } } } @@ -85,11 +83,9 @@ &__label { position: relative; - top: -5px; display: inline-block; - margin-top: 10px; margin-bottom: 0; - padding: 0 0 5px 32px; + padding: 0 0 0 2rem; cursor: pointer; font-weight: var(--form-label-font-weight); // remove 300ms pause on mobile @@ -101,54 +97,24 @@ position: absolute; top: 0; left: 0; - width: 22px; - height: 22px; + width: $jenkins-radio-size; + height: $jenkins-radio-size; border-radius: 50%; - background: transparent; + background: var(--input-color); box-shadow: - 0 0 0 10px transparent, - inset 0 0 0 2px var(--input-border); + 0 0 0 $jenkins-radio-glow-size transparent, + inset 0 0 0 $jenkins-radio-border-size var(--input-border); transition: box-shadow var(--standard-transition); } } &__description { - margin: 0 0 0 32px; + margin: 0 0 0 2rem; color: var(--text-color-secondary); line-height: 1.66; } - &__children { - position: relative; - margin-top: 10px; - opacity: 0; - padding-left: 32px; - transition: var(--standard-transition); - visibility: hidden; - max-height: 0; - - &::after { - content: ""; - position: absolute; - top: 0; - left: 10px; - bottom: 0; - width: 2px; - background: var(--input-border); - border-radius: 2px; - transition: var(--standard-transition); - } - - &:focus-within { - &::after { - background: var(--focus-input-border); - } - } - } - - &__input:checked + &__label + &__children { - visibility: visible; - opacity: 1; - max-height: none; + &__input:not(:checked) + &__label + &__children { + display: none; } } diff --git a/war/src/main/scss/form/_reorderable-list.scss b/war/src/main/scss/form/_reorderable-list.scss index c19152975d2e..7cd726556df1 100644 --- a/war/src/main/scss/form/_reorderable-list.scss +++ b/war/src/main/scss/form/_reorderable-list.scss @@ -7,6 +7,14 @@ border-radius: 10px; margin-bottom: 1rem; margin-top: 1rem; + transition: + opacity 0.2s ease-in, + max-height 0.2s ease-in; +} + +.repeated-chunk.fade-in, +.repeated-chunk.fade-out { + opacity: 0; } .repeated-chunk .show-if-last { diff --git a/war/src/main/scss/form/_search-bar.scss b/war/src/main/scss/form/_search-bar.scss index 81f7450570e4..ed552e85c987 100644 --- a/war/src/main/scss/form/_search-bar.scss +++ b/war/src/main/scss/form/_search-bar.scss @@ -21,7 +21,6 @@ 0 0 0 2px transparent, 0 0 0 12px transparent; transition: var(--standard-transition); - font-weight: 500; height: var(--search-bar-height); &::placeholder { @@ -142,7 +141,7 @@ justify-content: center; transition: 0.25s ease; text-align: center; - font-size: 0.8em; + font-size: 0.6875rem; font-weight: 500; line-height: 1; color: var(--text-color-secondary); @@ -257,7 +256,7 @@ align-items: center; gap: 0.7rem; padding: 0.5rem 0.7rem; - font-size: 0.85rem; + font-size: 0.875rem; border-radius: 10px; color: var(--text-color); font-weight: 500; diff --git a/war/src/main/scss/form/_select.scss b/war/src/main/scss/form/_select.scss index acdedfc17728..e8b2b2973b94 100644 --- a/war/src/main/scss/form/_select.scss +++ b/war/src/main/scss/form/_select.scss @@ -21,10 +21,10 @@ appearance: none; display: block; border: 2px solid var(--input-border); - padding: 8px; + padding: var(--form-input-padding); width: 100% !important; // TODO remove important after https://github.com/jenkinsci/credentials-plugin/pull/255 max-width: 100% !important; // TODO remove important after https://github.com/jenkinsci/credentials-plugin/pull/255 - border-radius: 6px; + border-radius: var(--form-input-border-radius); box-shadow: 0 0 0 10px transparent; transition: var(--standard-transition); min-height: 38px; diff --git a/war/src/main/scss/pages/_about.scss b/war/src/main/scss/pages/_about.scss index 08be61408749..b39fc84e4cd9 100644 --- a/war/src/main/scss/pages/_about.scss +++ b/war/src/main/scss/pages/_about.scss @@ -124,13 +124,13 @@ } .app-about-version { - font-weight: 600; + font-weight: 500; color: var(--text-color-secondary); margin: 0; } .app-about-paragraph { - font-size: 1.1rem; + font-size: 1.125rem; margin-bottom: var(--section-padding); font-weight: 500; } diff --git a/war/src/main/scss/pages/_dashboard.scss b/war/src/main/scss/pages/_dashboard.scss index cb029a9861a9..3ace60fac309 100644 --- a/war/src/main/scss/pages/_dashboard.scss +++ b/war/src/main/scss/pages/_dashboard.scss @@ -121,7 +121,7 @@ $min-button-size: 36px; &__label { color: var(--link-color); - font-weight: 600; + font-weight: 500; margin: 0; font-size: 1rem; } diff --git a/war/src/main/scss/pages/_icon-legend.scss b/war/src/main/scss/pages/_icon-legend.scss index 02cb37cff584..9d62a5c084aa 100644 --- a/war/src/main/scss/pages/_icon-legend.scss +++ b/war/src/main/scss/pages/_icon-legend.scss @@ -23,7 +23,7 @@ dd { margin: 0; padding: 0; - font-size: 0.95rem; + font-size: 0.9375rem; font-weight: 500; line-height: 1.6; } diff --git a/war/src/main/scss/pages/_index.scss b/war/src/main/scss/pages/_index.scss index 0e0b224dc6a0..c8e20e272271 100644 --- a/war/src/main/scss/pages/_index.scss +++ b/war/src/main/scss/pages/_index.scss @@ -2,6 +2,7 @@ @use "build"; @use "dashboard"; @use "icon-legend"; +@use "job"; @use "manage-jenkins"; @use "plugin-manager"; @use "setupWizardFirstUser"; diff --git a/war/src/main/scss/pages/_job.scss b/war/src/main/scss/pages/_job.scss new file mode 100644 index 000000000000..3b982fcffcf4 --- /dev/null +++ b/war/src/main/scss/pages/_job.scss @@ -0,0 +1,184 @@ +@use "../abstracts/mixins"; + +#buildHistoryPage { + margin: 10px 0 10px 10px; + + .jenkins-search { + margin-inline: -0.25rem; + margin-bottom: 5px; + } +} + +.app-builds-container { + transition: opacity var(--standard-transition); + + &__items { + margin-bottom: -0.5rem; + } + + &__placeholder { + display: flex; + align-items: center; + justify-content: center; + text-align: center; + padding: 3rem; + animation: fade-in-builds-placeholder var(--standard-transition); + + @keyframes fade-in-builds-placeholder { + from { + opacity: 0; + } + } + } + + &__heading { + display: flex; + font-size: 0.75rem; + color: var(--text-color-secondary); + margin-top: 10px; + font-weight: 450; + margin-bottom: 4px; + } + + &__controls { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 15px; + margin: 0 -0.35rem; + margin-top: 1rem; + margin-bottom: -0.5rem; + + .jenkins-button { + padding: 10px; + + svg { + transition: translate var(--standard-transition); + } + + &:first-of-type { + justify-content: start; + + &:hover { + translate: -2px 0; + + svg { + translate: -4px 0; + } + } + } + + &:last-of-type { + justify-content: end; + + &:hover { + translate: 2px 0; + + svg { + translate: 4px 0; + } + } + } + } + + .app-builds-container__button--disabled { + color: var(--text-color-secondary) !important; + opacity: 0.25; + pointer-events: none; + } + } + + &--loading { + opacity: 0.4; + filter: blur(0.5px); + } +} + +.app-builds-container__item { + @include mixins.item(); + + display: grid; + grid-template-columns: auto 1fr auto; + gap: 0.5rem 0.65rem; + padding: 0 0 0.25rem; + margin: 0 -0.5rem; + font-size: 0.8125rem !important; + min-height: 2rem; + + &__icon { + display: inline-flex; + justify-content: center; + padding: 0 0 0 0.5rem; + margin-top: 0.385rem; + + svg { + width: 1.25rem; + height: 1.25rem; + } + } + + .app-builds-container__item__inner { + display: flex; + align-items: stretch; + flex-wrap: wrap; + + &__link { + display: flex; + color: var(--text-color); + gap: 0.5rem; + text-decoration: none; + font-weight: 450; + flex-grow: 1; + padding: 0.45rem 0 0; + + .app-builds-container__item__time { + color: var(--text-color-secondary); + } + } + + &__controls { + display: flex; + align-items: center; + justify-content: start; + flex-wrap: wrap; + gap: 0.5rem; + margin-top: 0.3rem; + } + } + + &--not-interactable { + cursor: default; + + &::before, + &::after { + display: none; + } + + .app-builds-container__item__description { + margin-bottom: 0; + } + } + + .jenkins-jumplist-link { + margin-top: 0.2rem; + padding-right: 0.8rem; + } + + &__description { + color: var(--text-color-secondary); + padding-left: 2.25rem; + margin-top: -2px; + grid-column: 1 / span 2; + + &::before { + content: ""; + position: absolute; + left: 17px; + top: 34px; + bottom: 6px; + width: 2px; + background: var(--text-color-secondary); + border-radius: 10px; + opacity: 0.3; + } + } +} diff --git a/war/src/main/webapp/WEB-INF/web.xml b/war/src/main/webapp/WEB-INF/web.xml index 29e9194decd2..4ef6db9e3fb5 100644 --- a/war/src/main/webapp/WEB-INF/web.xml +++ b/war/src/main/webapp/WEB-INF/web.xml @@ -66,8 +66,8 @@ THE SOFTWARE. true - compression-filter - org.kohsuke.stapler.compression.CompressionFilter + uncaught-exception-filter + org.kohsuke.stapler.UncaughtExceptionFilter true @@ -149,7 +149,7 @@ THE SOFTWARE. /* - compression-filter + uncaught-exception-filter /* diff --git a/war/src/main/webapp/help/system-config/computerRetentionCheckInterval.html b/war/src/main/webapp/help/system-config/computerRetentionCheckInterval.html new file mode 100644 index 000000000000..1c85b796d431 --- /dev/null +++ b/war/src/main/webapp/help/system-config/computerRetentionCheckInterval.html @@ -0,0 +1,13 @@ +
+ Configure the check interval (in seconds) of computer retention strategies. + Retention strategies are configured in the individual agent configuration + under "Availability". Administrators can trade elevated CPU usage from + frequent agent checks for responsiveness to capacity needs. +

+ For example, if you run your build agents on short-lived VMs that boot fast, + you may want to scale up new capacity as soon as builds queue up and scale + VMs down as soon as no more work is available to cut delays for users and + costs of keeping idle VMs alive. Be sure to adjust the delays in the + respective retention strategies accordingly as well. +

+
diff --git a/war/src/main/webapp/scripts/hudson-behavior.js b/war/src/main/webapp/scripts/hudson-behavior.js index 8a207dcefc76..110a09fa199f 100644 --- a/war/src/main/webapp/scripts/hudson-behavior.js +++ b/war/src/main/webapp/scripts/hudson-behavior.js @@ -1661,7 +1661,8 @@ function rowvgStartEachRow(recursive, f) { } } changeTo(e, "-hover.png"); - YAHOO.util.Event.stopEvent(event); + event.stopPropagation(); + event.preventDefault(); return false; }; e = null; // memory leak prevention @@ -1756,15 +1757,6 @@ function rowvgStartEachRow(recursive, f) { }, ); - Behaviour.specify( - ".button-with-dropdown", - "-button-with-dropdown", - ++p, - function (e) { - new YAHOO.widget.Button(e, { type: "menu", menu: e.nextElementSibling }); - }, - ); - window.addEventListener("load", function () { // Add a class to the bottom bar when it's stuck to the bottom of the screen const el = document.querySelector("#bottom-sticker"); @@ -1901,8 +1893,11 @@ function xor(a, b) { // eslint-disable-next-line no-unused-vars function replaceDescription(initialDescription, submissionUrl) { var d = document.getElementById("description"); - d.firstElementChild.nextElementSibling.innerHTML = - "
"; + let button = d.firstElementChild.nextElementSibling; + if (button !== null) { + d.firstElementChild.nextElementSibling.innerHTML = + "
"; + } let parameters = {}; if (initialDescription !== null && initialDescription !== "") { parameters["description"] = initialDescription; @@ -2226,35 +2221,6 @@ function toQueryString(params) { return query; } -// eslint-disable-next-line no-unused-vars -function getElementOverflowParams(element) { - // First we force it to wrap so we can get those dimension. - // Then we force it to "nowrap", so we can get those dimension. - // We can then compare the two sets, which will indicate if - // wrapping is potentially happening, or not. - - // Force it to wrap. - element.classList.add("force-wrap"); - var wrappedClientWidth = element.clientWidth; - var wrappedClientHeight = element.clientHeight; - element.classList.remove("force-wrap"); - - // Force it to nowrap. Return the comparisons. - element.classList.add("force-nowrap"); - var nowrapClientHeight = element.clientHeight; - try { - var overflowParams = { - element: element, - clientWidth: wrappedClientWidth, - scrollWidth: element.scrollWidth, - isOverflowed: wrappedClientHeight > nowrapClientHeight, - }; - return overflowParams; - } finally { - element.classList.remove("force-nowrap"); - } -} - // get the cascaded computed style value. 'a' is the style name like 'backgroundColor' function getStyle(e, a) { if (document.defaultView && document.defaultView.getComputedStyle) { @@ -2276,14 +2242,13 @@ function getStyle(e, a) { */ // eslint-disable-next-line no-unused-vars function ensureVisible(e) { - var viewport = YAHOO.util.Dom.getClientRegion(); - var pos = YAHOO.util.Dom.getRegion(e); - - var Y = viewport.top; - var H = viewport.height; + const scrollTop = document.documentElement.scrollTop; + let Y = scrollTop; + let H = window.innerHeight; + let c = 0; function handleStickers(name, f) { - var e = document.getElementById(name); + const e = document.getElementById(name); if (e) { f(e); } @@ -2295,6 +2260,7 @@ function ensureVisible(e) { t = t.clientHeight; Y += t; H -= t; + c += t; }); handleStickers("bottom-sticker", function (b) { @@ -2302,17 +2268,15 @@ function ensureVisible(e) { H -= b; }); - var y = pos.top; - var h = pos.height; + const box = e.getBoundingClientRect(); + const y = Math.round(box.top + scrollTop); + const h = e.offsetHeight; + const d = y + h - (Y + H); - var d = y + h - (Y + H); - if (d > 0) { - document.body.scrollTop += d; - } else { - d = Y - y; - if (d > 0) { - document.body.scrollTop -= d; - } + if (h > H) { + document.documentElement.scrollTop = y - c; + } else if (d > 0) { + document.documentElement.scrollTop += d; } } diff --git a/war/src/main/webapp/scripts/sortable.js b/war/src/main/webapp/scripts/sortable.js index 7b4b9e8f4da8..b42be9ee945b 100644 --- a/war/src/main/webapp/scripts/sortable.js +++ b/war/src/main/webapp/scripts/sortable.js @@ -133,16 +133,14 @@ var Sortable = (function () { */ getStoredPreference: function () { var key = this.getStorageKey(); - if (storage.hasKey(key)) { - var val = storage.getItem(key); - if (val) { - var vals = val.split(":"); - if (vals.length == 2) { - return { - column: parseInt(vals[0]), - direction: arrowTable[vals[1]], - }; - } + var val = sessionStorage.getItem(key); + if (val) { + var vals = val.split(":"); + if (vals.length == 2) { + return { + column: parseInt(vals[0]), + direction: arrowTable[vals[1]], + }; } } return null; @@ -156,7 +154,13 @@ var Sortable = (function () { savePreference: function () { var key = this.getStorageKey(); - storage.setItem(key, this.pref.column + ":" + this.pref.direction.id); + var value = this.pref.column + ":" + this.pref.direction.id; + try { + sessionStorage.setItem(key, value); + } catch (e) { + // storage could be full + console.warn(e); + } }, /** @@ -442,29 +446,6 @@ var Sortable = (function () { }, }; - var storage; - try { - storage = YAHOO.util.StorageManager.get( - YAHOO.util.StorageEngineHTML5.ENGINE_NAME, - YAHOO.util.StorageManager.LOCATION_SESSION, - { - order: [YAHOO.util.StorageEngineGears], - }, - ); - // eslint-disable-next-line no-unused-vars - } catch (e) { - // no storage available - storage = { - setItem: function () {}, - getItem: function () { - return null; - }, - hasKey: function () { - return false; - }, - }; - } - return { Sortable: Sortable, sorter: sorter, diff --git a/war/src/test/java/executable/MainTest.java b/war/src/test/java/executable/MainTest.java index 676cdd5d2986..106b835ac3e7 100644 --- a/war/src/test/java/executable/MainTest.java +++ b/war/src/test/java/executable/MainTest.java @@ -11,34 +11,28 @@ class MainTest { void unsupported() { assertJavaCheckFails(8, false); assertJavaCheckFails(8, true); + assertJavaCheckFails(11, false); + assertJavaCheckFails(11, true); } @Test void supported() { - assertJavaCheckPasses(11, false); - assertJavaCheckPasses(11, true); assertJavaCheckPasses(17, false); assertJavaCheckPasses(17, true); + assertJavaCheckPasses(21, false); + assertJavaCheckPasses(21, true); } @Test void future() { - assertJavaCheckFails(12, false); - assertJavaCheckFails(13, false); - assertJavaCheckFails(14, false); - assertJavaCheckFails(15, false); - assertJavaCheckFails(16, false); assertJavaCheckFails(18, false); assertJavaCheckFails(19, false); assertJavaCheckFails(20, false); - assertJavaCheckPasses(12, true); - assertJavaCheckPasses(13, true); - assertJavaCheckPasses(14, true); - assertJavaCheckPasses(15, true); - assertJavaCheckPasses(16, true); + assertJavaCheckFails(22, false); assertJavaCheckPasses(18, true); assertJavaCheckPasses(19, true); assertJavaCheckPasses(20, true); + assertJavaCheckPasses(22, true); } private static void assertJavaCheckFails(int releaseVersion, boolean enableFutureJava) { diff --git a/war/webpack.config.js b/war/webpack.config.js index c5e8e17442d1..b9f012095ff4 100644 --- a/war/webpack.config.js +++ b/war/webpack.config.js @@ -50,8 +50,8 @@ module.exports = (env, argv) => ({ "components/row-selection-controller": [ path.join(__dirname, "src/main/js/components/row-selection-controller"), ], - "filter-build-history": [ - path.join(__dirname, "src/main/js/filter-build-history.js"), + "pages/project/builds-card": [ + path.join(__dirname, "src/main/js/pages/project/builds-card.js"), ], "simple-page": [path.join(__dirname, "src/main/scss/simple-page.scss")], styles: [path.join(__dirname, "src/main/scss/styles.scss")], diff --git a/war/yarn.lock b/war/yarn.lock index 8be8c0934732..97b3c957b34e 100644 --- a/war/yarn.lock +++ b/war/yarn.lock @@ -22,14 +22,14 @@ __metadata: languageName: node linkType: hard -"@babel/cli@npm:7.24.5": - version: 7.24.5 - resolution: "@babel/cli@npm:7.24.5" +"@babel/cli@npm:7.24.8": + version: 7.24.8 + resolution: "@babel/cli@npm:7.24.8" dependencies: "@jridgewell/trace-mapping": "npm:^0.3.25" "@nicolo-ribaudo/chokidar-2": "npm:2.1.8-no-fsevents.3" chokidar: "npm:^3.4.0" - commander: "npm:^4.0.1" + commander: "npm:^6.2.0" convert-source-map: "npm:^2.0.0" fs-readdir-recursive: "npm:^1.1.0" glob: "npm:^7.2.0" @@ -45,122 +45,123 @@ __metadata: bin: babel: ./bin/babel.js babel-external-helpers: ./bin/babel-external-helpers.js - checksum: 10c0/ec1c0546986b1b2423a125f919701b1c29ea1e999302035379adbfb9104e819d9cecc9d947ac91a26a9da7e6445f1812fc61deabf9d0a5f3894f53ec19fdfa04 + checksum: 10c0/b7f464ccb00db60aed63d71e980df823900d20c740bc2d9eb36c3abd4b3e2402cc438818382344085ef6603aeea2e6ee19af8f0ecb934966eccf077b87af7c7c languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.23.5, @babel/code-frame@npm:^7.24.2": - version: 7.24.2 - resolution: "@babel/code-frame@npm:7.24.2" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/code-frame@npm:7.24.7" dependencies: - "@babel/highlight": "npm:^7.24.2" + "@babel/highlight": "npm:^7.24.7" picocolors: "npm:^1.0.0" - checksum: 10c0/d1d4cba89475ab6aab7a88242e1fd73b15ecb9f30c109b69752956434d10a26a52cbd37727c4eca104b6d45227bd1dfce39a6a6f4a14c9b2f07f871e968cf406 + checksum: 10c0/ab0af539473a9f5aeaac7047e377cb4f4edd255a81d84a76058595f8540784cc3fbe8acf73f1e073981104562490aabfb23008cd66dc677a456a4ed5390fdde6 languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.23.5, @babel/compat-data@npm:^7.24.4": - version: 7.24.4 - resolution: "@babel/compat-data@npm:7.24.4" - checksum: 10c0/9cd8a9cd28a5ca6db5d0e27417d609f95a8762b655e8c9c97fd2de08997043ae99f0139007083c5e607601c6122e8432c85fe391731b19bf26ad458fa0c60dd3 +"@babel/compat-data@npm:^7.22.6, @babel/compat-data@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/compat-data@npm:7.24.8" + checksum: 10c0/7f465e9d8e44c5b516eeb3001362a3cd9a6df51dd90d3ac9868e1e7fa631ac57fc781cec6700110d4f555ba37fe59c4a71927b445106fe0062e79e79ffe11091 languageName: node linkType: hard -"@babel/core@npm:7.24.5": - version: 7.24.5 - resolution: "@babel/core@npm:7.24.5" +"@babel/core@npm:7.24.9": + version: 7.24.9 + resolution: "@babel/core@npm:7.24.9" dependencies: "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.24.2" - "@babel/generator": "npm:^7.24.5" - "@babel/helper-compilation-targets": "npm:^7.23.6" - "@babel/helper-module-transforms": "npm:^7.24.5" - "@babel/helpers": "npm:^7.24.5" - "@babel/parser": "npm:^7.24.5" - "@babel/template": "npm:^7.24.0" - "@babel/traverse": "npm:^7.24.5" - "@babel/types": "npm:^7.24.5" + "@babel/code-frame": "npm:^7.24.7" + "@babel/generator": "npm:^7.24.9" + "@babel/helper-compilation-targets": "npm:^7.24.8" + "@babel/helper-module-transforms": "npm:^7.24.9" + "@babel/helpers": "npm:^7.24.8" + "@babel/parser": "npm:^7.24.8" + "@babel/template": "npm:^7.24.7" + "@babel/traverse": "npm:^7.24.8" + "@babel/types": "npm:^7.24.9" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10c0/e26ba810a77bc8e21579a12fc36c79a0a60554404dc9447f2d64eb1f26d181c48d3b97d39d9f158e9911ec7162a8280acfaf2b4b210e975f0dd4bd4dbb1ee159 + checksum: 10c0/e104ec6efbf099f55184933e9ab078eb5821c792ddfef3e9c6561986ec4ff103f5c11e3d7d6e5e8929e50e2c58db1cc80e5b6f14b530335b6622095ec4b4124c languageName: node linkType: hard -"@babel/generator@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/generator@npm:7.24.5" +"@babel/generator@npm:^7.24.8, @babel/generator@npm:^7.24.9": + version: 7.24.10 + resolution: "@babel/generator@npm:7.24.10" dependencies: - "@babel/types": "npm:^7.24.5" + "@babel/types": "npm:^7.24.9" "@jridgewell/gen-mapping": "npm:^0.3.5" "@jridgewell/trace-mapping": "npm:^0.3.25" jsesc: "npm:^2.5.1" - checksum: 10c0/0d64f880150e7dfb92ceff2b4ac865f36aa1e295120920246492ffd0146562dabf79ba8699af1c8833f8a7954818d4d146b7b02f808df4d6024fb99f98b2f78d + checksum: 10c0/abcfd75f625aecc87ce6036ef788b12723fd3c46530df1130d1f00d18e48b462849ddaeef8b1a02bfdcb6e28956389a98c5729dad1c3c5448307dacb6c959f29 languageName: node linkType: hard -"@babel/helper-annotate-as-pure@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" +"@babel/helper-annotate-as-pure@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-annotate-as-pure@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 10c0/5a80dc364ddda26b334bbbc0f6426cab647381555ef7d0cd32eb284e35b867c012ce6ce7d52a64672ed71383099c99d32765b3d260626527bb0e3470b0f58e45 + "@babel/types": "npm:^7.24.7" + checksum: 10c0/4679f7df4dffd5b3e26083ae65228116c3da34c3fff2c11ae11b259a61baec440f51e30fd236f7a0435b9d471acd93d0bc5a95df8213cbf02b1e083503d81b9a languageName: node linkType: hard -"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.22.15" +"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.22.15" - checksum: 10c0/2535e3824ca6337f65786bbac98e562f71699f25532cecd196f027d7698b4967a96953d64e36567956658ad1a05ccbdc62d1ba79ee751c79f4f1d2d3ecc2e01c + "@babel/traverse": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 10c0/0ed84abf848c79fb1cd4c1ddac12c771d32c1904d87fc3087f33cfdeb0c2e0db4e7892b74b407d9d8d0c000044f3645a7391a781f788da8410c290bb123a1f13 languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.23.6": - version: 7.23.6 - resolution: "@babel/helper-compilation-targets@npm:7.23.6" +"@babel/helper-compilation-targets@npm:^7.22.6, @babel/helper-compilation-targets@npm:^7.24.7, @babel/helper-compilation-targets@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-compilation-targets@npm:7.24.8" dependencies: - "@babel/compat-data": "npm:^7.23.5" - "@babel/helper-validator-option": "npm:^7.23.5" - browserslist: "npm:^4.22.2" + "@babel/compat-data": "npm:^7.24.8" + "@babel/helper-validator-option": "npm:^7.24.8" + browserslist: "npm:^4.23.1" lru-cache: "npm:^5.1.1" semver: "npm:^6.3.1" - checksum: 10c0/ba38506d11185f48b79abf439462ece271d3eead1673dd8814519c8c903c708523428806f05f2ec5efd0c56e4e278698fac967e5a4b5ee842c32415da54bc6fa + checksum: 10c0/2885c44ef6aaf82b7e4352b30089bb09fbe08ed5ec24eb452c2bdc3c021e2a65ab412f74b3d67ec1398da0356c730b33a2ceca1d67d34c85080d31ca6efa9aec languageName: node linkType: hard -"@babel/helper-create-class-features-plugin@npm:^7.24.1, @babel/helper-create-class-features-plugin@npm:^7.24.4, @babel/helper-create-class-features-plugin@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/helper-create-class-features-plugin@npm:7.24.5" +"@babel/helper-create-class-features-plugin@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-create-class-features-plugin@npm:7.24.7" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-member-expression-to-functions": "npm:^7.24.5" - "@babel/helper-optimise-call-expression": "npm:^7.22.5" - "@babel/helper-replace-supers": "npm:^7.24.1" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.24.5" + "@babel/helper-annotate-as-pure": "npm:^7.24.7" + "@babel/helper-environment-visitor": "npm:^7.24.7" + "@babel/helper-function-name": "npm:^7.24.7" + "@babel/helper-member-expression-to-functions": "npm:^7.24.7" + "@babel/helper-optimise-call-expression": "npm:^7.24.7" + "@babel/helper-replace-supers": "npm:^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" + "@babel/helper-split-export-declaration": "npm:^7.24.7" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/afc72e8075a249663f8024ef1760de4c0b9252bdde16419ac955fa7e15b8d4096ca1e01f796df4fa8cfdb056708886f60b631ad492242a8e47307974fc305920 + checksum: 10c0/6b7b47d70b41c00f39f86790cff67acf2bce0289d52a7c182b28e797f4e0e6d69027e3d06eccf1d54dddc2e5dde1df663bb1932437e5f447aeb8635d8d64a6ab languageName: node linkType: hard -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.22.15, @babel/helper-create-regexp-features-plugin@npm:^7.22.5": - version: 7.22.15 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.22.15" +"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-create-regexp-features-plugin@npm:7.24.7" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-annotate-as-pure": "npm:^7.24.7" regexpu-core: "npm:^5.3.1" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/8eba4c1b7b94a83e7a82df5c3e504584ff0ba6ab8710a67ecc2c434a7fb841a29c2f5c94d2de51f25446119a1df538fa90b37bd570db22ddd5e7147fe98277c6 + checksum: 10c0/ed611a7eb0c71843f9cdc471eeb38767972229f9225f7aaa90d124d7ee0062cf6908fd53ee9c34f731394c429594f06049a7738a71d342e0191d4047b2fc0ac2 languageName: node linkType: hard @@ -179,243 +180,249 @@ __metadata: languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-environment-visitor@npm:7.22.20" - checksum: 10c0/e762c2d8f5d423af89bd7ae9abe35bd4836d2eb401af868a63bbb63220c513c783e25ef001019418560b3fdc6d9a6fb67e6c0b650bcdeb3a2ac44b5c3d2bdd94 +"@babel/helper-environment-visitor@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-environment-visitor@npm:7.24.7" + dependencies: + "@babel/types": "npm:^7.24.7" + checksum: 10c0/36ece78882b5960e2d26abf13cf15ff5689bf7c325b10a2895a74a499e712de0d305f8d78bb382dd3c05cfba7e47ec98fe28aab5674243e0625cd38438dd0b2d languageName: node linkType: hard -"@babel/helper-function-name@npm:^7.22.5, @babel/helper-function-name@npm:^7.23.0": - version: 7.23.0 - resolution: "@babel/helper-function-name@npm:7.23.0" +"@babel/helper-function-name@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-function-name@npm:7.24.7" dependencies: - "@babel/template": "npm:^7.22.15" - "@babel/types": "npm:^7.23.0" - checksum: 10c0/d771dd1f3222b120518176733c52b7cadac1c256ff49b1889dbbe5e3fed81db855b8cc4e40d949c9d3eae0e795e8229c1c8c24c0e83f27cfa6ee3766696c6428 + "@babel/template": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 10c0/e5e41e6cf86bd0f8bf272cbb6e7c5ee0f3e9660414174435a46653efba4f2479ce03ce04abff2aa2ef9359cf057c79c06cb7b134a565ad9c0e8a50dcdc3b43c4 languageName: node linkType: hard -"@babel/helper-hoist-variables@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-hoist-variables@npm:7.22.5" +"@babel/helper-hoist-variables@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-hoist-variables@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 10c0/60a3077f756a1cd9f14eb89f0037f487d81ede2b7cfe652ea6869cd4ec4c782b0fb1de01b8494b9a2d2050e3d154d7d5ad3be24806790acfb8cbe2073bf1e208 + "@babel/types": "npm:^7.24.7" + checksum: 10c0/19ee37563bbd1219f9d98991ad0e9abef77803ee5945fd85aa7aa62a67c69efca9a801696a1b58dda27f211e878b3327789e6fd2a6f6c725ccefe36774b5ce95 languageName: node linkType: hard -"@babel/helper-member-expression-to-functions@npm:^7.23.0, @babel/helper-member-expression-to-functions@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/helper-member-expression-to-functions@npm:7.24.5" +"@babel/helper-member-expression-to-functions@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-member-expression-to-functions@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.24.5" - checksum: 10c0/a3c0276a1ede8648a0e6fd86ad846cd57421d05eddfa29446b8b5a013db650462022b9ec1e65ea32c747d0542d729c80866830697f94fb12d603e87c51f080a5 + "@babel/traverse": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 10c0/9638c1d33cf6aba028461ccd3db6061c76ff863ca0d5013dd9a088bf841f2f77c46956493f9da18355c16759449d23b74cc1de4da357ade5c5c34c858f840f0a languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.24.1, @babel/helper-module-imports@npm:^7.24.3": - version: 7.24.3 - resolution: "@babel/helper-module-imports@npm:7.24.3" +"@babel/helper-module-imports@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-module-imports@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.24.0" - checksum: 10c0/052c188adcd100f5e8b6ff0c9643ddaabc58b6700d3bbbc26804141ad68375a9f97d9d173658d373d31853019e65f62610239e3295cdd58e573bdcb2fded188d + "@babel/traverse": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 10c0/97c57db6c3eeaea31564286e328a9fb52b0313c5cfcc7eee4bc226aebcf0418ea5b6fe78673c0e4a774512ec6c86e309d0f326e99d2b37bfc16a25a032498af0 languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.23.3, @babel/helper-module-transforms@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/helper-module-transforms@npm:7.24.5" +"@babel/helper-module-transforms@npm:^7.24.7, @babel/helper-module-transforms@npm:^7.24.8, @babel/helper-module-transforms@npm:^7.24.9": + version: 7.24.9 + resolution: "@babel/helper-module-transforms@npm:7.24.9" dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-module-imports": "npm:^7.24.3" - "@babel/helper-simple-access": "npm:^7.24.5" - "@babel/helper-split-export-declaration": "npm:^7.24.5" - "@babel/helper-validator-identifier": "npm:^7.24.5" + "@babel/helper-environment-visitor": "npm:^7.24.7" + "@babel/helper-module-imports": "npm:^7.24.7" + "@babel/helper-simple-access": "npm:^7.24.7" + "@babel/helper-split-export-declaration": "npm:^7.24.7" + "@babel/helper-validator-identifier": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/6e77d72f62b7e87abaea800ea0bccd4d54cde26485750969f5f493c032eb63251eb50c3522cace557781565d51c1d0c4bcc866407d24becfb109c18fb92c978d + checksum: 10c0/e27bca43bc113731ee4f2b33a4c5bf9c7eebf4d64487b814c305cbd5feb272c29fcd3d79634ba03131ade171e5972bc7ede8dbc83ba0deb02f1e62d318c87770 languageName: node linkType: hard -"@babel/helper-optimise-call-expression@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" +"@babel/helper-optimise-call-expression@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-optimise-call-expression@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 10c0/31b41a764fc3c585196cf5b776b70cf4705c132e4ce9723f39871f215f2ddbfb2e28a62f9917610f67c8216c1080482b9b05f65dd195dae2a52cef461f2ac7b8 + "@babel/types": "npm:^7.24.7" + checksum: 10c0/ca6a9884705dea5c95a8b3ce132d1e3f2ae951ff74987d400d1d9c215dae9c0f9e29924d8f8e131e116533d182675bc261927be72f6a9a2968eaeeaa51eb1d0f languageName: node linkType: hard -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.0, @babel/helper-plugin-utils@npm:^7.24.5, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": - version: 7.24.5 - resolution: "@babel/helper-plugin-utils@npm:7.24.5" - checksum: 10c0/4ae40094e6a2f183281213344f4df60c66b16b19a2bc38d2bb11810a6dc0a0e7ec638957d0e433ff8b615775b8f3cd1b7edbf59440d1b50e73c389fc22913377 +"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.10.4, @babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.14.5, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.24.7, @babel/helper-plugin-utils@npm:^7.24.8, @babel/helper-plugin-utils@npm:^7.8.0, @babel/helper-plugin-utils@npm:^7.8.3": + version: 7.24.8 + resolution: "@babel/helper-plugin-utils@npm:7.24.8" + checksum: 10c0/0376037f94a3bfe6b820a39f81220ac04f243eaee7193774b983e956c1750883ff236b30785795abbcda43fac3ece74750566830c2daa4d6e3870bb0dff34c2d languageName: node linkType: hard -"@babel/helper-remap-async-to-generator@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-remap-async-to-generator@npm:7.22.20" +"@babel/helper-remap-async-to-generator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-remap-async-to-generator@npm:7.24.7" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-wrap-function": "npm:^7.22.20" + "@babel/helper-annotate-as-pure": "npm:^7.24.7" + "@babel/helper-environment-visitor": "npm:^7.24.7" + "@babel/helper-wrap-function": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/aa93aa74250b636d477e8d863fbe59d4071f8c2654841b7ac608909e480c1cf3ff7d7af5a4038568829ad09d810bb681668cbe497d9c89ba5c352793dc9edf1e + checksum: 10c0/4e7fa2cdcbc488e41c27066c16e562857ef3c5c2bfe70d2f1e32e9ee7546b17c3fc1c20d05bf2a7f1c291bd9e7a0a219f6a9fa387209013294be79a26fcfe64d languageName: node linkType: hard -"@babel/helper-replace-supers@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/helper-replace-supers@npm:7.24.1" +"@babel/helper-replace-supers@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-replace-supers@npm:7.24.7" dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-member-expression-to-functions": "npm:^7.23.0" - "@babel/helper-optimise-call-expression": "npm:^7.22.5" + "@babel/helper-environment-visitor": "npm:^7.24.7" + "@babel/helper-member-expression-to-functions": "npm:^7.24.7" + "@babel/helper-optimise-call-expression": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/d39a3df7892b7c3c0e307fb229646168a9bd35e26a72080c2530729322600e8cff5f738f44a14860a2358faffa741b6a6a0d6749f113387b03ddbfa0ec10e1a0 + checksum: 10c0/0e133bb03371dee78e519c334a09c08e1493103a239d9628db0132dfaac3fc16380479ca3c590d278a9b71b624030a338c18ebbfe6d430ebb2e4653775c4b3e3 languageName: node linkType: hard -"@babel/helper-simple-access@npm:^7.22.5, @babel/helper-simple-access@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/helper-simple-access@npm:7.24.5" +"@babel/helper-simple-access@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-simple-access@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.24.5" - checksum: 10c0/d96a0ab790a400f6c2dcbd9457b9ca74b9ba6d0f67ff9cd5bcc73792c8fbbd0847322a0dddbd8987dd98610ee1637c680938c7d83d3ffce7d06d7519d823d996 + "@babel/traverse": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 10c0/7230e419d59a85f93153415100a5faff23c133d7442c19e0cd070da1784d13cd29096ee6c5a5761065c44e8164f9f80e3a518c41a0256df39e38f7ad6744fed7 languageName: node linkType: hard -"@babel/helper-skip-transparent-expression-wrappers@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.22.5" +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 10c0/ab7fa2aa709ab49bb8cd86515a1e715a3108c4bb9a616965ba76b43dc346dee66d1004ccf4d222b596b6224e43e04cbc5c3a34459501b388451f8c589fbc3691 + "@babel/traverse": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 10c0/e3a9b8ac9c262ac976a1bcb5fe59694db5e6f0b4f9e7bdba5c7693b8b5e28113c23bdaa60fe8d3ec32a337091b67720b2053bcb3d5655f5406536c3d0584242b languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/helper-split-export-declaration@npm:7.24.5" +"@babel/helper-split-export-declaration@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-split-export-declaration@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.24.5" - checksum: 10c0/d7a812d67d031a348f3fb0e6263ce2dbe6038f81536ba7fb16db385383bcd6542b71833194303bf6d3d0e4f7b6b584c9c8fae8772122e2ce68fc9bdf07f4135d + "@babel/types": "npm:^7.24.7" + checksum: 10c0/0254577d7086bf09b01bbde98f731d4fcf4b7c3fa9634fdb87929801307c1f6202a1352e3faa5492450fa8da4420542d44de604daf540704ff349594a78184f6 languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/helper-string-parser@npm:7.24.1" - checksum: 10c0/2f9bfcf8d2f9f083785df0501dbab92770111ece2f90d120352fda6dd2a7d47db11b807d111e6f32aa1ba6d763fe2dc6603d153068d672a5d0ad33ca802632b2 +"@babel/helper-string-parser@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-string-parser@npm:7.24.8" + checksum: 10c0/6361f72076c17fabf305e252bf6d580106429014b3ab3c1f5c4eb3e6d465536ea6b670cc0e9a637a77a9ad40454d3e41361a2909e70e305116a23d68ce094c08 languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.20, @babel/helper-validator-identifier@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/helper-validator-identifier@npm:7.24.5" - checksum: 10c0/05f957229d89ce95a137d04e27f7d0680d84ae48b6ad830e399db0779341f7d30290f863a93351b4b3bde2166737f73a286ea42856bb07c8ddaa95600d38645c +"@babel/helper-validator-identifier@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-validator-identifier@npm:7.24.7" + checksum: 10c0/87ad608694c9477814093ed5b5c080c2e06d44cb1924ae8320474a74415241223cc2a725eea2640dd783ff1e3390e5f95eede978bc540e870053152e58f1d651 languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.23.5": - version: 7.23.5 - resolution: "@babel/helper-validator-option@npm:7.23.5" - checksum: 10c0/af45d5c0defb292ba6fd38979e8f13d7da63f9623d8ab9ededc394f67eb45857d2601278d151ae9affb6e03d5d608485806cd45af08b4468a0515cf506510e94 +"@babel/helper-validator-option@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-validator-option@npm:7.24.8" + checksum: 10c0/73db93a34ae89201351288bee7623eed81a54000779462a986105b54ffe82069e764afd15171a428b82e7c7a9b5fec10b5d5603b216317a414062edf5c67a21f languageName: node linkType: hard -"@babel/helper-wrap-function@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-wrap-function@npm:7.22.20" +"@babel/helper-wrap-function@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-wrap-function@npm:7.24.7" dependencies: - "@babel/helper-function-name": "npm:^7.22.5" - "@babel/template": "npm:^7.22.15" - "@babel/types": "npm:^7.22.19" - checksum: 10c0/97b5f42ff4d305318ff2f99a5f59d3e97feff478333b2d893c4f85456d3c66372070f71d7bf9141f598c8cf2741c49a15918193633c427a88d170d98eb8c46eb + "@babel/helper-function-name": "npm:^7.24.7" + "@babel/template": "npm:^7.24.7" + "@babel/traverse": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 10c0/d5689f031bf0eb38c0d7fad6b7e320ddef4bfbdf08d12d7d76ef41b7ca365a32721e74cb5ed5a9a9ec634bc20f9b7a27314fa6fb08f1576b8f6d8330fcea6f47 languageName: node linkType: hard -"@babel/helpers@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/helpers@npm:7.24.5" +"@babel/helpers@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helpers@npm:7.24.8" dependencies: - "@babel/template": "npm:^7.24.0" - "@babel/traverse": "npm:^7.24.5" - "@babel/types": "npm:^7.24.5" - checksum: 10c0/0630b0223c3a9a34027ddc05b3bac54d68d5957f84e92d2d4814b00448a76e12f9188f9c85cfce2011696d82a8ffcbd8189da097c0af0181d32eb27eca34185e + "@babel/template": "npm:^7.24.7" + "@babel/types": "npm:^7.24.8" + checksum: 10c0/42b8939b0a0bf72d6df9721973eb0fd7cd48f42641c5c9c740916397faa586255c06d36c6e6a7e091860723096281c620f6ffaee0011a3bb254a6f5475d89a12 languageName: node linkType: hard -"@babel/highlight@npm:^7.24.2": - version: 7.24.2 - resolution: "@babel/highlight@npm:7.24.2" +"@babel/highlight@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/highlight@npm:7.24.7" dependencies: - "@babel/helper-validator-identifier": "npm:^7.22.20" + "@babel/helper-validator-identifier": "npm:^7.24.7" chalk: "npm:^2.4.2" js-tokens: "npm:^4.0.0" picocolors: "npm:^1.0.0" - checksum: 10c0/98ce00321daedeed33a4ed9362dc089a70375ff1b3b91228b9f05e6591d387a81a8cba68886e207861b8871efa0bc997ceabdd9c90f6cce3ee1b2f7f941b42db + checksum: 10c0/674334c571d2bb9d1c89bdd87566383f59231e16bcdcf5bb7835babdf03c9ae585ca0887a7b25bdf78f303984af028df52831c7989fecebb5101cc132da9393a languageName: node linkType: hard -"@babel/parser@npm:^7.24.0, @babel/parser@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/parser@npm:7.24.5" +"@babel/parser@npm:^7.24.7, @babel/parser@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/parser@npm:7.24.8" bin: parser: ./bin/babel-parser.js - checksum: 10c0/8333a6ad5328bad34fa0e12bcee147c3345ea9a438c0909e7c68c6cfbea43c464834ffd7eabd1cbc1c62df0a558e22ffade9f5b29440833ba7b33d96a71f88c0 + checksum: 10c0/ce69671de8fa6f649abf849be262707ac700b573b8b1ce1893c66cc6cd76aeb1294a19e8c290b0eadeb2f47d3f413a2e57a281804ffbe76bfb9fa50194cf3c52 languageName: node linkType: hard -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.24.5" +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.24.7" dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-plugin-utils": "npm:^7.24.5" + "@babel/helper-environment-visitor": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/b471972dcc4a3ba32821329a57725e2b563421e975d7ffec7fcabd70af0fced6a50bcc9ed2a8cbd4a9ac7c09cfbf43c7116e82f3b9064b33a22309500b632108 + checksum: 10c0/394c30e2b708ad385fa1219528e039066a1f1cb40f47986f283878848fd354c745e6397f588b4e5a046ee8d64bfdf4c208e4c3dfbdcfb2fd34315ec67c64e7af languageName: node linkType: hard -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.24.1" +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/d4e592e6fc4878654243d2e7b51ea86471b868a8cb09de29e73b65d2b64159990c6c198fd7c9c2af2e38b1cddf70206243792853c47384a84f829dada152f605 + checksum: 10c0/a36307428ecc1a01b00cf90812335eed1575d13f211ab24fe4d0c55c28a2fcbd4135f142efabc3b277b2a8e09ee05df594a1272353f061b63829495b5dcfdb96 languageName: node linkType: hard -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.24.1" +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" - "@babel/plugin-transform-optional-chaining": "npm:^7.24.1" + "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" + "@babel/plugin-transform-optional-chaining": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.13.0 - checksum: 10c0/351c36e45795a7890d610ab9041a52f4078a59429f6e74c281984aa44149a10d43e82b3a8172c703c0d5679471e165d1c02b6d2e45a677958ee301b89403f202 + checksum: 10c0/aeb6e7aa363a47f815cf956ea1053c5dd8b786a17799f065c9688ba4b0051fe7565d258bbe9400bfcbfb3114cb9fda66983e10afe4d750bc70ff75403e15dd36 languageName: node linkType: hard -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.24.1" +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.24.7" dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-environment-visitor": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/d7dd5a59a54635a3152895dcaa68f3370bb09d1f9906c1e72232ff759159e6be48de4a598a993c986997280a2dc29922a48aaa98020f16439f3f57ad72788354 + checksum: 10c0/2b52a73e444f6adc73f927b623e53a4cf64397170dd1071268536df1b3db1e02131418c8dc91351af48837a6298212118f4a72d5407f8005cf9a732370a315b0 languageName: node linkType: hard @@ -483,25 +490,25 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-syntax-import-assertions@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-syntax-import-assertions@npm:7.24.1" +"@babel/plugin-syntax-import-assertions@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/72f0340d73e037f0702c61670054e0af66ece7282c5c2f4ba8de059390fee502de282defdf15959cd9f71aa18dc5c5e4e7a0fde317799a0600c6c4e0a656d82b + checksum: 10c0/b82c53e095274ee71c248551352d73441cf65b3b3fc0107258ba4e9aef7090772a425442b3ed1c396fa207d0efafde8929c87a17d3c885b3ca2021316e87e246 languageName: node linkType: hard -"@babel/plugin-syntax-import-attributes@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-syntax-import-attributes@npm:7.24.1" +"@babel/plugin-syntax-import-attributes@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-syntax-import-attributes@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/309634e3335777aee902552b2cf244c4a8050213cc878b3fb9d70ad8cbbff325dc46ac5e5791836ff477ea373b27832238205f6ceaff81f7ea7c4c7e8fbb13bb + checksum: 10c0/eccc54d0f03c96d0eec7a6e2fa124dadbc7298345b62ffc4238f173308c4325b5598f139695ff05a95cf78412ef6903599e4b814496612bf39aad4715a16375b languageName: node linkType: hard @@ -627,605 +634,605 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-arrow-functions@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-arrow-functions@npm:7.24.1" +"@babel/plugin-transform-arrow-functions@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/f44bfacf087dc21b422bab99f4e9344ee7b695b05c947dacae66de05c723ab9d91800be7edc1fa016185e8c819f3aca2b4a5f66d8a4d1e47d9bad80b8fa55b8e + checksum: 10c0/6ac05a54e5582f34ac6d5dc26499e227227ec1c7fa6fc8de1f3d40c275f140d3907f79bbbd49304da2d7008a5ecafb219d0b71d78ee3290ca22020d878041245 languageName: node linkType: hard -"@babel/plugin-transform-async-generator-functions@npm:^7.24.3": - version: 7.24.3 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.24.3" +"@babel/plugin-transform-async-generator-functions@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-async-generator-functions@npm:7.24.7" dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-plugin-utils": "npm:^7.24.0" - "@babel/helper-remap-async-to-generator": "npm:^7.22.20" + "@babel/helper-environment-visitor": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-remap-async-to-generator": "npm:^7.24.7" "@babel/plugin-syntax-async-generators": "npm:^7.8.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/55ceed059f819dcccbfe69600bfa1c055ada466bd54eda117cfdd2cf773dd85799e2f6556e4a559b076e93b9704abcca2aef9d72aad7dc8a5d3d17886052f1d3 + checksum: 10c0/6b5e33ae66dce0afce9b06d8dace6fa052528e60f7622aa6cfd3e71bd372ca5079d426e78336ca564bc0d5f37acbcda1b21f4fe656fcb642f1a93a697ab39742 languageName: node linkType: hard -"@babel/plugin-transform-async-to-generator@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-async-to-generator@npm:7.24.1" +"@babel/plugin-transform-async-to-generator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-async-to-generator@npm:7.24.7" dependencies: - "@babel/helper-module-imports": "npm:^7.24.1" - "@babel/helper-plugin-utils": "npm:^7.24.0" - "@babel/helper-remap-async-to-generator": "npm:^7.22.20" + "@babel/helper-module-imports": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-remap-async-to-generator": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/3731ba8e83cbea1ab22905031f25b3aeb0b97c6467360a2cc685352f16e7c786417d8883bc747f5a0beff32266bdb12a05b6292e7b8b75967087200a7bc012c4 + checksum: 10c0/83c82e243898875af8457972a26ab29baf8a2078768ee9f35141eb3edff0f84b165582a2ff73e90a9e08f5922bf813dbf15a85c1213654385198f4591c0dc45d languageName: node linkType: hard -"@babel/plugin-transform-block-scoped-functions@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.24.1" +"@babel/plugin-transform-block-scoped-functions@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/6fbaa85f5204f34845dfc0bebf62fdd3ac5a286241c85651e59d426001e7a1785ac501f154e093e0b8ee49e1f51e3f8b06575a5ae8d4a9406d43e4816bf18c37 + checksum: 10c0/113e86de4612ae91773ff5cb6b980f01e1da7e26ae6f6012127415d7ae144e74987bc23feb97f63ba4bc699331490ddea36eac004d76a20d5369e4cc6a7f61cd languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/plugin-transform-block-scoping@npm:7.24.5" +"@babel/plugin-transform-block-scoping@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-block-scoping@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.5" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/85997fc8179b7d26e8af30865aeb91789f3bc1f0cd5643ed25f25891ff9c071460ec1220599b19070b424a3b902422f682e9b02e515872540173eae2e25f760c + checksum: 10c0/dcbc5e385c0ca5fb5736b1c720c90755cffe9f91d8c854f82e61e59217dd3f6c91b3633eeee4b55a89d3f59e5275d0f5b0b1b1363d4fa70c49c468b55aa87700 languageName: node linkType: hard -"@babel/plugin-transform-class-properties@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-class-properties@npm:7.24.1" +"@babel/plugin-transform-class-properties@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-class-properties@npm:7.24.7" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.24.1" - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-create-class-features-plugin": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/00dff042ac9df4ae67b5ef98b1137cc72e0a24e6d911dc200540a8cb1f00b4cff367a922aeb22da17da662079f0abcd46ee1c5f4cdf37ceebf6ff1639bb9af27 + checksum: 10c0/75018a466c7ede3d2397e158891c224ba7fca72864506ce067ddbc02fc65191d44da4d6379c996d0c7f09019e26b5c3f5f1d3a639cd98366519723886f0689d0 languageName: node linkType: hard -"@babel/plugin-transform-class-static-block@npm:^7.24.4": - version: 7.24.4 - resolution: "@babel/plugin-transform-class-static-block@npm:7.24.4" +"@babel/plugin-transform-class-static-block@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-class-static-block@npm:7.24.7" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.24.4" - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-create-class-features-plugin": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" peerDependencies: "@babel/core": ^7.12.0 - checksum: 10c0/19dfeaf4a2ac03695034f7211a8b5ad89103b224608ac3e91791055107c5fe4d7ebe5d9fbb31b4a91265694af78762260642eb270f4b239c175984ee4b253f80 + checksum: 10c0/b0ade39a3d09dce886f79dbd5907c3d99b48167eddb6b9bbde24a0598129654d7017e611c20494cdbea48b07ac14397cd97ea34e3754bbb2abae4e698128eccb languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/plugin-transform-classes@npm:7.24.5" +"@babel/plugin-transform-classes@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-classes@npm:7.24.8" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-compilation-targets": "npm:^7.23.6" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-plugin-utils": "npm:^7.24.5" - "@babel/helper-replace-supers": "npm:^7.24.1" - "@babel/helper-split-export-declaration": "npm:^7.24.5" + "@babel/helper-annotate-as-pure": "npm:^7.24.7" + "@babel/helper-compilation-targets": "npm:^7.24.8" + "@babel/helper-environment-visitor": "npm:^7.24.7" + "@babel/helper-function-name": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-replace-supers": "npm:^7.24.7" + "@babel/helper-split-export-declaration": "npm:^7.24.7" globals: "npm:^11.1.0" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/4affcbb7cb01fa4764c7a4b534c30fd24a4b68e680a2d6e242dd7ca8726490f0f1426c44797deff84a38a162e0629718900c68d28daffe2b12adf5b4194156a7 + checksum: 10c0/4423da0f747bdb6aab1995d98a74533fa679f637ec20706810dd57fb4ba2b1885ec8cae6a0b2c3f69f27165de6ff6aa2da9c4061c893848736a8267d0c653079 languageName: node linkType: hard -"@babel/plugin-transform-computed-properties@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-computed-properties@npm:7.24.1" +"@babel/plugin-transform-computed-properties@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-computed-properties@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" - "@babel/template": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/template": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/8292c508b656b7722e2c2ca0f6f31339852e3ed2b9b80f6e068a4010e961b431ca109ecd467fc906283f4b1574c1e7b1cb68d35a4dea12079d386c15ff7e0eac + checksum: 10c0/25636dbc1f605c0b8bc60aa58628a916b689473d11551c9864a855142e36742fe62d4a70400ba3b74902338e77fb3d940376c0a0ba154b6b7ec5367175233b49 languageName: node linkType: hard -"@babel/plugin-transform-destructuring@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/plugin-transform-destructuring@npm:7.24.5" +"@babel/plugin-transform-destructuring@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-destructuring@npm:7.24.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.5" + "@babel/helper-plugin-utils": "npm:^7.24.8" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/6a37953a95f04b335bf3e2118fb93f50dd9593c658d1b2f8918a380a2ee30f1b420139eccf7ec3873c86a8208527895fcf6b7e21c0e734a6ad6e5d5042eace4d + checksum: 10c0/804968c1d5f5072c717505296c1e5d5ec33e90550423de66de82bbcb78157156e8470bbe77a04ab8c710a88a06360a30103cf223ac7eff4829adedd6150de5ce languageName: node linkType: hard -"@babel/plugin-transform-dotall-regex@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-dotall-regex@npm:7.24.1" +"@babel/plugin-transform-dotall-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-dotall-regex@npm:7.24.7" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.22.15" - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-create-regexp-features-plugin": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/758def705ec5a87ef910280dc2df5d2fda59dc5d4771c1725c7aed0988ae5b79e29aeb48109120301a3e1c6c03dfac84700469de06f38ca92c96834e09eadf5d + checksum: 10c0/793f14c9494972d294b7e7b97b747f47874b6d57d7804d3443c701becf5db192c9311be6a1835c07664486df1f5c60d33196c36fb7e11a53015e476b4c145b33 languageName: node linkType: hard -"@babel/plugin-transform-duplicate-keys@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-duplicate-keys@npm:7.24.1" +"@babel/plugin-transform-duplicate-keys@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-duplicate-keys@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/41072f57f83a6c2b15f3ee0b6779cdca105ff3d98061efe92ac02d6c7b90fdb6e7e293b8a4d5b9c690d9ae5d3ae73e6bde4596dc4d8c66526a0e5e1abc73c88c + checksum: 10c0/75ff7ec1117ac500e77bf20a144411d39c0fdd038f108eec061724123ce6d1bb8d5bd27968e466573ee70014f8be0043361cdb0ef388f8a182d1d97ad67e51b9 languageName: node linkType: hard -"@babel/plugin-transform-dynamic-import@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-dynamic-import@npm:7.24.1" +"@babel/plugin-transform-dynamic-import@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-dynamic-import@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" "@babel/plugin-syntax-dynamic-import": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/7e2834780e9b5251ef341854043a89c91473b83c335358620ca721554877e64e416aeb3288a35f03e825c4958e07d5d00ead08c4490fadc276a21fe151d812f1 + checksum: 10c0/eeda48372efd0a5103cb22dadb13563c975bce18ae85daafbb47d57bb9665d187da9d4fe8d07ac0a6e1288afcfcb73e4e5618bf75ff63fddf9736bfbf225203b languageName: node linkType: hard -"@babel/plugin-transform-exponentiation-operator@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.24.1" +"@babel/plugin-transform-exponentiation-operator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.24.7" dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor": "npm:^7.22.15" - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-builder-binary-assignment-operator-visitor": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/f0fc4c5a9add25fd6bf23dabe6752e9b7c0a2b2554933dddfd16601245a2ba332b647951079c782bf3b94c6330e3638b9b4e0227f469a7c1c707446ba0eba6c7 + checksum: 10c0/ace3e11c94041b88848552ba8feb39ae4d6cad3696d439ff51445bd2882d8b8775d85a26c2c0edb9b5e38c9e6013cc11b0dea89ec8f93c7d9d7ee95e3645078c languageName: node linkType: hard -"@babel/plugin-transform-export-namespace-from@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-export-namespace-from@npm:7.24.1" +"@babel/plugin-transform-export-namespace-from@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-export-namespace-from@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" "@babel/plugin-syntax-export-namespace-from": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/510bb23b2423d5fbffef69b356e4050929c21a7627e8194b1506dd935c7d9cbbd696c9ae9d7c3bcd7e6e7b69561b0b290c2d72d446327b40fc20ce40bbca6712 + checksum: 10c0/4e144d7f1c57bc63b4899dbbbdfed0880f2daa75ea9c7251c7997f106e4b390dc362175ab7830f11358cb21f6b972ca10a43a2e56cd789065f7606b082674c0c languageName: node linkType: hard -"@babel/plugin-transform-for-of@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-for-of@npm:7.24.1" +"@babel/plugin-transform-for-of@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-for-of@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/e4bc92b1f334246e62d4bde079938df940794db564742034f6597f2e38bd426e11ae8c5670448e15dd6e45c462f2a9ab3fa87259bddf7c08553ffd9457fc2b2c + checksum: 10c0/77629b1173e55d07416f05ba7353caa09d2c2149da2ca26721ab812209b63689d1be45116b68eadc011c49ced59daf5320835b15245eb7ae93ae0c5e8277cfc0 languageName: node linkType: hard -"@babel/plugin-transform-function-name@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-function-name@npm:7.24.1" +"@babel/plugin-transform-function-name@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-function-name@npm:7.24.7" dependencies: - "@babel/helper-compilation-targets": "npm:^7.23.6" - "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-compilation-targets": "npm:^7.24.7" + "@babel/helper-function-name": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/65c1735ec3b5e43db9b5aebf3c16171c04b3050c92396b9e22dda0d2aaf51f43fdcf147f70a40678fd9a4ee2272a5acec4826e9c21bcf968762f4c184897ad75 + checksum: 10c0/3e9642428d6952851850d89ea9307d55946528d18973784d0e2f04a651b23bd9924dd8a2641c824b483bd4ab1223bab1d2f6a1106a939998f7ced512cb60ac5b languageName: node linkType: hard -"@babel/plugin-transform-json-strings@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-json-strings@npm:7.24.1" +"@babel/plugin-transform-json-strings@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-json-strings@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" "@babel/plugin-syntax-json-strings": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/13d9b6a3c31ab4be853b3d49d8d1171f9bd8198562fd75da8f31e7de31398e1cfa6eb1d073bed93c9746e4f9c47a53b20f8f4c255ece3f88c90852ad3181dc2d + checksum: 10c0/17c72cd5bf3e90e722aabd333559275f3309e3fa0b9cea8c2944ab83ae01502c71a2be05da5101edc02b3fc8df15a8dbb9b861cbfcc8a52bf5e797cf01d3a40a languageName: node linkType: hard -"@babel/plugin-transform-literals@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-literals@npm:7.24.1" +"@babel/plugin-transform-literals@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-literals@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/a27cc7d565ee57b5a2bf136fa889c5c2f5988545ae7b3b2c83a7afe5dd37dfac80dca88b1c633c65851ce6af7d2095c04c01228657ce0198f918e64b5ccd01fa + checksum: 10c0/9f3f6f3831929cd2a977748c07addf9944d5cccb50bd3a24a58beb54f91f00d6cacd3d7831d13ffe1ad6f8aba0aefd7bca5aec65d63b77f39c62ad1f2d484a3e languageName: node linkType: hard -"@babel/plugin-transform-logical-assignment-operators@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.24.1" +"@babel/plugin-transform-logical-assignment-operators@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/98a2e0843ddfe51443c1bfcf08ba40ad8856fd4f8e397b392a5390a54f257c8c1b9a99d8ffc0fc7e8c55cce45e2cd9c2795a4450303f48f501bcbd662de44554 + checksum: 10c0/dbe882eb9053931f2ab332c50fc7c2a10ef507d6421bd9831adbb4cb7c9f8e1e5fbac4fbd2e007f6a1bf1df1843547559434012f118084dc0bf42cda3b106272 languageName: node linkType: hard -"@babel/plugin-transform-member-expression-literals@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-member-expression-literals@npm:7.24.1" +"@babel/plugin-transform-member-expression-literals@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/2af731d02aa4c757ef80c46df42264128cbe45bfd15e1812d1a595265b690a44ad036041c406a73411733540e1c4256d8174705ae6b8cfaf757fc175613993fd + checksum: 10c0/e789ae359bdf2d20e90bedef18dfdbd965c9ebae1cee398474a0c349590fda7c8b874e1a2ceee62e47e5e6ec1730e76b0f24e502164357571854271fc12cc684 languageName: node linkType: hard -"@babel/plugin-transform-modules-amd@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-modules-amd@npm:7.24.1" +"@babel/plugin-transform-modules-amd@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-modules-amd@npm:7.24.7" dependencies: - "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-module-transforms": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/71fd04e5e7026e6e52701214b1e9f7508ba371b757e5075fbb938a79235ed66a54ce65f89bb92b59159e9f03f01b392e6c4de6d255b948bec975a90cfd6809ef + checksum: 10c0/6df7de7fce34117ca4b2fa07949b12274c03668cbfe21481c4037b6300796d50ae40f4f170527b61b70a67f26db906747797e30dbd0d9809a441b6e220b5728f languageName: node linkType: hard -"@babel/plugin-transform-modules-commonjs@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.1" +"@babel/plugin-transform-modules-commonjs@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.24.8" dependencies: - "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helper-plugin-utils": "npm:^7.24.0" - "@babel/helper-simple-access": "npm:^7.22.5" + "@babel/helper-module-transforms": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-simple-access": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/efb3ea2047604a7eb44a9289311ebb29842fe6510ff8b66a77a60440448c65e1312a60dc48191ed98246bdbd163b5b6f3348a0669bcc0e3809e69c7c776b20fa + checksum: 10c0/f1cf552307ebfced20d3907c1dd8be941b277f0364aa655e2b5fee828c84c54065745183104dae86f1f93ea0406db970a463ef7ceaaed897623748e99640e5a7 languageName: node linkType: hard -"@babel/plugin-transform-modules-systemjs@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.24.1" +"@babel/plugin-transform-modules-systemjs@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.24.7" dependencies: - "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helper-plugin-utils": "npm:^7.24.0" - "@babel/helper-validator-identifier": "npm:^7.22.20" + "@babel/helper-hoist-variables": "npm:^7.24.7" + "@babel/helper-module-transforms": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-validator-identifier": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/38145f8abe8a4ce2b41adabe5d65eb7bd54a139dc58e2885fec975eb5cf247bd938c1dd9f09145c46dbe57d25dd0ef7f00a020e5eb0cbe8195b2065d51e2d93d + checksum: 10c0/e2a795e0a6baafe26f4a74010622212ddd873170742d673f450e0097f8d984f6e6a95eb8ce41b05071ee9790c4be088b33801aaab3f78ee202c567634e52a331 languageName: node linkType: hard -"@babel/plugin-transform-modules-umd@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-modules-umd@npm:7.24.1" +"@babel/plugin-transform-modules-umd@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-modules-umd@npm:7.24.7" dependencies: - "@babel/helper-module-transforms": "npm:^7.23.3" - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-module-transforms": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/14c90c58562b54e17fe4a8ded3f627f9a993648f8378ef00cb2f6c34532032b83290d2ad54c7fff4f0c2cd49091bda780f8cc28926ec4b77a6c2141105a2e699 + checksum: 10c0/7791d290121db210e4338b94b4a069a1a79e4c7a8d7638d8159a97b281851bbed3048dac87a4ae718ad963005e6c14a5d28e6db2eeb2b04e031cee92fb312f85 languageName: node linkType: hard -"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.22.5" +"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.24.7" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.22.5" - "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-create-regexp-features-plugin": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/b0b072bef303670b5a98307bc37d1ac326cb7ad40ea162b89a03c2ffc465451be7ef05be95cb81ed28bfeb29670dc98fe911f793a67bceab18b4cb4c81ef48f3 + checksum: 10c0/41a0b0f2d0886318237440aa3b489f6d0305361d8671121777d9ff89f9f6de9d0c02ce93625049061426c8994064ef64deae8b819d1b14c00374a6a2336fb5d9 languageName: node linkType: hard -"@babel/plugin-transform-new-target@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-new-target@npm:7.24.1" +"@babel/plugin-transform-new-target@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-new-target@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c4cabe628163855f175a8799eb73d692b6f1dc347aae5022af0c253f80c92edb962e48ddccc98b691eff3d5d8e53c9a8f10894c33ba4cebc2e2f8f8fe554fb7a + checksum: 10c0/2540808a35e1a978e537334c43dab439cf24c93e7beb213a2e71902f6710e60e0184316643790c0a6644e7a8021e52f7ab8165e6b3e2d6651be07bdf517b67df languageName: node linkType: hard -"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.24.1" +"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" "@babel/plugin-syntax-nullish-coalescing-operator": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/c8532951506fb031287280cebeef10aa714f8a7cea2b62a13c805f0e0af945ba77a7c87e4bbbe4c37fe973e0e5d5e649cfac7f0374f57efc54cdf9656362a392 + checksum: 10c0/7243c8ff734ed5ef759dd8768773c4b443c12e792727e759a1aec2c7fa2bfdd24f1ecb42e292a7b3d8bd3d7f7b861cf256a8eb4ba144fc9cc463892c303083d9 languageName: node linkType: hard -"@babel/plugin-transform-numeric-separator@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-numeric-separator@npm:7.24.1" +"@babel/plugin-transform-numeric-separator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-numeric-separator@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" "@babel/plugin-syntax-numeric-separator": "npm:^7.10.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/15e2b83292e586fb4f5b4b4021d4821a806ca6de2b77d5ad6c4e07aa7afa23704e31b4d683dac041afc69ac51b2461b96e8c98e46311cc1faba54c73f235044f + checksum: 10c0/e18e09ca5a6342645d00ede477731aa6e8714ff357efc9d7cda5934f1703b3b6fb7d3298dce3ce3ba53e9ff1158eab8f1aadc68874cc21a6099d33a1ca457789 languageName: node linkType: hard -"@babel/plugin-transform-object-rest-spread@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/plugin-transform-object-rest-spread@npm:7.24.5" +"@babel/plugin-transform-object-rest-spread@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.24.7" dependencies: - "@babel/helper-compilation-targets": "npm:^7.23.6" - "@babel/helper-plugin-utils": "npm:^7.24.5" + "@babel/helper-compilation-targets": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" - "@babel/plugin-transform-parameters": "npm:^7.24.5" + "@babel/plugin-transform-parameters": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/91d7303af9b5744b8f569c1b8e45c9c9322ded05e7ee94e71b9ff2327f0d2c7b5aa87e040697a6baacc2dcb5c5e5e00913087c36f24c006bdaa4f958fd5bfd2d + checksum: 10c0/9ad64bc003f583030f9da50614b485852f8edac93f8faf5d1cd855201a4852f37c5255ae4daf70dd4375bdd4874e16e39b91f680d4668ec219ba05441ce286eb languageName: node linkType: hard -"@babel/plugin-transform-object-super@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-object-super@npm:7.24.1" +"@babel/plugin-transform-object-super@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-object-super@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" - "@babel/helper-replace-supers": "npm:^7.24.1" + "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-replace-supers": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/d30e6b9e59a707efd7ed524fc0a8deeea046011a6990250f2e9280516683138e2d13d9c52daf41d78407bdab0378aef7478326f2a15305b773d851cb6e106157 + checksum: 10c0/770cebb4b4e1872c216b17069db9a13b87dfee747d359dc56d9fcdd66e7544f92dc6ab1861a4e7e0528196aaff2444e4f17dc84efd8eaf162d542b4ba0943869 languageName: node linkType: hard -"@babel/plugin-transform-optional-catch-binding@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.24.1" +"@babel/plugin-transform-optional-catch-binding@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" "@babel/plugin-syntax-optional-catch-binding": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/68408b9ef772d9aa5dccf166c86dc4d2505990ce93e03dcfc65c73fb95c2511248e009ba9ccf5b96405fb85de1c16ad8291016b1cc5689ee4becb1e3050e0ae7 + checksum: 10c0/1e2f10a018f7d03b3bde6c0b70d063df8d5dd5209861d4467726cf834f5e3d354e2276079dc226aa8e6ece35f5c9b264d64b8229a8bb232829c01e561bcfb07a languageName: node linkType: hard -"@babel/plugin-transform-optional-chaining@npm:^7.24.1, @babel/plugin-transform-optional-chaining@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.5" +"@babel/plugin-transform-optional-chaining@npm:^7.24.7, @babel/plugin-transform-optional-chaining@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.24.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.5" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" "@babel/plugin-syntax-optional-chaining": "npm:^7.8.3" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/f4e9446ec69f58f40b7843ce7603cfc50332976e6e794d4ddbe6b24670cd50ebc7766c4e3cbaecf0fbb744e98cbfbb54146f4e966314b1d58511b8bbf3d2722b + checksum: 10c0/4ffbe1aad7dec7c9aa2bf6ceb4b2f91f96815b2784f2879bde80e46934f59d64a12cb2c6262e40897c4754d77d2c35d8a5cfed63044fdebf94978b1ed3d14b17 languageName: node linkType: hard -"@babel/plugin-transform-parameters@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/plugin-transform-parameters@npm:7.24.5" +"@babel/plugin-transform-parameters@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-parameters@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.5" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/e08b8c46a24b1b21dde7783cb0aeb56ffe9ef6d6f1795649ce76273657158d3bfa5370c6594200ed7d371983b599c8e194b76108dffed9ab5746fe630ef2e8f5 + checksum: 10c0/53bf190d6926771545d5184f1f5f3f5144d0f04f170799ad46a43f683a01fab8d5fe4d2196cf246774530990c31fe1f2b9f0def39f0a5ddbb2340b924f5edf01 languageName: node linkType: hard -"@babel/plugin-transform-private-methods@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-private-methods@npm:7.24.1" +"@babel/plugin-transform-private-methods@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-private-methods@npm:7.24.7" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.24.1" - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-create-class-features-plugin": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/d8e18587d2a8b71a795da5e8841b0e64f1525a99ad73ea8b9caa331bc271d69646e2e1e749fd634321f3df9d126070208ddac22a27ccf070566b2efb74fecd99 + checksum: 10c0/5b7bf923b738fbe3ad6c33b260e0a7451be288edfe4ef516303fa787a1870cd87533bfbf61abb779c22ed003c2fc484dec2436fe75a48756f686c0241173d364 languageName: node linkType: hard -"@babel/plugin-transform-private-property-in-object@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/plugin-transform-private-property-in-object@npm:7.24.5" +"@babel/plugin-transform-private-property-in-object@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-private-property-in-object@npm:7.24.7" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.22.5" - "@babel/helper-create-class-features-plugin": "npm:^7.24.5" - "@babel/helper-plugin-utils": "npm:^7.24.5" + "@babel/helper-annotate-as-pure": "npm:^7.24.7" + "@babel/helper-create-class-features-plugin": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/de7182bfde298e56c08a5d7ee1156f83c9af8c856bbe2248438848846a4ce544e050666bd0482e16a6006195e8be4923abd14650bef51fa0edd7f82014c2efcd + checksum: 10c0/c6fa7defb90b1b0ed46f24ff94ff2e77f44c1f478d1090e81712f33cf992dda5ba347016f030082a2f770138bac6f4a9c2c1565e9f767a125901c77dd9c239ba languageName: node linkType: hard -"@babel/plugin-transform-property-literals@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-property-literals@npm:7.24.1" +"@babel/plugin-transform-property-literals@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-property-literals@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/3bf3e01f7bb8215a8b6d0081b6f86fea23e3a4543b619e059a264ede028bc58cdfb0acb2c43271271915a74917effa547bc280ac636a9901fa9f2fb45623f87e + checksum: 10c0/52564b58f3d111dc02d241d5892a4b01512e98dfdf6ef11b0ed62f8b11b0acacccef0fc229b44114fe8d1a57a8b70780b11bdd18b807d3754a781a07d8f57433 languageName: node linkType: hard -"@babel/plugin-transform-regenerator@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-regenerator@npm:7.24.1" +"@babel/plugin-transform-regenerator@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-regenerator@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" regenerator-transform: "npm:^0.15.2" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/0a333585d7c0b38d31cc549d0f3cf7c396d1d50b6588a307dc58325505ddd4f5446188bc536c4779431b396251801b3f32d6d8e87db8274bc84e8c41950737f7 + checksum: 10c0/d2dc2c788fdae9d97217e70d46ba8ca9db0035c398dc3e161552b0c437113719a75c04f201f9c91ddc8d28a1da60d0b0853f616dead98a396abb9c845c44892b languageName: node linkType: hard -"@babel/plugin-transform-reserved-words@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-reserved-words@npm:7.24.1" +"@babel/plugin-transform-reserved-words@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-reserved-words@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/936d6e73cafb2cbb495f6817c6f8463288dbc9ab3c44684b931ebc1ece24f0d55dfabc1a75ba1de5b48843d0fef448dcfdbecb8485e4014f8f41d0d1440c536f + checksum: 10c0/2229de2768615e7f5dc0bbc55bc121b5678fd6d2febd46c74a58e42bb894d74cd5955c805880f4e02d0e1cf94f6886270eda7fafc1be9305a1ec3b9fd1d063f5 languageName: node linkType: hard -"@babel/plugin-transform-shorthand-properties@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-shorthand-properties@npm:7.24.1" +"@babel/plugin-transform-shorthand-properties@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/8273347621183aada3cf1f3019d8d5f29467ba13a75b72cb405bc7f23b7e05fd85f4edb1e4d9f0103153dddb61826a42dc24d466480d707f8932c1923a4c25fa + checksum: 10c0/41b155bdbb3be66618358488bf7731b3b2e8fff2de3dbfd541847720a9debfcec14db06a117abedd03c9cd786db20a79e2a86509a4f19513f6e1b610520905cf languageName: node linkType: hard -"@babel/plugin-transform-spread@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-spread@npm:7.24.1" +"@babel/plugin-transform-spread@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-spread@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + "@babel/helper-plugin-utils": "npm:^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/50a0302e344546d57e5c9f4dea575f88e084352eeac4e9a3e238c41739eef2df1daf4a7ebbb3ccb7acd3447f6a5ce9938405f98bf5f5583deceb8257f5a673c9 + checksum: 10c0/facba1553035f76b0d2930d4ada89a8cd0f45b79579afd35baefbfaf12e3b86096995f4b0c402cf9ee23b3f2ea0a4460c3b1ec0c192d340962c948bb223d4e66 languageName: node linkType: hard -"@babel/plugin-transform-sticky-regex@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-sticky-regex@npm:7.24.1" +"@babel/plugin-transform-sticky-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-sticky-regex@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/786fe2ae11ef9046b9fa95677935abe495031eebf1274ad03f2054a20adea7b9dbd00336ac0b143f7924bc562e5e09793f6e8613607674b97e067d4838ccc4a0 + checksum: 10c0/5a74ed2ed0a3ab51c3d15fcaf09d9e2fe915823535c7a4d7b019813177d559b69677090e189ec3d5d08b619483eb5ad371fbcfbbff5ace2a76ba33ee566a1109 languageName: node linkType: hard -"@babel/plugin-transform-template-literals@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-template-literals@npm:7.24.1" +"@babel/plugin-transform-template-literals@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-template-literals@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/f73bcda5488eb81c6e7a876498d9e6b72be32fca5a4d9db9053491a2d1300cd27b889b463fd2558f3cd5826a85ed00f61d81b234aa55cb5a0abf1b6fa1bd5026 + checksum: 10c0/3630f966257bcace122f04d3157416a09d40768c44c3a800855da81146b009187daa21859d1c3b7d13f4e19e8888e60613964b175b2275d451200fb6d8d6cfe6 languageName: node linkType: hard -"@babel/plugin-transform-typeof-symbol@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/plugin-transform-typeof-symbol@npm:7.24.5" +"@babel/plugin-transform-typeof-symbol@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/plugin-transform-typeof-symbol@npm:7.24.8" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.5" + "@babel/helper-plugin-utils": "npm:^7.24.8" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/5f0b5e33a86b84d89673829ffa2b5f175e102d3d0f45917cda121bc2b3650e1e5bb7a653f8cc1059c5b3a7b2e91e1aafd6623028b96ae752715cc5c2171c96e5 + checksum: 10c0/2f570a4fbbdc5fd85f48165a97452826560051e3b8efb48c3bb0a0a33ee8485633439e7b71bfe3ef705583a1df43f854f49125bd759abdedc195b2cf7e60012a languageName: node linkType: hard -"@babel/plugin-transform-unicode-escapes@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-unicode-escapes@npm:7.24.1" +"@babel/plugin-transform-unicode-escapes@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-unicode-escapes@npm:7.24.7" dependencies: - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/67a72a1ed99639de6a93aead35b1993cb3f0eb178a8991fcef48732c38c9f0279c85bbe1e2e2477b85afea873e738ff0955a35057635ce67bc149038e2d8a28e + checksum: 10c0/8b18e2e66af33471a6971289492beff5c240e56727331db1d34c4338a6a368a82a7ed6d57ec911001b6d65643aed76531e1e7cac93265fb3fb2717f54d845e69 languageName: node linkType: hard -"@babel/plugin-transform-unicode-property-regex@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.24.1" +"@babel/plugin-transform-unicode-property-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.24.7" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.22.15" - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-create-regexp-features-plugin": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/d9d9752df7d51bf9357c0bf3762fe16b8c841fca9ecf4409a16f15ccc34be06e8e71abfaee1251b7d451227e70e6b873b36f86b090efdb20f6f7de5fdb6c7a05 + checksum: 10c0/bc57656eb94584d1b74a385d378818ac2b3fca642e3f649fead8da5fb3f9de22f8461185936915dfb33d5a9104e62e7a47828331248b09d28bb2d59e9276de3e languageName: node linkType: hard -"@babel/plugin-transform-unicode-regex@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-unicode-regex@npm:7.24.1" +"@babel/plugin-transform-unicode-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-unicode-regex@npm:7.24.7" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.22.15" - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-create-regexp-features-plugin": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/6046ab38e5d14ed97dbb921bd79ac1d7ad9d3286da44a48930e980b16896db2df21e093563ec3c916a630dc346639bf47c5924a33902a06fe3bbb5cdc7ef5f2f + checksum: 10c0/83f72a345b751566b601dc4d07e9f2c8f1bc0e0c6f7abb56ceb3095b3c9d304de73f85f2f477a09f8cc7edd5e65afd0ff9e376cdbcbea33bc0c28f3705b38fd9 languageName: node linkType: hard -"@babel/plugin-transform-unicode-sets-regex@npm:^7.24.1": - version: 7.24.1 - resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.24.1" +"@babel/plugin-transform-unicode-sets-regex@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.24.7" dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.22.15" - "@babel/helper-plugin-utils": "npm:^7.24.0" + "@babel/helper-create-regexp-features-plugin": "npm:^7.24.7" + "@babel/helper-plugin-utils": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/b6c1f6b90afeeddf97e5713f72575787fcb7179be7b4c961869bfbc66915f66540dc49da93e4369da15596bd44b896d1eb8a50f5e1fd907abd7a1a625901006b + checksum: 10c0/7457c0ee8e80a80cb6fdc1fe54ab115b52815627616ce9151be8ef292fc99d04a910ec24f11382b4f124b89374264396892b086886bd2a9c2317904d87c9b21b languageName: node linkType: hard -"@babel/preset-env@npm:7.24.5": - version: 7.24.5 - resolution: "@babel/preset-env@npm:7.24.5" +"@babel/preset-env@npm:7.24.8": + version: 7.24.8 + resolution: "@babel/preset-env@npm:7.24.8" dependencies: - "@babel/compat-data": "npm:^7.24.4" - "@babel/helper-compilation-targets": "npm:^7.23.6" - "@babel/helper-plugin-utils": "npm:^7.24.5" - "@babel/helper-validator-option": "npm:^7.23.5" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.24.5" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.24.1" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.24.1" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.24.1" + "@babel/compat-data": "npm:^7.24.8" + "@babel/helper-compilation-targets": "npm:^7.24.8" + "@babel/helper-plugin-utils": "npm:^7.24.8" + "@babel/helper-validator-option": "npm:^7.24.8" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.24.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.24.7" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.24.7" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.24.7" "@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators": "npm:^7.8.4" "@babel/plugin-syntax-class-properties": "npm:^7.12.13" "@babel/plugin-syntax-class-static-block": "npm:^7.14.5" "@babel/plugin-syntax-dynamic-import": "npm:^7.8.3" "@babel/plugin-syntax-export-namespace-from": "npm:^7.8.3" - "@babel/plugin-syntax-import-assertions": "npm:^7.24.1" - "@babel/plugin-syntax-import-attributes": "npm:^7.24.1" + "@babel/plugin-syntax-import-assertions": "npm:^7.24.7" + "@babel/plugin-syntax-import-attributes": "npm:^7.24.7" "@babel/plugin-syntax-import-meta": "npm:^7.10.4" "@babel/plugin-syntax-json-strings": "npm:^7.8.3" "@babel/plugin-syntax-logical-assignment-operators": "npm:^7.10.4" @@ -1237,63 +1244,63 @@ __metadata: "@babel/plugin-syntax-private-property-in-object": "npm:^7.14.5" "@babel/plugin-syntax-top-level-await": "npm:^7.14.5" "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" - "@babel/plugin-transform-arrow-functions": "npm:^7.24.1" - "@babel/plugin-transform-async-generator-functions": "npm:^7.24.3" - "@babel/plugin-transform-async-to-generator": "npm:^7.24.1" - "@babel/plugin-transform-block-scoped-functions": "npm:^7.24.1" - "@babel/plugin-transform-block-scoping": "npm:^7.24.5" - "@babel/plugin-transform-class-properties": "npm:^7.24.1" - "@babel/plugin-transform-class-static-block": "npm:^7.24.4" - "@babel/plugin-transform-classes": "npm:^7.24.5" - "@babel/plugin-transform-computed-properties": "npm:^7.24.1" - "@babel/plugin-transform-destructuring": "npm:^7.24.5" - "@babel/plugin-transform-dotall-regex": "npm:^7.24.1" - "@babel/plugin-transform-duplicate-keys": "npm:^7.24.1" - "@babel/plugin-transform-dynamic-import": "npm:^7.24.1" - "@babel/plugin-transform-exponentiation-operator": "npm:^7.24.1" - "@babel/plugin-transform-export-namespace-from": "npm:^7.24.1" - "@babel/plugin-transform-for-of": "npm:^7.24.1" - "@babel/plugin-transform-function-name": "npm:^7.24.1" - "@babel/plugin-transform-json-strings": "npm:^7.24.1" - "@babel/plugin-transform-literals": "npm:^7.24.1" - "@babel/plugin-transform-logical-assignment-operators": "npm:^7.24.1" - "@babel/plugin-transform-member-expression-literals": "npm:^7.24.1" - "@babel/plugin-transform-modules-amd": "npm:^7.24.1" - "@babel/plugin-transform-modules-commonjs": "npm:^7.24.1" - "@babel/plugin-transform-modules-systemjs": "npm:^7.24.1" - "@babel/plugin-transform-modules-umd": "npm:^7.24.1" - "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.22.5" - "@babel/plugin-transform-new-target": "npm:^7.24.1" - "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.24.1" - "@babel/plugin-transform-numeric-separator": "npm:^7.24.1" - "@babel/plugin-transform-object-rest-spread": "npm:^7.24.5" - "@babel/plugin-transform-object-super": "npm:^7.24.1" - "@babel/plugin-transform-optional-catch-binding": "npm:^7.24.1" - "@babel/plugin-transform-optional-chaining": "npm:^7.24.5" - "@babel/plugin-transform-parameters": "npm:^7.24.5" - "@babel/plugin-transform-private-methods": "npm:^7.24.1" - "@babel/plugin-transform-private-property-in-object": "npm:^7.24.5" - "@babel/plugin-transform-property-literals": "npm:^7.24.1" - "@babel/plugin-transform-regenerator": "npm:^7.24.1" - "@babel/plugin-transform-reserved-words": "npm:^7.24.1" - "@babel/plugin-transform-shorthand-properties": "npm:^7.24.1" - "@babel/plugin-transform-spread": "npm:^7.24.1" - "@babel/plugin-transform-sticky-regex": "npm:^7.24.1" - "@babel/plugin-transform-template-literals": "npm:^7.24.1" - "@babel/plugin-transform-typeof-symbol": "npm:^7.24.5" - "@babel/plugin-transform-unicode-escapes": "npm:^7.24.1" - "@babel/plugin-transform-unicode-property-regex": "npm:^7.24.1" - "@babel/plugin-transform-unicode-regex": "npm:^7.24.1" - "@babel/plugin-transform-unicode-sets-regex": "npm:^7.24.1" + "@babel/plugin-transform-arrow-functions": "npm:^7.24.7" + "@babel/plugin-transform-async-generator-functions": "npm:^7.24.7" + "@babel/plugin-transform-async-to-generator": "npm:^7.24.7" + "@babel/plugin-transform-block-scoped-functions": "npm:^7.24.7" + "@babel/plugin-transform-block-scoping": "npm:^7.24.7" + "@babel/plugin-transform-class-properties": "npm:^7.24.7" + "@babel/plugin-transform-class-static-block": "npm:^7.24.7" + "@babel/plugin-transform-classes": "npm:^7.24.8" + "@babel/plugin-transform-computed-properties": "npm:^7.24.7" + "@babel/plugin-transform-destructuring": "npm:^7.24.8" + "@babel/plugin-transform-dotall-regex": "npm:^7.24.7" + "@babel/plugin-transform-duplicate-keys": "npm:^7.24.7" + "@babel/plugin-transform-dynamic-import": "npm:^7.24.7" + "@babel/plugin-transform-exponentiation-operator": "npm:^7.24.7" + "@babel/plugin-transform-export-namespace-from": "npm:^7.24.7" + "@babel/plugin-transform-for-of": "npm:^7.24.7" + "@babel/plugin-transform-function-name": "npm:^7.24.7" + "@babel/plugin-transform-json-strings": "npm:^7.24.7" + "@babel/plugin-transform-literals": "npm:^7.24.7" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.24.7" + "@babel/plugin-transform-member-expression-literals": "npm:^7.24.7" + "@babel/plugin-transform-modules-amd": "npm:^7.24.7" + "@babel/plugin-transform-modules-commonjs": "npm:^7.24.8" + "@babel/plugin-transform-modules-systemjs": "npm:^7.24.7" + "@babel/plugin-transform-modules-umd": "npm:^7.24.7" + "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.24.7" + "@babel/plugin-transform-new-target": "npm:^7.24.7" + "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.24.7" + "@babel/plugin-transform-numeric-separator": "npm:^7.24.7" + "@babel/plugin-transform-object-rest-spread": "npm:^7.24.7" + "@babel/plugin-transform-object-super": "npm:^7.24.7" + "@babel/plugin-transform-optional-catch-binding": "npm:^7.24.7" + "@babel/plugin-transform-optional-chaining": "npm:^7.24.8" + "@babel/plugin-transform-parameters": "npm:^7.24.7" + "@babel/plugin-transform-private-methods": "npm:^7.24.7" + "@babel/plugin-transform-private-property-in-object": "npm:^7.24.7" + "@babel/plugin-transform-property-literals": "npm:^7.24.7" + "@babel/plugin-transform-regenerator": "npm:^7.24.7" + "@babel/plugin-transform-reserved-words": "npm:^7.24.7" + "@babel/plugin-transform-shorthand-properties": "npm:^7.24.7" + "@babel/plugin-transform-spread": "npm:^7.24.7" + "@babel/plugin-transform-sticky-regex": "npm:^7.24.7" + "@babel/plugin-transform-template-literals": "npm:^7.24.7" + "@babel/plugin-transform-typeof-symbol": "npm:^7.24.8" + "@babel/plugin-transform-unicode-escapes": "npm:^7.24.7" + "@babel/plugin-transform-unicode-property-regex": "npm:^7.24.7" + "@babel/plugin-transform-unicode-regex": "npm:^7.24.7" + "@babel/plugin-transform-unicode-sets-regex": "npm:^7.24.7" "@babel/preset-modules": "npm:0.1.6-no-external-plugins" babel-plugin-polyfill-corejs2: "npm:^0.4.10" babel-plugin-polyfill-corejs3: "npm:^0.10.4" babel-plugin-polyfill-regenerator: "npm:^0.6.1" - core-js-compat: "npm:^3.31.0" + core-js-compat: "npm:^3.37.1" semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/2cc0edae09205d6409a75d02e53aaa1c590e89adbb7b389019c7b75e4c47b6b63eeb1a816df5c42b672ce410747e7ddc23b6747e8e41a6c95d6fa00c665509e2 + checksum: 10c0/a6f29498ec58989845a61f9c10b1b4e80586f1810a33db461d597cdb0ad2cd847381a993038b09f727512a08b2c1a33a330a5d4e6d65463ee98a1b4302d52ec6 languageName: node linkType: hard @@ -1326,109 +1333,109 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.22.15, @babel/template@npm:^7.24.0": - version: 7.24.0 - resolution: "@babel/template@npm:7.24.0" +"@babel/template@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/template@npm:7.24.7" dependencies: - "@babel/code-frame": "npm:^7.23.5" - "@babel/parser": "npm:^7.24.0" - "@babel/types": "npm:^7.24.0" - checksum: 10c0/9d3dd8d22fe1c36bc3bdef6118af1f4b030aaf6d7d2619f5da203efa818a2185d717523486c111de8d99a8649ddf4bbf6b2a7a64962d8411cf6a8fa89f010e54 + "@babel/code-frame": "npm:^7.24.7" + "@babel/parser": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 10c0/95b0b3ee80fcef685b7f4426f5713a855ea2cd5ac4da829b213f8fb5afe48a2a14683c2ea04d446dbc7f711c33c5cd4a965ef34dcbe5bc387c9e966b67877ae3 languageName: node linkType: hard -"@babel/traverse@npm:^7.24.5": - version: 7.24.5 - resolution: "@babel/traverse@npm:7.24.5" +"@babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/traverse@npm:7.24.8" dependencies: - "@babel/code-frame": "npm:^7.24.2" - "@babel/generator": "npm:^7.24.5" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.24.5" - "@babel/parser": "npm:^7.24.5" - "@babel/types": "npm:^7.24.5" + "@babel/code-frame": "npm:^7.24.7" + "@babel/generator": "npm:^7.24.8" + "@babel/helper-environment-visitor": "npm:^7.24.7" + "@babel/helper-function-name": "npm:^7.24.7" + "@babel/helper-hoist-variables": "npm:^7.24.7" + "@babel/helper-split-export-declaration": "npm:^7.24.7" + "@babel/parser": "npm:^7.24.8" + "@babel/types": "npm:^7.24.8" debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 10c0/3f22534bc2b2ed9208e55ef48af3b32939032b23cb9dc4037447cb108640df70bbb0b9fea86e9c58648949fdc2cb14e89aa79ffa3c62a5dd43459a52fe8c01d1 + checksum: 10c0/67a5cc35824455cdb54fb9e196a44b3186283e29018a9c2331f51763921e18e891b3c60c283615a27540ec8eb4c8b89f41c237b91f732a7aa518b2eb7a0d434d languageName: node linkType: hard -"@babel/types@npm:^7.22.15, @babel/types@npm:^7.22.19, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.24.0, @babel/types@npm:^7.24.5, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": - version: 7.24.5 - resolution: "@babel/types@npm:7.24.5" +"@babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.24.9, @babel/types@npm:^7.4.4, @babel/types@npm:^7.8.3": + version: 7.24.9 + resolution: "@babel/types@npm:7.24.9" dependencies: - "@babel/helper-string-parser": "npm:^7.24.1" - "@babel/helper-validator-identifier": "npm:^7.24.5" + "@babel/helper-string-parser": "npm:^7.24.8" + "@babel/helper-validator-identifier": "npm:^7.24.7" to-fast-properties: "npm:^2.0.0" - checksum: 10c0/e1284eb046c5e0451b80220d1200e2327e0a8544a2fe45bb62c952e5fdef7099c603d2336b17b6eac3cc046b7a69bfbce67fe56e1c0ea48cd37c65cb88638f2a + checksum: 10c0/4970b3481cab39c5c3fdb7c28c834df5c7049f3c7f43baeafe121bb05270ebf0da7c65b097abf314877f213baa591109c82204f30d66cdd46c22ece4a2f32415 languageName: node linkType: hard -"@csstools/cascade-layer-name-parser@npm:^1.0.11": - version: 1.0.11 - resolution: "@csstools/cascade-layer-name-parser@npm:1.0.11" +"@csstools/cascade-layer-name-parser@npm:^1.0.13": + version: 1.0.13 + resolution: "@csstools/cascade-layer-name-parser@npm:1.0.13" peerDependencies: - "@csstools/css-parser-algorithms": ^2.6.3 - "@csstools/css-tokenizer": ^2.3.1 - checksum: 10c0/52ac8369877c8072ff5c111f656bd87e9a2a4b9e44e48fe005c26faeb6cffd83bfe2f463f4f385a2ae5cfe1f82bbf95d26ddaabca18b66c6b657c4fe1520fb43 + "@csstools/css-parser-algorithms": ^2.7.1 + "@csstools/css-tokenizer": ^2.4.1 + checksum: 10c0/a6412fc8601af1baadc8195934aa668d3476e799891c9d0883390f31ec8678e9b565ac14d919bec633bbc086657ac12aa4cd852c718851a2d34517ee6856ff8e languageName: node linkType: hard -"@csstools/color-helpers@npm:^4.2.0": - version: 4.2.0 - resolution: "@csstools/color-helpers@npm:4.2.0" - checksum: 10c0/3f1feac43c2ef35f38b3b06fe74e0acc130283d7efb6874f6624e45e178c1a7b3c7e39816c7421cddbffc2666430906aa6f0d3dd7c7209db1369c0afd4a29b1b +"@csstools/color-helpers@npm:^4.2.1": + version: 4.2.1 + resolution: "@csstools/color-helpers@npm:4.2.1" + checksum: 10c0/72e11b186ad0f6019a9b4b3752e620fa798c2a40cf47e8cad565dff46e572c9342eb8cf804542d7886344a1e540555d77f20119ace6b2d8a45b6e5ef8a41685c languageName: node linkType: hard -"@csstools/css-calc@npm:^1.2.2": - version: 1.2.2 - resolution: "@csstools/css-calc@npm:1.2.2" +"@csstools/css-calc@npm:^1.2.4": + version: 1.2.4 + resolution: "@csstools/css-calc@npm:1.2.4" peerDependencies: - "@csstools/css-parser-algorithms": ^2.6.3 - "@csstools/css-tokenizer": ^2.3.1 - checksum: 10c0/6032b482764a11c1b882d7502928950ab11760044fa7a2c23ecee802002902f6ea8fca045ee2919302af5a5c399e7baa9f68dff001ac6246ac7fef48fb3f6df7 + "@csstools/css-parser-algorithms": ^2.7.1 + "@csstools/css-tokenizer": ^2.4.1 + checksum: 10c0/6233746eb642797b7fbc2cf6e7651e95700b294e78e3c29e8730c3236bb92cf62903efb6e54639e8f877683c40646e137c95e615c4450809b21b61a6192888ca languageName: node linkType: hard -"@csstools/css-color-parser@npm:^2.0.2": - version: 2.0.2 - resolution: "@csstools/css-color-parser@npm:2.0.2" +"@csstools/css-color-parser@npm:^2.0.4": + version: 2.0.4 + resolution: "@csstools/css-color-parser@npm:2.0.4" dependencies: - "@csstools/color-helpers": "npm:^4.2.0" - "@csstools/css-calc": "npm:^1.2.2" + "@csstools/color-helpers": "npm:^4.2.1" + "@csstools/css-calc": "npm:^1.2.4" peerDependencies: - "@csstools/css-parser-algorithms": ^2.6.3 - "@csstools/css-tokenizer": ^2.3.1 - checksum: 10c0/c5ae4ad78745e425dce56da9f1ab053fb4f7963399735df3303305b32123bed0b2237689c2e7e99da2c62387e3226c12ea85e70e275c4027c7507e4ac929bffa + "@csstools/css-parser-algorithms": ^2.7.1 + "@csstools/css-tokenizer": ^2.4.1 + checksum: 10c0/e009a2f34b6c328daad54262deb86b71c6a7a9a1da1db8ad39cf719641e1a728ed8ddbd23613d519d26deee33b89ba12cb15a6928718c1b3cc5e24ac1ed02f47 languageName: node linkType: hard -"@csstools/css-parser-algorithms@npm:^2.6.1, @csstools/css-parser-algorithms@npm:^2.6.3": - version: 2.6.3 - resolution: "@csstools/css-parser-algorithms@npm:2.6.3" +"@csstools/css-parser-algorithms@npm:^2.7.1": + version: 2.7.1 + resolution: "@csstools/css-parser-algorithms@npm:2.7.1" peerDependencies: - "@csstools/css-tokenizer": ^2.3.1 - checksum: 10c0/6648fda75a1c08096320fb5c04fd13656a0168de13584d2795547fecfb26c2c7d8b3b1fb79ba7aa758714851e98bfbec20d89e28697f999f41f91133eafe4207 + "@csstools/css-tokenizer": ^2.4.1 + checksum: 10c0/7d29bef6f5790ddb67d922ad232253bf910e4fa5293f5e4a5ed8b920ae9bd4e8171942df7d8943af23b42fd4e9fb460181394d20c97da9562e6ce98a875e8c47 languageName: node linkType: hard -"@csstools/css-tokenizer@npm:^2.2.4, @csstools/css-tokenizer@npm:^2.3.1": - version: 2.3.1 - resolution: "@csstools/css-tokenizer@npm:2.3.1" - checksum: 10c0/fed6619fb5108e109d4dd10b0e967035a92793bae8fb84544e1342058b6df4e306d9d075623e2201fe88831b1ada797aea3546a8d12229d2d81cd7a5dfee4444 +"@csstools/css-tokenizer@npm:^2.4.1": + version: 2.4.1 + resolution: "@csstools/css-tokenizer@npm:2.4.1" + checksum: 10c0/fe71cee85ec7372da07083d088b6a704f43e5d3d2d8071c4b8a86fae60408b559a218a43f8625bf2f0be5c7f90c8f3ad20a1aae1921119a1c02b51c310cc2b6b languageName: node linkType: hard -"@csstools/media-query-list-parser@npm:^2.1.11, @csstools/media-query-list-parser@npm:^2.1.9": - version: 2.1.11 - resolution: "@csstools/media-query-list-parser@npm:2.1.11" +"@csstools/media-query-list-parser@npm:^2.1.13": + version: 2.1.13 + resolution: "@csstools/media-query-list-parser@npm:2.1.13" peerDependencies: - "@csstools/css-parser-algorithms": ^2.6.3 - "@csstools/css-tokenizer": ^2.3.1 - checksum: 10c0/9bcd99f7d28ae3cdaba73fbbfef571b0393dd4e841f522cc796fe5161744f17e327ba1713dad3c481626fade1357c55890e3d365177abed50e857b69130a9be5 + "@csstools/css-parser-algorithms": ^2.7.1 + "@csstools/css-tokenizer": ^2.4.1 + checksum: 10c0/8bf72342c15581b8f658633436d83c26a214056f6b960ff121b940271f4b1b5b07e9cc3990a73e684fb72319592f0c392408b4f0e08bbe242b2065aa456e2733 languageName: node linkType: hard @@ -1444,46 +1451,60 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-color-function@npm:^3.0.16": - version: 3.0.16 - resolution: "@csstools/postcss-color-function@npm:3.0.16" +"@csstools/postcss-color-function@npm:^3.0.19": + version: 3.0.19 + resolution: "@csstools/postcss-color-function@npm:3.0.19" dependencies: - "@csstools/css-color-parser": "npm:^2.0.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/41756a4601a3f1086290dab6ca92b54e201bd94637b54b439c66a04fd628a14e2a0bd1452ad294d2981e2f4bb306758fa5f44639b1c4332320435050749aa487 + checksum: 10c0/067e33d7dfc32b56fe63d4f97464a3eaf27dde720961e44feab6076bd2c172dd4c1bad16aa37a922dcbba470756bd6a13e728d9e71eab6937d48d83873cd1879 languageName: node linkType: hard -"@csstools/postcss-color-mix-function@npm:^2.0.16": - version: 2.0.16 - resolution: "@csstools/postcss-color-mix-function@npm:2.0.16" +"@csstools/postcss-color-mix-function@npm:^2.0.19": + version: 2.0.19 + resolution: "@csstools/postcss-color-mix-function@npm:2.0.19" dependencies: - "@csstools/css-color-parser": "npm:^2.0.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/70cd5b291dd615e20e4475517bf0027c90c433241397a66866f89acedb12cb91f45552a162bdd1000636ec56f7d6a099b65e44fe100fd03228fc65f17cfae285 + checksum: 10c0/e967d93672a065806dc78da0153f8b4f5087f7c3ddfe361eba4942780760d47b317124913c9b0dda7f9bfff1253f77d1b6debd8a6a2aa3a6c80e263101da5e8c languageName: node linkType: hard -"@csstools/postcss-exponential-functions@npm:^1.0.7": - version: 1.0.7 - resolution: "@csstools/postcss-exponential-functions@npm:1.0.7" +"@csstools/postcss-content-alt-text@npm:^1.0.0": + version: 1.0.0 + resolution: "@csstools/postcss-content-alt-text@npm:1.0.0" dependencies: - "@csstools/css-calc": "npm:^1.2.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" + "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/2079c81c3437686ef432d88502fa3a13bf8a27b7af105b4c6c2eb8e779f14adc8967a5a3ed03271ab919eeaf999fc4489fe4b37d32a8f61ab3212439517bddcc + checksum: 10c0/0c2c64857ac652989d00c3d2ba49d0cd1cc245193cba6724d2f5841aa990ee6a07267cfebc6fabde6a6246616df60373006d17c5ea9b904129fbfd826dc10a8d + languageName: node + linkType: hard + +"@csstools/postcss-exponential-functions@npm:^1.0.9": + version: 1.0.9 + resolution: "@csstools/postcss-exponential-functions@npm:1.0.9" + dependencies: + "@csstools/css-calc": "npm:^1.2.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + peerDependencies: + postcss: ^8.4 + checksum: 10c0/eaec29ef6ec201786c606176235dced4af1922d5ac56c6b0993ad2e7d87464a32702d9b28cae9a76e8527f741b50cbc31d4c646f45d02dc69d520f241b3e7878 languageName: node linkType: hard @@ -1499,59 +1520,59 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-gamut-mapping@npm:^1.0.9": - version: 1.0.9 - resolution: "@csstools/postcss-gamut-mapping@npm:1.0.9" +"@csstools/postcss-gamut-mapping@npm:^1.0.11": + version: 1.0.11 + resolution: "@csstools/postcss-gamut-mapping@npm:1.0.11" dependencies: - "@csstools/css-color-parser": "npm:^2.0.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" peerDependencies: postcss: ^8.4 - checksum: 10c0/412ae1410f3fce240401576441637c2c4e71d1a54153ac9b7a991b3de7519c253d03e10db78b09872eb10b0776d7f960b442779efabc11332b5be6672163c836 + checksum: 10c0/29e755013f1d1de34eb62a931ed410d2830ca3dfc81476cb3c72d9d3260b85a9adedc51aa548550c6e308f3f9640c489e6953db40e9cac9835d0421d5b14ef1f languageName: node linkType: hard -"@csstools/postcss-gradients-interpolation-method@npm:^4.0.17": - version: 4.0.17 - resolution: "@csstools/postcss-gradients-interpolation-method@npm:4.0.17" +"@csstools/postcss-gradients-interpolation-method@npm:^4.0.20": + version: 4.0.20 + resolution: "@csstools/postcss-gradients-interpolation-method@npm:4.0.20" dependencies: - "@csstools/css-color-parser": "npm:^2.0.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/465ac42856ca1a57aa2b9ea41ede31d9e2bcf2fe84345dbc182ae41f463069a0cfd41041b834b5133108c702cd85ecb8636b51b0b88fff8a221628639b59f386 + checksum: 10c0/6588825a72a1471e2d6036c8cf7dbad2bf05f369d96dbdd68ff5ce7ff91803b8ee1146f5f1bf6f3ab6299944549da872914664c3f9e8ae5a31847f76f0085c74 languageName: node linkType: hard -"@csstools/postcss-hwb-function@npm:^3.0.15": - version: 3.0.15 - resolution: "@csstools/postcss-hwb-function@npm:3.0.15" +"@csstools/postcss-hwb-function@npm:^3.0.18": + version: 3.0.18 + resolution: "@csstools/postcss-hwb-function@npm:3.0.18" dependencies: - "@csstools/css-color-parser": "npm:^2.0.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/fdfaeefbab1008ab1e4a98a2b45cc3db002b2724c404fa0600954b411a68b1fa4028286250bf9898eed10fa80c44e4d6b4e55f1aca073c3dfce8198a0aaedf3f + checksum: 10c0/e9d76b0b2f9c54920124ca1804b49e3f5b26e003729418b5ef4b340ff1baa4779da1c02be618888fdbcc2d0747182352efbbd3ffe128e2417928c35c25443789 languageName: node linkType: hard -"@csstools/postcss-ic-unit@npm:^3.0.6": - version: 3.0.6 - resolution: "@csstools/postcss-ic-unit@npm:3.0.6" +"@csstools/postcss-ic-unit@npm:^3.0.7": + version: 3.0.7 + resolution: "@csstools/postcss-ic-unit@npm:3.0.7" dependencies: - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/a4b962327d433419fdcfdcf620ce6a5cf09aa3c93029ad08b035df1e2bc35caae31de49f1d14218de0656fced35c0d2e07e5ff7b8099c29dbfb40395fc283234 + checksum: 10c0/2add905b75860c64d7174886fecfc76d86e3818f42f003f4bbfc0604cc7f0f31c6dbd1651e6b9512fea876190d80033578ae49e813b64b17c8cf3b1f03d8e146 languageName: node linkType: hard @@ -1576,17 +1597,17 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-light-dark-function@npm:^1.0.5": - version: 1.0.5 - resolution: "@csstools/postcss-light-dark-function@npm:1.0.5" +"@csstools/postcss-light-dark-function@npm:^1.0.8": + version: 1.0.8 + resolution: "@csstools/postcss-light-dark-function@npm:1.0.8" dependencies: - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/4fbeda98372d0da25d3ed87da09903c9a0a5d0b8c13cc9de82a98acce4a8f8367e5ba33bfc25c2534d10f2b1db9d5b4278df4ebab755e27ef2b03a95e0ebe264 + checksum: 10c0/78fa6d799d38f14af1b32b534eedbec9478033e1fbc5a4e820f2421e865673d010b69b391546686ceb408ead64d79bb4eba2a4fb1fc9f0de70ff21e3ff8477c6 languageName: node linkType: hard @@ -1628,42 +1649,42 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-logical-viewport-units@npm:^2.0.9": - version: 2.0.9 - resolution: "@csstools/postcss-logical-viewport-units@npm:2.0.9" +"@csstools/postcss-logical-viewport-units@npm:^2.0.11": + version: 2.0.11 + resolution: "@csstools/postcss-logical-viewport-units@npm:2.0.11" dependencies: - "@csstools/css-tokenizer": "npm:^2.3.1" + "@csstools/css-tokenizer": "npm:^2.4.1" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/25b01e36b08c571806d09046be63582dbebf97a4612df59be405fa8a92e6eebcd4e768ad7fbe53b0b8739d6ab04d56957964fb04d6a3ea129fc5f72e6d0adf95 + checksum: 10c0/20207e9b7fc3ab52df5fcd06fde71fca4fd22bd6bd451cfc2ec6ea69994708b7fc5381e203dc4367293a8de00b1eca7a3ebe89cfa9b933d2f2cb8e3ac4d5aa86 languageName: node linkType: hard -"@csstools/postcss-media-minmax@npm:^1.1.6": - version: 1.1.6 - resolution: "@csstools/postcss-media-minmax@npm:1.1.6" +"@csstools/postcss-media-minmax@npm:^1.1.8": + version: 1.1.8 + resolution: "@csstools/postcss-media-minmax@npm:1.1.8" dependencies: - "@csstools/css-calc": "npm:^1.2.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - "@csstools/media-query-list-parser": "npm:^2.1.11" + "@csstools/css-calc": "npm:^1.2.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/media-query-list-parser": "npm:^2.1.13" peerDependencies: postcss: ^8.4 - checksum: 10c0/2cbfb3728a232c655d82f63d5ac7da36876d14e5fee5d62a0738efed40c58f20ef11f600395ade24d5063d750e8e093251dd93cc361f782b5a6c0e0f80288f51 + checksum: 10c0/7d666905282c7a89387dbce84f3429bad04870e0de264c5b1ce3e6f042b8eb72d585a18b2d7ac5e1a8c7f6785892da3cc7f6ea0b48069b06e9d383bdbc149b4a languageName: node linkType: hard -"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^2.0.9": - version: 2.0.9 - resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:2.0.9" +"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^2.0.11": + version: 2.0.11 + resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:2.0.11" dependencies: - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - "@csstools/media-query-list-parser": "npm:^2.1.11" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/media-query-list-parser": "npm:^2.1.13" peerDependencies: postcss: ^8.4 - checksum: 10c0/d431d2900a7177c938d9dc2d5bdf3c1930758adc214cc72f94b34e6bbd02fd917c200dc81482db515519c97d4f1e766ba3200f3ec9b55081887f2f8111f68e20 + checksum: 10c0/b4023a1951b7661196332852ce714a4e2fb4f1a67164ec0944e28a009b389e59c67e9de790920fcd082b122276414dd39c12ae12a4566e59e1bbcc794560a870 languageName: node linkType: hard @@ -1690,44 +1711,44 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-oklab-function@npm:^3.0.16": - version: 3.0.16 - resolution: "@csstools/postcss-oklab-function@npm:3.0.16" +"@csstools/postcss-oklab-function@npm:^3.0.19": + version: 3.0.19 + resolution: "@csstools/postcss-oklab-function@npm:3.0.19" dependencies: - "@csstools/css-color-parser": "npm:^2.0.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/9c67ee5f51116df16ab6baffa1b3c6c7aa93d53b836f421125ae8824075bd3cfaa1a93594466de0ac935c89c4fc8171e80974e1a15bafa23ea864e4cf1f1c1f2 + checksum: 10c0/2909f76ba408c9f60b61c479994c96200b0e1d3dbf524d5ae6dc5ca1e21d38caf974595e0d071c3900dbe3568376928085dd811aa24ea3e715bcd9de26fb0fa9 languageName: node linkType: hard -"@csstools/postcss-progressive-custom-properties@npm:^3.2.0": - version: 3.2.0 - resolution: "@csstools/postcss-progressive-custom-properties@npm:3.2.0" +"@csstools/postcss-progressive-custom-properties@npm:^3.3.0": + version: 3.3.0 + resolution: "@csstools/postcss-progressive-custom-properties@npm:3.3.0" dependencies: postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/829880844fbbeef1c67e0b380057e574659b4caed38c8414c17d7eb4a0cc727afa1cd74a889bc7ca79c819ecae757810356706901cf6bb677a36ca123915cbb7 + checksum: 10c0/6c9987d65049a70b5090dcfe42fde9ab2b3cb88911a81bb6651ed81c8baf99502ff2cbec0cb3e022426fa994b558b4bf33fd791ccdcdf683dde75b4865d34f39 languageName: node linkType: hard -"@csstools/postcss-relative-color-syntax@npm:^2.0.16": - version: 2.0.16 - resolution: "@csstools/postcss-relative-color-syntax@npm:2.0.16" +"@csstools/postcss-relative-color-syntax@npm:^2.0.19": + version: 2.0.19 + resolution: "@csstools/postcss-relative-color-syntax@npm:2.0.19" dependencies: - "@csstools/css-color-parser": "npm:^2.0.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/cdc965706212dcbc03394f55c79a0ad043d1e0174059c4d0d90e4267fe8e6fd9eef7cfed4f5bbc1f8e89c225c1c042ae792e115bba198eb2daae763d65f44679 + checksum: 10c0/f0aff764f4889ff664b6fa94ddfa5a22daf39354aa2d2ac0eab893eb3ed841b7d2a72131393334d6a5379445fc80f92ab5bd63d4dc3b43746bc7c9055da46591 languageName: node linkType: hard @@ -1742,41 +1763,41 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-stepped-value-functions@npm:^3.0.8": - version: 3.0.8 - resolution: "@csstools/postcss-stepped-value-functions@npm:3.0.8" +"@csstools/postcss-stepped-value-functions@npm:^3.0.10": + version: 3.0.10 + resolution: "@csstools/postcss-stepped-value-functions@npm:3.0.10" dependencies: - "@csstools/css-calc": "npm:^1.2.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" + "@csstools/css-calc": "npm:^1.2.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" peerDependencies: postcss: ^8.4 - checksum: 10c0/2be66aa769808245137be8ff14308aa17c3a0d75433f6fd6789114966a78c365dbf173d087e7ff5bc80118c75be2ff740baab83ed39fc0671980f6217779956b + checksum: 10c0/f9ebe50fb884d002aa40070196a827816f635b891fd2147ae5ddf1ad6df5bddbb50783d6786897bb3dffa33052565e38289392040cf4454aaa179ab00353117d languageName: node linkType: hard -"@csstools/postcss-text-decoration-shorthand@npm:^3.0.6": - version: 3.0.6 - resolution: "@csstools/postcss-text-decoration-shorthand@npm:3.0.6" +"@csstools/postcss-text-decoration-shorthand@npm:^3.0.7": + version: 3.0.7 + resolution: "@csstools/postcss-text-decoration-shorthand@npm:3.0.7" dependencies: - "@csstools/color-helpers": "npm:^4.2.0" + "@csstools/color-helpers": "npm:^4.2.1" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/5abdc4fad1c3f15e9d47c7af3995dec9cdf4e6f87c5857eb2e149764779b8389f4f4b21d11e6f2509c57c554a0dc5c11f68f212acd04bbc47defa15911ac3eb9 + checksum: 10c0/072b9893ca2409aa16e53e84747d7b7e13071ce19738a0800a139bf71b535e439958d9093df2b85f83eee2e0c44bc22a14bf3a39b5a7508bca9e747a12273d02 languageName: node linkType: hard -"@csstools/postcss-trigonometric-functions@npm:^3.0.8": - version: 3.0.8 - resolution: "@csstools/postcss-trigonometric-functions@npm:3.0.8" +"@csstools/postcss-trigonometric-functions@npm:^3.0.10": + version: 3.0.10 + resolution: "@csstools/postcss-trigonometric-functions@npm:3.0.10" dependencies: - "@csstools/css-calc": "npm:^1.2.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" + "@csstools/css-calc": "npm:^1.2.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" peerDependencies: postcss: ^8.4 - checksum: 10c0/aeed8d1026f4a5cb7afafbadd739af84291d5bfcbcdef2f79b77174f003d0cd0c7f9deb3fe0b9377efab37ce9bb17a2499efd4af8211f5ff9eb01b878b0b62b3 + checksum: 10c0/31adcc66510d9788ccb0669d2761517a6135b13692007d8e4334bc0e8d3515dfecfbdcd04e060d0c09a0f5fc2f12db92221b9d53e92b65b044c89cde9a3424cb languageName: node linkType: hard @@ -1798,7 +1819,7 @@ __metadata: languageName: node linkType: hard -"@csstools/selector-specificity@npm:^3.0.3, @csstools/selector-specificity@npm:^3.1.1": +"@csstools/selector-specificity@npm:^3.1.1": version: 3.1.1 resolution: "@csstools/selector-specificity@npm:3.1.1" peerDependencies: @@ -1823,10 +1844,10 @@ __metadata: languageName: node linkType: hard -"@dual-bundle/import-meta-resolve@npm:^4.0.0": - version: 4.0.0 - resolution: "@dual-bundle/import-meta-resolve@npm:4.0.0" - checksum: 10c0/868b8314fc753b7767887108535afe3288de941d92bc8453164dbcb1abe886b171e338f6f7d02ff556256dee69c90e4ac6360e0c6a856a5ad7190274ab52de2e +"@dual-bundle/import-meta-resolve@npm:^4.1.0": + version: 4.1.0 + resolution: "@dual-bundle/import-meta-resolve@npm:4.1.0" + checksum: 10c0/55069e550ee2710e738dd8bbd34aba796cede456287454b50c3be46fbef8695d00625677f3f41f5ffbec1174c0f57f314da9a908388bc9f8ad41a8438db884d9 languageName: node linkType: hard @@ -1841,10 +1862,21 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.6.1": - version: 4.10.0 - resolution: "@eslint-community/regexpp@npm:4.10.0" - checksum: 10c0/c5f60ef1f1ea7649fa7af0e80a5a79f64b55a8a8fa5086de4727eb4c86c652aedee407a9c143b8995d2c0b2d75c1222bec9ba5d73dbfc1f314550554f0979ef4 +"@eslint-community/regexpp@npm:^4.11.0": + version: 4.11.0 + resolution: "@eslint-community/regexpp@npm:4.11.0" + checksum: 10c0/0f6328869b2741e2794da4ad80beac55cba7de2d3b44f796a60955b0586212ec75e6b0253291fd4aad2100ad471d1480d8895f2b54f1605439ba4c875e05e523 + languageName: node + linkType: hard + +"@eslint/config-array@npm:^0.17.0": + version: 0.17.0 + resolution: "@eslint/config-array@npm:0.17.0" + dependencies: + "@eslint/object-schema": "npm:^2.1.4" + debug: "npm:^4.3.1" + minimatch: "npm:^3.1.2" + checksum: 10c0/97eb23ef0948dbc5f24884a3b75c537ca37ee2b1f27a864cd0d9189c089bc1a724dc6e1a4d9b7dd304d9f732ca02aa7916243a7715d6f1f17159d8a8c83f0c9e languageName: node linkType: hard @@ -1865,21 +1897,17 @@ __metadata: languageName: node linkType: hard -"@eslint/js@npm:9.3.0": - version: 9.3.0 - resolution: "@eslint/js@npm:9.3.0" - checksum: 10c0/1550c68922eb17c3ce541d9ffbb687e656bc0d4e2fff2d9cb0a75101a9cdb6184b7af7378ccf46c6ca750b280d25d45cc5e7374a83a4ee89d404d3717502fd9d +"@eslint/js@npm:9.7.0": + version: 9.7.0 + resolution: "@eslint/js@npm:9.7.0" + checksum: 10c0/73fc10666f6f4aed6f58e407e09f42ceb0d42fa60c52701c64ea9f59a81a6a8ad5caecdfd423d03088481515fe7ec17eb461acb4ef1ad70b649b6eae465b3164 languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.13.0": - version: 0.13.0 - resolution: "@humanwhocodes/config-array@npm:0.13.0" - dependencies: - "@humanwhocodes/object-schema": "npm:^2.0.3" - debug: "npm:^4.3.1" - minimatch: "npm:^3.0.5" - checksum: 10c0/205c99e756b759f92e1f44a3dc6292b37db199beacba8f26c2165d4051fe73a4ae52fdcfd08ffa93e7e5cb63da7c88648f0e84e197d154bbbbe137b2e0dd332e +"@eslint/object-schema@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/object-schema@npm:2.1.4" + checksum: 10c0/e9885532ea70e483fb007bf1275968b05bb15ebaa506d98560c41a41220d33d342e19023d5f2939fed6eb59676c1bda5c847c284b4b55fce521d282004da4dda languageName: node linkType: hard @@ -1890,13 +1918,6 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^2.0.3": - version: 2.0.3 - resolution: "@humanwhocodes/object-schema@npm:2.0.3" - checksum: 10c0/80520eabbfc2d32fe195a93557cef50dfe8c8905de447f022675aaf66abc33ae54098f5ea78548d925aa671cd4ab7c7daa5ad704fe42358c9b5e7db60f80696c - languageName: node - linkType: hard - "@humanwhocodes/retry@npm:^0.3.0": version: 0.3.0 resolution: "@humanwhocodes/retry@npm:0.3.0" @@ -2420,12 +2441,12 @@ __metadata: languageName: node linkType: hard -"acorn-import-assertions@npm:^1.9.0": - version: 1.9.0 - resolution: "acorn-import-assertions@npm:1.9.0" +"acorn-import-attributes@npm:^1.9.5": + version: 1.9.5 + resolution: "acorn-import-attributes@npm:1.9.5" peerDependencies: acorn: ^8 - checksum: 10c0/3b4a194e128efdc9b86c2b1544f623aba4c1aa70d638f8ab7dc3971a5b4aa4c57bd62f99af6e5325bb5973c55863b4112e708a6f408bad7a138647ca72283afe + checksum: 10c0/5926eaaead2326d5a86f322ff1b617b0f698aa61dc719a5baa0e9d955c9885cc71febac3fb5bacff71bbf2c4f9c12db2056883c68c53eb962c048b952e1e013d languageName: node linkType: hard @@ -2438,12 +2459,12 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.11.3, acorn@npm:^8.7.1, acorn@npm:^8.8.2": - version: 8.11.3 - resolution: "acorn@npm:8.11.3" +"acorn@npm:^8.12.0, acorn@npm:^8.7.1, acorn@npm:^8.8.2": + version: 8.12.0 + resolution: "acorn@npm:8.12.0" bin: acorn: bin/acorn - checksum: 10c0/3ff155f8812e4a746fee8ecff1f227d527c4c45655bb1fad6347c3cb58e46190598217551b1500f18542d2bbe5c87120cb6927f5a074a59166fbdd9468f0a299 + checksum: 10c0/a19f9dead009d3b430fa3c253710b47778cdaace15b316de6de93a68c355507bc1072a9956372b6c990cbeeb167d4a929249d0faeb8ae4bb6911d68d53299549 languageName: node linkType: hard @@ -2754,26 +2775,26 @@ __metadata: languageName: node linkType: hard -"braces@npm:^3.0.2, braces@npm:~3.0.2": - version: 3.0.2 - resolution: "braces@npm:3.0.2" +"braces@npm:^3.0.3, braces@npm:~3.0.2": + version: 3.0.3 + resolution: "braces@npm:3.0.3" dependencies: - fill-range: "npm:^7.0.1" - checksum: 10c0/321b4d675791479293264019156ca322163f02dc06e3c4cab33bb15cd43d80b51efef69b0930cfde3acd63d126ebca24cd0544fa6f261e093a0fb41ab9dda381 + fill-range: "npm:^7.1.1" + checksum: 10c0/7c6dfd30c338d2997ba77500539227b9d1f85e388a5f43220865201e407e076783d0881f2d297b9f80951b4c957fcf0b51c1d2d24227631643c3f7c284b0aa04 languageName: node linkType: hard -"browserslist@npm:^4.0.0, browserslist@npm:^4.21.10, browserslist@npm:^4.22.2, browserslist@npm:^4.22.3, browserslist@npm:^4.23.0": - version: 4.23.0 - resolution: "browserslist@npm:4.23.0" +"browserslist@npm:^4.0.0, browserslist@npm:^4.21.10, browserslist@npm:^4.23.0, browserslist@npm:^4.23.1": + version: 4.23.1 + resolution: "browserslist@npm:4.23.1" dependencies: - caniuse-lite: "npm:^1.0.30001587" - electron-to-chromium: "npm:^1.4.668" + caniuse-lite: "npm:^1.0.30001629" + electron-to-chromium: "npm:^1.4.796" node-releases: "npm:^2.0.14" - update-browserslist-db: "npm:^1.0.13" + update-browserslist-db: "npm:^1.0.16" bin: browserslist: cli.js - checksum: 10c0/8e9cc154529062128d02a7af4d8adeead83ca1df8cd9ee65a88e2161039f3d68a4d40fea7353cab6bae4c16182dec2fdd9a1cf7dc2a2935498cee1af0e998943 + checksum: 10c0/eb47c7ab9d60db25ce2faca70efeb278faa7282a2f62b7f2fa2f92e5f5251cf65144244566c86559419ff4f6d78f59ea50e39911321ad91f3b27788901f1f5e9 languageName: node linkType: hard @@ -2823,10 +2844,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001587, caniuse-lite@npm:^1.0.30001599": - version: 1.0.30001605 - resolution: "caniuse-lite@npm:1.0.30001605" - checksum: 10c0/ceb96a0ecfdaee6510c00aebaaa63db20aaeafab03450d4e3b214e009cb632f87385a70c299cdd1ca4c17e1473883d8fa2051c5b2d083a454338c0c779b25cbc +"caniuse-lite@npm:^1.0.0, caniuse-lite@npm:^1.0.30001599, caniuse-lite@npm:^1.0.30001629": + version: 1.0.30001639 + resolution: "caniuse-lite@npm:1.0.30001639" + checksum: 10c0/3f56ce3d516a4fba959ad10ed6ecb15c6329233fc01f9f2714234a2ca91f408296d708a366ece510ca6566f71cb80d20d4c019441a1451ac1456e0128c8de78a languageName: node linkType: hard @@ -2980,10 +3001,10 @@ __metadata: languageName: node linkType: hard -"commander@npm:^4.0.1": - version: 4.1.1 - resolution: "commander@npm:4.1.1" - checksum: 10c0/84a76c08fe6cc08c9c93f62ac573d2907d8e79138999312c92d4155bc2325d487d64d13f669b2000c9f8caf70493c1be2dac74fec3c51d5a04f8bc3ae1830bab +"commander@npm:^6.2.0": + version: 6.2.1 + resolution: "commander@npm:6.2.1" + checksum: 10c0/85748abd9d18c8bc88febed58b98f66b7c591d9b5017cad459565761d7b29ca13b7783ea2ee5ce84bf235897333706c4ce29adf1ce15c8252780e7000e2ce9ea languageName: node linkType: hard @@ -3015,12 +3036,12 @@ __metadata: languageName: node linkType: hard -"core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.36.1": - version: 3.36.1 - resolution: "core-js-compat@npm:3.36.1" +"core-js-compat@npm:^3.36.1, core-js-compat@npm:^3.37.1": + version: 3.37.1 + resolution: "core-js-compat@npm:3.37.1" dependencies: browserslist: "npm:^4.23.0" - checksum: 10c0/70fba18a4095cd8ac04e5ba8cee251e328935859cf2851c1f67770068ea9f9fe71accb1b7de17cd3c9a28d304a4c41712bd9aa895110ebb6e3be71b666b029d1 + checksum: 10c0/4e2da9c900f2951a57947af7aeef4d16f2c75d7f7e966c0d0b62953f65225003ade5e84d3ae98847f65b24c109c606821d9dc925db8ca418fb761e7c81963c2a languageName: node linkType: hard @@ -3194,10 +3215,10 @@ __metadata: languageName: node linkType: hard -"cssdb@npm:^8.0.0": - version: 8.0.0 - resolution: "cssdb@npm:8.0.0" - checksum: 10c0/d9a31b760214624352000b16a8f7194c357f66b6c445e663ab58dd03b6f0f53efaaca6d6f96200d666e205894d2d1c346664ad993d9522ff9fc1c331804a8d62 +"cssdb@npm:^8.1.0": + version: 8.1.0 + resolution: "cssdb@npm:8.1.0" + checksum: 10c0/1fa1f1566c7e9964f5c71e443583eaba16a90933a3ef6803815c4281d084b75da948c415bade33d7085894fe0929c082fcb3135bf4400048cfff40d227ebd5dd languageName: node linkType: hard @@ -3280,15 +3301,15 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4": - version: 4.3.4 - resolution: "debug@npm:4.3.4" +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.5": + version: 4.3.5 + resolution: "debug@npm:4.3.5" dependencies: ms: "npm:2.1.2" peerDependenciesMeta: supports-color: optional: true - checksum: 10c0/cedbec45298dd5c501d01b92b119cd3faebe5438c3917ff11ae1bff86a6c722930ac9c8659792824013168ba6db7c4668225d845c633fbdafbbf902a6389f736 + checksum: 10c0/082c375a2bdc4f4469c99f325ff458adad62a3fc2c482d59923c260cb08152f34e2659f72b3767db8bb2f21ca81a60a42d1019605a412132d7b9f59363a005cc languageName: node linkType: hard @@ -3368,10 +3389,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.668": - version: 1.4.680 - resolution: "electron-to-chromium@npm:1.4.680" - checksum: 10c0/f5877042ee84fce419b1c475ca1f75d1c19c0ecf358572635dffed97d8591a25c169ee1b5abfb8a14d741c699fcc4a92b1ef1f771fbd7887f3a18499a8eaf260 +"electron-to-chromium@npm:^1.4.796": + version: 1.4.816 + resolution: "electron-to-chromium@npm:1.4.816" + checksum: 10c0/1a84bc42234484cbc5e8b521de57fd3ab9984a2111d8605eab26b3525f382c0c7b83b45bf8b34e5fa4a730cd183fef5dffa4a0627754c7f4fb0aae9cb3c16b37 languageName: node linkType: hard @@ -3405,13 +3426,13 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.16.0": - version: 5.16.0 - resolution: "enhanced-resolve@npm:5.16.0" +"enhanced-resolve@npm:^5.17.0": + version: 5.17.0 + resolution: "enhanced-resolve@npm:5.17.0" dependencies: graceful-fs: "npm:^4.2.4" tapable: "npm:^2.2.0" - checksum: 10c0/dd69669cbb638ccacefd03e04d5e195ee6a99b7f5f8012f86d2df7781834de357923e06064ea621137c4ce0b37cc12b872b4e6d1ac6ab15fe98e7f1dfbbb08c4 + checksum: 10c0/90065e58e4fd08e77ba47f827eaa17d60c335e01e4859f6e644bb3b8d0e32b203d33894aee92adfa5121fa262f912b48bdf0d0475e98b4a0a1132eea1169ad37 languageName: node linkType: hard @@ -3461,10 +3482,10 @@ __metadata: languageName: node linkType: hard -"escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: 10c0/afd02e6ca91ffa813e1108b5e7756566173d6bc0d1eb951cb44d6b21702ec17c1cf116cfe75d4a2b02e05acb0b808a7a9387d0d1ca5cf9c04ad03a8445c3e46d +"escalade@npm:^3.1.2": + version: 3.1.2 + resolution: "escalade@npm:3.1.2" + checksum: 10c0/6b4adafecd0682f3aa1cd1106b8fff30e492c7015b178bc81b2d2f75106dabea6c6d6e8508fc491bd58e597c74abb0e8e2368f943ecb9393d4162e3c2f3cf287 languageName: node linkType: hard @@ -3510,13 +3531,13 @@ __metadata: languageName: node linkType: hard -"eslint-scope@npm:^8.0.1": - version: 8.0.1 - resolution: "eslint-scope@npm:8.0.1" +"eslint-scope@npm:^8.0.2": + version: 8.0.2 + resolution: "eslint-scope@npm:8.0.2" dependencies: esrecurse: "npm:^4.3.0" estraverse: "npm:^5.2.0" - checksum: 10c0/0ec40ab284e58ac7ef064ecd23c127e03d339fa57173c96852336c73afc70ce5631da21dc1c772415a37a421291845538dd69db83c68d611044c0fde1d1fa269 + checksum: 10c0/477f820647c8755229da913025b4567347fd1f0bf7cbdf3a256efff26a7e2e130433df052bd9e3d014025423dc00489bea47eb341002b15553673379c1a7dc36 languageName: node linkType: hard @@ -3534,15 +3555,15 @@ __metadata: languageName: node linkType: hard -"eslint@npm:9.3.0": - version: 9.3.0 - resolution: "eslint@npm:9.3.0" +"eslint@npm:9.7.0": + version: 9.7.0 + resolution: "eslint@npm:9.7.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" - "@eslint-community/regexpp": "npm:^4.6.1" + "@eslint-community/regexpp": "npm:^4.11.0" + "@eslint/config-array": "npm:^0.17.0" "@eslint/eslintrc": "npm:^3.1.0" - "@eslint/js": "npm:9.3.0" - "@humanwhocodes/config-array": "npm:^0.13.0" + "@eslint/js": "npm:9.7.0" "@humanwhocodes/module-importer": "npm:^1.0.1" "@humanwhocodes/retry": "npm:^0.3.0" "@nodelib/fs.walk": "npm:^1.2.8" @@ -3551,10 +3572,10 @@ __metadata: cross-spawn: "npm:^7.0.2" debug: "npm:^4.3.2" escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^8.0.1" + eslint-scope: "npm:^8.0.2" eslint-visitor-keys: "npm:^4.0.0" - espree: "npm:^10.0.1" - esquery: "npm:^1.4.2" + espree: "npm:^10.1.0" + esquery: "npm:^1.5.0" esutils: "npm:^2.0.2" fast-deep-equal: "npm:^3.1.3" file-entry-cache: "npm:^8.0.0" @@ -3574,18 +3595,18 @@ __metadata: text-table: "npm:^0.2.0" bin: eslint: bin/eslint.js - checksum: 10c0/d0cf1923408ce720f2fa0dde39094dbee6b03a71d5e6466402bbeb29c08a618713f7a1e8cfc4b4d50dbe3750ce68adf614a0e973dea6fa36ddc428dfb89d4cac + checksum: 10c0/e2369a9534404f62f37ee5560e56fb84e0776a9c8f084550170017992772e7034d73571bdf4060e2fe9b836f136d45b07d50407d4b9361de720ee77794259274 languageName: node linkType: hard -"espree@npm:^10.0.1": - version: 10.0.1 - resolution: "espree@npm:10.0.1" +"espree@npm:^10.0.1, espree@npm:^10.1.0": + version: 10.1.0 + resolution: "espree@npm:10.1.0" dependencies: - acorn: "npm:^8.11.3" + acorn: "npm:^8.12.0" acorn-jsx: "npm:^5.3.2" eslint-visitor-keys: "npm:^4.0.0" - checksum: 10c0/7c0f84afa0f9db7bb899619e6364ed832ef13fe8943691757ddde9a1805ae68b826ed66803323015f707a629a5507d0d290edda2276c25131fe0ad883b8b5636 + checksum: 10c0/52e6feaa77a31a6038f0c0e3fce93010a4625701925b0715cd54a2ae190b3275053a0717db698697b32653788ac04845e489d6773b508d6c2e8752f3c57470a0 languageName: node linkType: hard @@ -3599,7 +3620,7 @@ __metadata: languageName: node linkType: hard -"esquery@npm:^1.4.2": +"esquery@npm:^1.5.0": version: 1.5.0 resolution: "esquery@npm:1.5.0" dependencies: @@ -3718,12 +3739,21 @@ __metadata: languageName: node linkType: hard -"fill-range@npm:^7.0.1": - version: 7.0.1 - resolution: "fill-range@npm:7.0.1" +"file-entry-cache@npm:^9.0.0": + version: 9.0.0 + resolution: "file-entry-cache@npm:9.0.0" + dependencies: + flat-cache: "npm:^5.0.0" + checksum: 10c0/07b0a4f062dc0aa258f3e1b06ac083ea25313f5e289943e146fafdaf3315dcc031635545eea7fe98fe5598b91d6c7f48dba7a251dd7ac20108a6ebf7d00b0b1c + languageName: node + linkType: hard + +"fill-range@npm:^7.1.1": + version: 7.1.1 + resolution: "fill-range@npm:7.1.1" dependencies: to-regex-range: "npm:^5.0.1" - checksum: 10c0/7cdad7d426ffbaadf45aeb5d15ec675bbd77f7597ad5399e3d2766987ed20bda24d5fac64b3ee79d93276f5865608bb22344a26b9b1ae6c4d00bd94bf611623f + checksum: 10c0/b75b691bbe065472f38824f694c2f7449d7f5004aa950426a2c28f0306c60db9b880c0b0e4ed819997ffb882d1da02cfcfc819bddc94d71627f5269682edf018 languageName: node linkType: hard @@ -3778,6 +3808,16 @@ __metadata: languageName: node linkType: hard +"flat-cache@npm:^5.0.0": + version: 5.0.0 + resolution: "flat-cache@npm:5.0.0" + dependencies: + flatted: "npm:^3.3.1" + keyv: "npm:^4.5.4" + checksum: 10c0/847f25eefec5d6614fdce76dc6097ee98f63fd4dfbcb908718905ac56610f939f4c28b1f908d6e8857d49286fe73235095d2e7ac9df096c35a3e8a15204c361b + languageName: node + linkType: hard + "flat@npm:^5.0.2": version: 5.0.2 resolution: "flat@npm:5.0.2" @@ -3787,10 +3827,10 @@ __metadata: languageName: node linkType: hard -"flatted@npm:^3.2.9": - version: 3.2.9 - resolution: "flatted@npm:3.2.9" - checksum: 10c0/5c91c5a0a21bbc0b07b272231e5b4efe6b822bcb4ad317caf6bb06984be4042a9e9045026307da0fdb4583f1f545e317a67ef1231a59e71f7fced3cc429cfc53 +"flatted@npm:^3.2.9, flatted@npm:^3.3.1": + version: 3.3.1 + resolution: "flatted@npm:3.3.1" + checksum: 10c0/324166b125ee07d4ca9bcf3a5f98d915d5db4f39d711fba640a3178b959919aae1f7cfd8aabcfef5826ed8aa8a2aa14cc85b2d7d18ff638ddf4ae3df39573eaf languageName: node linkType: hard @@ -3957,10 +3997,10 @@ __metadata: languageName: node linkType: hard -"globals@npm:15.3.0": - version: 15.3.0 - resolution: "globals@npm:15.3.0" - checksum: 10c0/edbef1c528185d02636ed6d72a1688168b922d6176031904386214f8b59d893f1d0a28da519b95665f557d366b17ea1affb9f433ea451e7372e2808fb31079d7 +"globals@npm:15.8.0": + version: 15.8.0 + resolution: "globals@npm:15.8.0" + checksum: 10c0/b96ec86e1244806920a80a1a7c4d64b68c55336887cfa1b52886927e0f9035133e4acd354fcda63b49e53df2089c41a11dd2b02281a6439a58cbc0d63ae083cb languageName: node linkType: hard @@ -4369,38 +4409,38 @@ __metadata: version: 0.0.0-use.local resolution: "jenkins-ui@workspace:." dependencies: - "@babel/cli": "npm:7.24.5" - "@babel/core": "npm:7.24.5" - "@babel/preset-env": "npm:7.24.5" - "@eslint/js": "npm:9.3.0" + "@babel/cli": "npm:7.24.8" + "@babel/core": "npm:7.24.9" + "@babel/preset-env": "npm:7.24.8" + "@eslint/js": "npm:9.7.0" babel-loader: "npm:9.1.3" clean-webpack-plugin: "npm:4.0.0" css-loader: "npm:7.1.2" css-minimizer-webpack-plugin: "npm:7.0.0" - eslint: "npm:9.3.0" + eslint: "npm:9.7.0" eslint-config-prettier: "npm:9.1.0" eslint-formatter-checkstyle: "npm:8.40.0" - globals: "npm:15.3.0" + globals: "npm:15.8.0" handlebars: "npm:4.7.8" handlebars-loader: "npm:1.7.3" hotkeys-js: "npm:3.12.2" jquery: "npm:3.7.1" lodash: "npm:4.17.21" mini-css-extract-plugin: "npm:2.9.0" - postcss: "npm:8.4.38" + postcss: "npm:8.4.39" postcss-loader: "npm:8.1.1" - postcss-preset-env: "npm:9.5.14" + postcss-preset-env: "npm:9.6.0" postcss-scss: "npm:4.0.9" - prettier: "npm:3.2.5" - sass: "npm:1.77.2" - sass-loader: "npm:14.2.1" + prettier: "npm:3.3.3" + sass: "npm:1.77.8" + sass-loader: "npm:15.0.0" sortablejs: "npm:1.15.2" style-loader: "npm:4.0.0" - stylelint: "npm:16.5.0" + stylelint: "npm:16.7.0" stylelint-checkstyle-reporter: "npm:1.0.0" - stylelint-config-standard: "npm:36.0.0" + stylelint-config-standard: "npm:36.0.1" tippy.js: "npm:6.3.7" - webpack: "npm:5.91.0" + webpack: "npm:5.93.0" webpack-cli: "npm:5.1.4" webpack-remove-empty-scripts: "npm:1.0.4" window-handle: "npm:1.0.1" @@ -4579,10 +4619,10 @@ __metadata: languageName: node linkType: hard -"known-css-properties@npm:^0.30.0": - version: 0.30.0 - resolution: "known-css-properties@npm:0.30.0" - checksum: 10c0/8b487a6b33487affcec41eb392ceb77acf4d093558dde5c88b5ea06b9a3c81781876d7cb09872e0518b9602f27c8f4112c9ac333e02c90a91c8fbd12e202ed48 +"known-css-properties@npm:^0.34.0": + version: 0.34.0 + resolution: "known-css-properties@npm:0.34.0" + checksum: 10c0/8549969f02b1858554e89faf4548ece37625d0d21b42e8d54fa53184e68e1512ef2531bb15941575ad816361ab7447b598c1b18c1b96ce0a868333d1a68f2e2c languageName: node linkType: hard @@ -4793,13 +4833,13 @@ __metadata: languageName: node linkType: hard -"micromatch@npm:^4.0.4, micromatch@npm:^4.0.5": - version: 4.0.5 - resolution: "micromatch@npm:4.0.5" +"micromatch@npm:^4.0.4, micromatch@npm:^4.0.7": + version: 4.0.7 + resolution: "micromatch@npm:4.0.7" dependencies: - braces: "npm:^3.0.2" + braces: "npm:^3.0.3" picomatch: "npm:^2.3.1" - checksum: 10c0/3d6505b20f9fa804af5d8c596cb1c5e475b9b0cd05f652c5b56141cf941bd72adaeb7a436fda344235cef93a7f29b7472efc779fcdb83b478eab0867b95cdeff + checksum: 10c0/58fa99bc5265edec206e9163a1d2cec5fabc46a5b473c45f4a700adce88c2520456ae35f2b301e4410fb3afb27e9521fb2813f6fc96be0a48a89430e0916a772 languageName: node linkType: hard @@ -4831,7 +4871,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": +"minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -5234,10 +5274,10 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: 10c0/20a5b249e331c14479d94ec6817a182fd7a5680debae82705747b2db7ec50009a5f6648d0621c561b0572703f84dbef0858abcbd5856d3c5511426afcb1961f7 +"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1": + version: 1.0.1 + resolution: "picocolors@npm:1.0.1" + checksum: 10c0/c63cdad2bf812ef0d66c8db29583802355d4ca67b9285d846f390cc15c2f6ccb94e8cb7eb6a6e97fc5990a6d3ad4ae42d86c84d3146e667c739a4234ed50d400 languageName: node linkType: hard @@ -5330,18 +5370,18 @@ __metadata: languageName: node linkType: hard -"postcss-color-functional-notation@npm:^6.0.11": - version: 6.0.11 - resolution: "postcss-color-functional-notation@npm:6.0.11" +"postcss-color-functional-notation@npm:^6.0.14": + version: 6.0.14 + resolution: "postcss-color-functional-notation@npm:6.0.14" dependencies: - "@csstools/css-color-parser": "npm:^2.0.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/7fd75e6881cf62f536f79dfc0ae1b709ea0b8b84833cce1671372711f6019ab4360c6a17089b654b2d376b87e7f9455b94f0d13b45ab0ab767e547b604709b3d + checksum: 10c0/fdc5188e19c3923da32fe08d50e55d0b3ca1cedf99f46331baa0a4bbd73a1fc6b4447b0346ab16049032b56ab84b98b4758a0ede7c237637e35a4cc60caac141 languageName: node linkType: hard @@ -5395,46 +5435,46 @@ __metadata: languageName: node linkType: hard -"postcss-custom-media@npm:^10.0.6": - version: 10.0.6 - resolution: "postcss-custom-media@npm:10.0.6" +"postcss-custom-media@npm:^10.0.8": + version: 10.0.8 + resolution: "postcss-custom-media@npm:10.0.8" dependencies: - "@csstools/cascade-layer-name-parser": "npm:^1.0.11" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - "@csstools/media-query-list-parser": "npm:^2.1.11" + "@csstools/cascade-layer-name-parser": "npm:^1.0.13" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/media-query-list-parser": "npm:^2.1.13" peerDependencies: postcss: ^8.4 - checksum: 10c0/98a524bc46b780a86094bbe8007f1e577137da5490823631a683d4b3df4a13e40c5e1ab52380275a54f7011abfd98bb597c6293d964c14f9f22ec6cf9d75c550 + checksum: 10c0/673ca0058a2f2357a83b33ce00bbeee7cda92621c08472fa55d7ac7ae56f5f8f979132528d537f2dedf715d35a8f9b14b2f0ab6b45423d49e2554c19aab3c827 languageName: node linkType: hard -"postcss-custom-properties@npm:^13.3.10": - version: 13.3.10 - resolution: "postcss-custom-properties@npm:13.3.10" +"postcss-custom-properties@npm:^13.3.12": + version: 13.3.12 + resolution: "postcss-custom-properties@npm:13.3.12" dependencies: - "@csstools/cascade-layer-name-parser": "npm:^1.0.11" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" + "@csstools/cascade-layer-name-parser": "npm:^1.0.13" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" "@csstools/utilities": "npm:^1.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/52688fd0aaadccfdf4a3d86d3a2ab988163e8108088c5e33fc9145d261f75b92b8321c044a8161345abda10df5715d674330309dcc0c17f2980db5515f6a76d6 + checksum: 10c0/6af9f6ac94a6ac887749cd38d4586349f6aca29269ebfdb837019a3ba0130032f0ff4899b431b5c348f4ac79a7b16fb7300a256514a6a68e32a63489c18a70e7 languageName: node linkType: hard -"postcss-custom-selectors@npm:^7.1.10": - version: 7.1.10 - resolution: "postcss-custom-selectors@npm:7.1.10" +"postcss-custom-selectors@npm:^7.1.12": + version: 7.1.12 + resolution: "postcss-custom-selectors@npm:7.1.12" dependencies: - "@csstools/cascade-layer-name-parser": "npm:^1.0.11" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - postcss-selector-parser: "npm:^6.0.13" + "@csstools/cascade-layer-name-parser": "npm:^1.0.13" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + postcss-selector-parser: "npm:^6.1.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/11311ae6f306420223c6bf926fb1798738f3aa525a267de204de8e8ee9de467bf63b580d9ad5dbb0fff4bd9266770a3fa7e27a24af08a2e0a4115d0727d1d043 + checksum: 10c0/78a7930e4f97c42b544f00c06272264432d47f9df777684b57673bb971b7ab49d5d6fb9289a5a869125e7e50dcd0cad65cf8846501253084b73a42ffab41b2c5 languageName: node linkType: hard @@ -5485,16 +5525,16 @@ __metadata: languageName: node linkType: hard -"postcss-double-position-gradients@npm:^5.0.6": - version: 5.0.6 - resolution: "postcss-double-position-gradients@npm:5.0.6" +"postcss-double-position-gradients@npm:^5.0.7": + version: 5.0.7 + resolution: "postcss-double-position-gradients@npm:5.0.7" dependencies: - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/9b24b13043fe506c0ddd94e707fe4f21f4f9a6c05ca49a4f45e23412951fd6a4cfa0095002d10b322ca8be60df0badae3715a27eefdeb7bf8da4fdd1ecd5d7a2 + checksum: 10c0/52d96a34aa3e2e251edeaa2d4c2dd106c687f7910ec18266693656c0edd003384b927c855cecac07f52b5c7bdccd140abdc7e27082ce4c3755e3a966206a2cb9 languageName: node linkType: hard @@ -5550,18 +5590,18 @@ __metadata: languageName: node linkType: hard -"postcss-lab-function@npm:^6.0.16": - version: 6.0.16 - resolution: "postcss-lab-function@npm:6.0.16" +"postcss-lab-function@npm:^6.0.19": + version: 6.0.19 + resolution: "postcss-lab-function@npm:6.0.19" dependencies: - "@csstools/css-color-parser": "npm:^2.0.2" - "@csstools/css-parser-algorithms": "npm:^2.6.3" - "@csstools/css-tokenizer": "npm:^2.3.1" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" + "@csstools/css-color-parser": "npm:^2.0.4" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" "@csstools/utilities": "npm:^1.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/ba8717cd8a197ec17acaac1b61631cd4403f07bd406b0c92f2e430a55e3f786cd6c338b626c3326e9178a0f3e58ff838ebaded19f480f39197a9cb17349ecdcd + checksum: 10c0/d9a91fb57dcbe967260df86e22ca335a5444f1f34d128fa7b5dbf2522772f2138ad708f1f20f0a59035d66ed736e82972ca7f1b669a157534a17ee8898af1921 languageName: node linkType: hard @@ -5877,61 +5917,62 @@ __metadata: languageName: node linkType: hard -"postcss-preset-env@npm:9.5.14": - version: 9.5.14 - resolution: "postcss-preset-env@npm:9.5.14" +"postcss-preset-env@npm:9.6.0": + version: 9.6.0 + resolution: "postcss-preset-env@npm:9.6.0" dependencies: "@csstools/postcss-cascade-layers": "npm:^4.0.6" - "@csstools/postcss-color-function": "npm:^3.0.16" - "@csstools/postcss-color-mix-function": "npm:^2.0.16" - "@csstools/postcss-exponential-functions": "npm:^1.0.7" + "@csstools/postcss-color-function": "npm:^3.0.19" + "@csstools/postcss-color-mix-function": "npm:^2.0.19" + "@csstools/postcss-content-alt-text": "npm:^1.0.0" + "@csstools/postcss-exponential-functions": "npm:^1.0.9" "@csstools/postcss-font-format-keywords": "npm:^3.0.2" - "@csstools/postcss-gamut-mapping": "npm:^1.0.9" - "@csstools/postcss-gradients-interpolation-method": "npm:^4.0.17" - "@csstools/postcss-hwb-function": "npm:^3.0.15" - "@csstools/postcss-ic-unit": "npm:^3.0.6" + "@csstools/postcss-gamut-mapping": "npm:^1.0.11" + "@csstools/postcss-gradients-interpolation-method": "npm:^4.0.20" + "@csstools/postcss-hwb-function": "npm:^3.0.18" + "@csstools/postcss-ic-unit": "npm:^3.0.7" "@csstools/postcss-initial": "npm:^1.0.1" "@csstools/postcss-is-pseudo-class": "npm:^4.0.8" - "@csstools/postcss-light-dark-function": "npm:^1.0.5" + "@csstools/postcss-light-dark-function": "npm:^1.0.8" "@csstools/postcss-logical-float-and-clear": "npm:^2.0.1" "@csstools/postcss-logical-overflow": "npm:^1.0.1" "@csstools/postcss-logical-overscroll-behavior": "npm:^1.0.1" "@csstools/postcss-logical-resize": "npm:^2.0.1" - "@csstools/postcss-logical-viewport-units": "npm:^2.0.9" - "@csstools/postcss-media-minmax": "npm:^1.1.6" - "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^2.0.9" + "@csstools/postcss-logical-viewport-units": "npm:^2.0.11" + "@csstools/postcss-media-minmax": "npm:^1.1.8" + "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^2.0.11" "@csstools/postcss-nested-calc": "npm:^3.0.2" "@csstools/postcss-normalize-display-values": "npm:^3.0.2" - "@csstools/postcss-oklab-function": "npm:^3.0.16" - "@csstools/postcss-progressive-custom-properties": "npm:^3.2.0" - "@csstools/postcss-relative-color-syntax": "npm:^2.0.16" + "@csstools/postcss-oklab-function": "npm:^3.0.19" + "@csstools/postcss-progressive-custom-properties": "npm:^3.3.0" + "@csstools/postcss-relative-color-syntax": "npm:^2.0.19" "@csstools/postcss-scope-pseudo-class": "npm:^3.0.1" - "@csstools/postcss-stepped-value-functions": "npm:^3.0.8" - "@csstools/postcss-text-decoration-shorthand": "npm:^3.0.6" - "@csstools/postcss-trigonometric-functions": "npm:^3.0.8" + "@csstools/postcss-stepped-value-functions": "npm:^3.0.10" + "@csstools/postcss-text-decoration-shorthand": "npm:^3.0.7" + "@csstools/postcss-trigonometric-functions": "npm:^3.0.10" "@csstools/postcss-unset-value": "npm:^3.0.1" autoprefixer: "npm:^10.4.19" - browserslist: "npm:^4.22.3" + browserslist: "npm:^4.23.1" css-blank-pseudo: "npm:^6.0.2" css-has-pseudo: "npm:^6.0.5" css-prefers-color-scheme: "npm:^9.0.1" - cssdb: "npm:^8.0.0" + cssdb: "npm:^8.1.0" postcss-attribute-case-insensitive: "npm:^6.0.3" postcss-clamp: "npm:^4.1.0" - postcss-color-functional-notation: "npm:^6.0.11" + postcss-color-functional-notation: "npm:^6.0.14" postcss-color-hex-alpha: "npm:^9.0.4" postcss-color-rebeccapurple: "npm:^9.0.3" - postcss-custom-media: "npm:^10.0.6" - postcss-custom-properties: "npm:^13.3.10" - postcss-custom-selectors: "npm:^7.1.10" + postcss-custom-media: "npm:^10.0.8" + postcss-custom-properties: "npm:^13.3.12" + postcss-custom-selectors: "npm:^7.1.12" postcss-dir-pseudo-class: "npm:^8.0.1" - postcss-double-position-gradients: "npm:^5.0.6" + postcss-double-position-gradients: "npm:^5.0.7" postcss-focus-visible: "npm:^9.0.1" postcss-focus-within: "npm:^8.0.1" postcss-font-variant: "npm:^5.0.0" postcss-gap-properties: "npm:^5.0.1" postcss-image-set-function: "npm:^6.0.3" - postcss-lab-function: "npm:^6.0.16" + postcss-lab-function: "npm:^6.0.19" postcss-logical: "npm:^7.0.1" postcss-nesting: "npm:^12.1.5" postcss-opacity-percentage: "npm:^2.0.0" @@ -5943,7 +5984,7 @@ __metadata: postcss-selector-not: "npm:^7.0.2" peerDependencies: postcss: ^8.4 - checksum: 10c0/8e0c8f5c2e7b8385a770c13185986dc50d7a73b10b98c65c2f86bb4cd2860de722caef8172b1676962dafbbc044d6be1955f2a092e951976a30d4ee33b0d7571 + checksum: 10c0/caa91ba4d3b897d43ab2669b3edf40b24ef32c88e23b113be8956412e64b28deed6ba229c331848fcbc0d143bfde155173fb1e1ada9ccae5037b2ee8f7e554b7 languageName: node linkType: hard @@ -6066,14 +6107,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:8.4.38, postcss@npm:^8.4.33, postcss@npm:^8.4.38": - version: 8.4.38 - resolution: "postcss@npm:8.4.38" +"postcss@npm:8.4.39, postcss@npm:^8.4.33, postcss@npm:^8.4.38, postcss@npm:^8.4.39": + version: 8.4.39 + resolution: "postcss@npm:8.4.39" dependencies: nanoid: "npm:^3.3.7" - picocolors: "npm:^1.0.0" + picocolors: "npm:^1.0.1" source-map-js: "npm:^1.2.0" - checksum: 10c0/955407b8f70cf0c14acf35dab3615899a2a60a26718a63c848cf3c29f2467b0533991b985a2b994430d890bd7ec2b1963e36352b0774a19143b5f591540f7c06 + checksum: 10c0/16f5ac3c4e32ee76d1582b3c0dcf1a1fdb91334a45ad755eeb881ccc50318fb8d64047de4f1601ac96e30061df203f0f2e2edbdc0bfc49b9c57bc9fb9bedaea3 languageName: node linkType: hard @@ -6084,12 +6125,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:3.2.5": - version: 3.2.5 - resolution: "prettier@npm:3.2.5" +"prettier@npm:3.3.3": + version: 3.3.3 + resolution: "prettier@npm:3.3.3" bin: prettier: bin/prettier.cjs - checksum: 10c0/ea327f37a7d46f2324a34ad35292af2ad4c4c3c3355da07313339d7e554320f66f65f91e856add8530157a733c6c4a897dc41b577056be5c24c40f739f5ee8c6 + checksum: 10c0/b85828b08e7505716324e4245549b9205c0cacb25342a030ba8885aba2039a115dbcf75a0b7ca3b37bc9d101ee61fab8113fc69ca3359f2a226f1ecc07ad2e26 languageName: node linkType: hard @@ -6323,9 +6364,9 @@ __metadata: languageName: node linkType: hard -"sass-loader@npm:14.2.1": - version: 14.2.1 - resolution: "sass-loader@npm:14.2.1" +"sass-loader@npm:15.0.0": + version: 15.0.0 + resolution: "sass-loader@npm:15.0.0" dependencies: neo-async: "npm:^2.6.2" peerDependencies: @@ -6345,20 +6386,20 @@ __metadata: optional: true webpack: optional: true - checksum: 10c0/9a48d454584d96d6c562eb323bb9e3c6808e930eeaaa916975b97d45831e0b87936a8655cdb3a4512a25abc9587dea65a9616e42396be0d7e7c507a4795a8146 + checksum: 10c0/8e17d21194f5806a971e98c149ac5a2387fa3b4327a81f2194253b61181c6dac965970c30e1e1b294f977e1822ff7c03feb0e26864f1f43cdea34a82caaf40af languageName: node linkType: hard -"sass@npm:1.77.2": - version: 1.77.2 - resolution: "sass@npm:1.77.2" +"sass@npm:1.77.8": + version: 1.77.8 + resolution: "sass@npm:1.77.8" dependencies: chokidar: "npm:>=3.0.0 <4.0.0" immutable: "npm:^4.0.0" source-map-js: "npm:>=0.6.2 <2.0.0" bin: sass: sass.js - checksum: 10c0/0d292339064de3c902e209d41de9c4eb2038cff326476aeebbb5be3eee1d23400d975face2b8e124ae617b10af3e93bec01580f61912f34e4c517fe137a118b6 + checksum: 10c0/2bfd62794070352c804f949e69bd8bb5b4ec846deeb924251b2c3f7b503170fb1ae186f513f0166907749eb34e0277dee747edcb78c886fb471aac01be1e864c languageName: node linkType: hard @@ -6635,44 +6676,44 @@ __metadata: languageName: node linkType: hard -"stylelint-config-recommended@npm:^14.0.0": - version: 14.0.0 - resolution: "stylelint-config-recommended@npm:14.0.0" +"stylelint-config-recommended@npm:^14.0.1": + version: 14.0.1 + resolution: "stylelint-config-recommended@npm:14.0.1" peerDependencies: - stylelint: ^16.0.0 - checksum: 10c0/4ad15c36e8c03291aa7bbe4b672ebfb0f46ab698e7580a0da8d29644046d102d7f31dbf00a2a6eab94b565c390c6fb0d5d528737b83ac3acf6dc2ef085a90b11 + stylelint: ^16.1.0 + checksum: 10c0/a0a0ecd91f4d193bbe2cc3408228f8a2d8fcb2b2578d77233f86780c9247c796a04e16aad7a91d97cb918e2de34b6a8062bab66ee017c3835d855081d94f4828 languageName: node linkType: hard -"stylelint-config-standard@npm:36.0.0": - version: 36.0.0 - resolution: "stylelint-config-standard@npm:36.0.0" +"stylelint-config-standard@npm:36.0.1": + version: 36.0.1 + resolution: "stylelint-config-standard@npm:36.0.1" dependencies: - stylelint-config-recommended: "npm:^14.0.0" + stylelint-config-recommended: "npm:^14.0.1" peerDependencies: stylelint: ^16.1.0 - checksum: 10c0/1fc9adddfc5cf0a1d7a443182a0731712a3950ace72a24081b4ede2b0bb6fc1eebd003c009f1d8d06c3a64ba9b31b0ed12512db2f91c8fa549238d8341580e4b + checksum: 10c0/7f9b954694358e77be5110418f31335be579ce59dd952bc3c6a9449265297db3170ec520e0905769253b48b99c3109a95c71f5b985bf402e48fd6c89b5364cb2 languageName: node linkType: hard -"stylelint@npm:16.5.0": - version: 16.5.0 - resolution: "stylelint@npm:16.5.0" +"stylelint@npm:16.7.0": + version: 16.7.0 + resolution: "stylelint@npm:16.7.0" dependencies: - "@csstools/css-parser-algorithms": "npm:^2.6.1" - "@csstools/css-tokenizer": "npm:^2.2.4" - "@csstools/media-query-list-parser": "npm:^2.1.9" - "@csstools/selector-specificity": "npm:^3.0.3" - "@dual-bundle/import-meta-resolve": "npm:^4.0.0" + "@csstools/css-parser-algorithms": "npm:^2.7.1" + "@csstools/css-tokenizer": "npm:^2.4.1" + "@csstools/media-query-list-parser": "npm:^2.1.13" + "@csstools/selector-specificity": "npm:^3.1.1" + "@dual-bundle/import-meta-resolve": "npm:^4.1.0" balanced-match: "npm:^2.0.0" colord: "npm:^2.9.3" cosmiconfig: "npm:^9.0.0" css-functions-list: "npm:^3.2.2" css-tree: "npm:^2.3.1" - debug: "npm:^4.3.4" + debug: "npm:^4.3.5" fast-glob: "npm:^3.3.2" fastest-levenshtein: "npm:^1.0.16" - file-entry-cache: "npm:^8.0.0" + file-entry-cache: "npm:^9.0.0" global-modules: "npm:^2.0.0" globby: "npm:^11.1.0" globjoin: "npm:^0.1.4" @@ -6680,16 +6721,16 @@ __metadata: ignore: "npm:^5.3.1" imurmurhash: "npm:^0.1.4" is-plain-object: "npm:^5.0.0" - known-css-properties: "npm:^0.30.0" + known-css-properties: "npm:^0.34.0" mathml-tag-names: "npm:^2.1.3" meow: "npm:^13.2.0" - micromatch: "npm:^4.0.5" + micromatch: "npm:^4.0.7" normalize-path: "npm:^3.0.0" - picocolors: "npm:^1.0.0" - postcss: "npm:^8.4.38" + picocolors: "npm:^1.0.1" + postcss: "npm:^8.4.39" postcss-resolve-nested-selector: "npm:^0.1.1" postcss-safe-parser: "npm:^7.0.0" - postcss-selector-parser: "npm:^6.0.16" + postcss-selector-parser: "npm:^6.1.0" postcss-value-parser: "npm:^4.2.0" resolve-from: "npm:^5.0.0" string-width: "npm:^4.2.3" @@ -6700,7 +6741,7 @@ __metadata: write-file-atomic: "npm:^5.0.1" bin: stylelint: bin/stylelint.mjs - checksum: 10c0/9281693ff6c1918e07fdcf7a950531f79678a28261a0d5bd36ca2fcf524e53d7305158d20ba890f5dd01c0ff90c09a13453dce2fe6887f4c157d8c2c0acf3666 + checksum: 10c0/98cb36037684433d991a0c507bbf8155309e96470177487f493e66de098631e5303b235470fc5c8086cd98013385b669c4e3cb68ad01421b898e1da6848e5d78 languageName: node linkType: hard @@ -6948,17 +6989,17 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.0.13": - version: 1.0.13 - resolution: "update-browserslist-db@npm:1.0.13" +"update-browserslist-db@npm:^1.0.16": + version: 1.1.0 + resolution: "update-browserslist-db@npm:1.1.0" dependencies: - escalade: "npm:^3.1.1" - picocolors: "npm:^1.0.0" + escalade: "npm:^3.1.2" + picocolors: "npm:^1.0.1" peerDependencies: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 10c0/e52b8b521c78ce1e0c775f356cd16a9c22c70d25f3e01180839c407a5dc787fb05a13f67560cbaf316770d26fa99f78f1acd711b1b54a4f35d4820d4ea7136e6 + checksum: 10c0/a7452de47785842736fb71547651c5bbe5b4dc1e3722ccf48a704b7b34e4dcf633991eaa8e4a6a517ffb738b3252eede3773bef673ef9021baa26b056d63a5b9 languageName: node linkType: hard @@ -7049,9 +7090,9 @@ __metadata: languageName: node linkType: hard -"webpack@npm:5.91.0": - version: 5.91.0 - resolution: "webpack@npm:5.91.0" +"webpack@npm:5.93.0": + version: 5.93.0 + resolution: "webpack@npm:5.93.0" dependencies: "@types/eslint-scope": "npm:^3.7.3" "@types/estree": "npm:^1.0.5" @@ -7059,10 +7100,10 @@ __metadata: "@webassemblyjs/wasm-edit": "npm:^1.12.1" "@webassemblyjs/wasm-parser": "npm:^1.12.1" acorn: "npm:^8.7.1" - acorn-import-assertions: "npm:^1.9.0" + acorn-import-attributes: "npm:^1.9.5" browserslist: "npm:^4.21.10" chrome-trace-event: "npm:^1.0.2" - enhanced-resolve: "npm:^5.16.0" + enhanced-resolve: "npm:^5.17.0" es-module-lexer: "npm:^1.2.1" eslint-scope: "npm:5.1.1" events: "npm:^3.2.0" @@ -7082,7 +7123,7 @@ __metadata: optional: true bin: webpack: bin/webpack.js - checksum: 10c0/74a3e0ea1c9a492accf035317f31769ffeaaab415811524b9f17bc7bf7012c5b6e1a9860df5ca6903f3ae2618727b801eb47d9351a2595dfffb25941d368b88c + checksum: 10c0/f0c72f1325ff57a4cc461bb978e6e1296f2a7d45c9765965271aa686ccdd448512956f4d7fdcf8c164d073af046c5a0aba17ce85ea98e33e5e2bfbfe13aa5808 languageName: node linkType: hard