Skip to content

CpsFlowExecution: parseScript(): log "Method Too Large" situations more readably#817

Open
jimklimov wants to merge 58 commits into
jenkinsci:masterfrom
jimklimov:logging-exMTL
Open

CpsFlowExecution: parseScript(): log "Method Too Large" situations more readably#817
jimklimov wants to merge 58 commits into
jenkinsci:masterfrom
jimklimov:logging-exMTL

Conversation

@jimklimov

@jimklimov jimklimov commented Nov 23, 2023

Copy link
Copy Markdown

A small almost-cosmetic change which makes life easier for my colleagues when they develop (and debug failures of) Jenkins scripted pipelines.

UPDATE: Grew to be not so small, so evicted into a method of its own to constrain changes to other parts of the codebase. Learned a few more tricks over time, as new MTL situations were found in the field.

@jimklimov jimklimov requested a review from a team as a code owner November 23, 2023 08:35
@bitwiseman

Copy link
Copy Markdown
Contributor

Out of curiosity, what output does this give you and how is it helpful?

Comment thread plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java Outdated
Comment thread plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java Outdated
jimklimov and others added 5 commits December 11, 2023 21:55
…to avoid catching by full name

Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>
…argeExceptionRealistic() tests

Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>
…sException as a carrier of MethodTooLargeException; re-throw with just a compact message to appear in the build log

Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>
@jimklimov

jimklimov commented Mar 5, 2024

Copy link
Copy Markdown
Author

Tests helped me realize that the catch block was a bit naive; the groovy parser returns a special exception class with a collection of errors, one of which (okay, the only one) is the Method Too Large one.

PR updated with handling of both eventualities, and if the only exception in view is the MTL - re-throw with a short message avoiding a wall of text in pipeline log. From self-test console (showing both server log id=... and pipeline log test0), it now complains much more readably, like this:

   6.903 [test0 #1] Started
   7.635 [id=99]	SEVERE	o.j.p.w.cps.CpsFlowExecution#parseScript: FAILED to parse WorkflowScript (the pipeline script) due to MethodTooLargeException: Method too large: WorkflowScript.___cps___1 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
   7.680 [test0 #1] java.lang.RuntimeException: FAILED to parse WorkflowScript (the pipeline script) due to MethodTooLargeException: Method too large: WorkflowScript.___cps___1 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
   7.680 [test0 #1] 	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:697)
   7.680 [test0 #1] 	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:586)
   7.681 [test0 #1] 	at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:335)
   7.681 [test0 #1] 	at hudson.model.ResourceController.execute(ResourceController.java:101)
   7.681 [test0 #1] 	at hudson.model.Executor.run(Executor.java:442)
   7.700 [test0 #1] Finished: FAILURE
   7.718 [id=27]	INFO	hudson.lifecycle.Lifecycle#onStatusUpdate: Stopping Jenkins
   7.766 [id=27]	INFO	hudson.lifecycle.Lifecycle#onStatusUpdate: Jenkins stopped

Still got a bit of stack trace from generic handling, but it is reasonably short - the ultimate pipeline devs won't have to scroll up a couple of screenfuls just to learn that their script was too long or complex.

Now that the message is visible to end users, I am open to suggestions how to make it more actionable, and/or if the RuntimeException is the right re-throw wrapper, and of course which color should the bike shed be (or this can all be part of another PR) :D

e.g. to explain about script length or its coding complexity and what to do about it (nesting, amount of stages, separation of methods into JSL classes, etc.); maybe point to a knowledge-base URL for a better maintainable article on the subject (don't want to replace one wall of text in the logs with another, right?)

Comment thread plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java Outdated
@jglick jglick requested a review from a team March 5, 2024 12:22
…unt to satisfy different CI platforms

Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>
…t importing the class

Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>
…uggestions for pipeline devs

Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>
… expected matching line

Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>
@jimklimov

jimklimov commented Mar 5, 2024

Copy link
Copy Markdown
Author

Out of curiosity, what output does this give you and how is it helpful?

Until today, it was helpful to myself and a few colleagues who may/can/do follow traces of the Jenkins server logs when developing pipelines (testing in private Jenkins instances and those wrapped by IDEs notwithstanding).

After the review comments some months ago (thanks, and sorry for not noticing) and a coding effort today, this should be better visible and more "actionable" to a more general population - now shown as a smaller wall of text right in the pipeline build logs:

   5.380 [test0 #1] Started
   5.975 [test0 #1] java.lang.RuntimeException: FAILED to parse WorkflowScript
       (the pipeline script) due to MethodTooLargeException; please refactor to
       simplify code structure and/or move logic to a Jenkins Shared Library:
       Method too large: WorkflowScript.___cps___1 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
   5.975 [test0 #1] 	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:703)
   5.975 [test0 #1] 	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:584)
   5.975 [test0 #1] 	at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:335)
   5.975 [test0 #1] 	at hudson.model.ResourceController.execute(ResourceController.java:101)
   5.975 [test0 #1] 	at hudson.model.Executor.run(Executor.java:442)
   6.011 [test0 #1] Finished: FAILURE

...which is IMHO a bit more comprehensible than the original (especially the first time you see it):

...
 > git checkout -f c391f78bf7ac0d4afffab4f312a3d81cc41577d1 # timeout=10
Commit message: "..."
 > git rev-list --no-walk c391f78bf7ac0d4afffab4f312a3d81cc41577d1 # timeout=10
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
General error during class generation: Method too large: WorkflowScript.___cps___20692 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;

groovyjarjarasm.asm.MethodTooLargeException: Method too large: WorkflowScript.___cps___20692 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
        at groovyjarjarasm.asm.MethodWriter.computeMethodInfoSize(MethodWriter.java:2087)
        at groovyjarjarasm.asm.ClassWriter.toByteArray(ClassWriter.java:447)
        at org.codehaus.groovy.control.CompilationUnit$17.call(CompilationUnit.java:850)
        at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1087)
        at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:624)
        at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:602)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:579)
        at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:323)
        at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:293)
        at groovy.lang.GroovyShell.parseClass(GroovyShell.java:677)
        at groovy.lang.GroovyShell.parse(GroovyShell.java:689)
        at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:142)
        at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:127)
        at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:554)
        at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:506)
        at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:335)
        at hudson.model.ResourceController.execute(ResourceController.java:101)
        at hudson.model.Executor.run(Executor.java:442)

1 error

        at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:309)
        at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1107)
        at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:624)
        at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:602)
        at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:579)
        at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:323)
        at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:293)
        at groovy.lang.GroovyShell.parseClass(GroovyShell.java:677)
        at groovy.lang.GroovyShell.parse(GroovyShell.java:689)
        at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:142)
        at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:127)
        at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:554)
        at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:506)
        at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:335)
        at hudson.model.ResourceController.execute(ResourceController.java:101)
        at hudson.model.Executor.run(Executor.java:442)
Finished: FAILURE

...and requires less scrolling to get to the crux of the issue =D

jimklimov and others added 2 commits March 5, 2024 15:52
…ethods (class complexity) from maxTryCatch (nesting depth)

Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>

@jglick jglick left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic here is pretty convoluted and seems excessive when we do not really need to make things particularly pretty, we just need to offer some clue beyond what there is today. Would suffice to do something along the lines of

if (Functions.printThrowable(x).containsString("MethodTooLargeException")) {
    throw new IllegalArgumentException("…your hint here…", x);
} else {
    throw x;
}

Comment thread plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java Outdated
Comment thread plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java Outdated
jimklimov and others added 2 commits June 11, 2024 08:57
…wExecution.java


Do not log to server console log (not all server admins are those who run the projects with issues).

Co-authored-by: Jesse Glick <jglick@cloudbees.com>
Comment on lines +690 to +701
if (ecCount > 1) {
// Not squashing with explicit MethodTooLargeException
// re-thrown below, in this codepath we have other errors.
throw new RuntimeException(msg, x);
} else {
// Do not confuse pipeline devs by a wall of text in the
// build console, but let the full context be found in
// server log with some dedication.
LOGGER.log(Level.FINE, mtlEx.getMessage());
//throw new RuntimeException(msg, mtlEx);
throw new RuntimeException(msg);
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding the concern of "pretty convoluted logic" - this block is largely why I did it so: groovy can return a MultipleCompilationErrorsException with an attached collection of one or more errors (broadly speaking), so we need to count if we only had the MethodTooLargeException one way or another here (and then print the pretty log), or also something else and then better print everything for human devs to sift through it diligently.

Comment thread plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java Outdated
@jimklimov

Copy link
Copy Markdown
Author

Sorry it took a while to notice that there was finally a new review here - too many browser tabs open to keep track of such :D

Thanks for doing it!

@jimklimov

jimklimov commented Jun 17, 2024

Copy link
Copy Markdown
Author

Hm, got another use-case to handle: managed to get a step definition too large (aka "global variable", anyhow in JSL as vars/cloudBranch.groovy)!

So the pipeline chugged along until it called that step - and that's where the job crashed, with a different exception:

[Pipeline] End of Pipeline
Also:   org.jenkinsci.plugins.workflow.actions.ErrorAction$ErrorId: a1490d3b-63d7-4555-ae55-3a0d6856aee6
org.jenkinsci.plugins.workflow.cps.CpsCompilationErrorsException: startup failed:
General error during class generation: Method too large: cloudBranch.___cps___586328 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;

groovyjarjarasm.asm.MethodTooLargeException: Method too large: cloudBranch.___cps___586328 ()Lcom/cloudbees/groovy/cps/impl/CpsFunction;
	at groovyjarjarasm.asm.MethodWriter.computeMethodInfoSize(MethodWriter.java:2087)
	at groovyjarjarasm.asm.ClassWriter.toByteArray(ClassWriter.java:447)
	at org.codehaus.groovy.control.CompilationUnit$17.call(CompilationUnit.java:850)
	at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1087)
...
<no further pointers to the class in question>
...
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)

1 error

	at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:309)
	at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1107)
	at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:624)
	at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:602)
	at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:579)
	at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:323)
...
	at org.jenkinsci.plugins.workflow.cps.LoggingInvoker.getProperty(LoggingInvoker.java:121)
	at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
	at WorkflowScript.run(WorkflowScript:428)
	at com.cloudbees.groovy.cps.CpsDefaultGroovyMethods.each(CpsDefaultGroovyMethods:2125)
	at com.cloudbees.groovy.cps.CpsDefaultGroovyMethods.each(CpsDefaultGroovyMethods:2110)
	at com.cloudbees.groovy.cps.CpsDefaultGroovyMethods.each(CpsDefaultGroovyMethods:2163)
	at WorkflowScript.run(WorkflowScript:385)
	at ___cps.transform___(Native Method)
	at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:73)
	at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
	at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:65)
...
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1583)
Finished: FAILURE

Note there are actually two lines at WorkflowScript.run(WorkflowScript:NNN), pipeline code at line 385 starts an ...each {} closure to iterate several repos this job processes, and the line 428 actually calls the cloudBranch() method.

Gotta look into the structure of CpsCompilationErrorsException to see how to best parse it here (and know if "method too large" was the only error, so the report can be trimmed), and also consider that not only WorkflowScript can have such troubles.

jimklimov and others added 2 commits June 24, 2024 18:00
Notably, the latter is a Throwable but not an Exception so e.g. LinkageError might be not handled.

Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>
…ding for logged message

Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>
@jglick jglick requested a review from a team July 5, 2024 22:40
}
actionableMsg.append("; please refactor to simplify code structure");
if (overflowedClassNameReport.contains("WorkflowScript") || CLASSNAME_SCRIPTNUM_PATTERN.matcher(overflowedClassName).find())
actionableMsg.append(" and/or move logic to a Jenkins Shared Library");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW the terminology in https://www.jenkins.io/doc/book/pipeline/shared-libraries/ is unfortunate. By definition a “library” is “shared”; why else would you create a library? The plugin itself uses the term Pipeline Groovy library.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to mention both terminologies, hopefully that makes it clearer to both populations of readers.

OTOH, I often see (and use) the acronym JSL though, but never saw a PGL...

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I would say that code-sharing is one aspect. Code offloading (into a separate compilable unit) is another :)
Some organizations might want the looks of a declarative pipeline for some job with their custom logic behind it, so the logic is in a library (trusted, un-sandboxed and all) while the pipeline seems to call a few steps with a clean interface. But it may be the only consumer (the not-quite-sharing aspect of this).


static final Logger TIMING_LOGGER = Logger.getLogger(CpsFlowExecution.class.getName() + ".timing");

static final Logger METHOD_TOO_LARGE_LOGGER = Logger.getLogger(CpsFlowExecution.class.getName() + ".MethodTooLargeLogging");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there some reason not to simply use

private static final Logger LOGGER = Logger.getLogger(CpsFlowExecution.class.getName());
?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something about keeping the possibly large messages out of sight unless truly wanted in troubleshooting.

Comment thread plugin/src/main/java/org/jenkinsci/plugins/workflow/cps/CpsFlowExecution.java Outdated
.append(METHOD_TOO_LARGE_LOGGER.getName())
.append(" is required)");

//return new RuntimeException(actionableMsg.toString(), mtlEx);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not leave commented-out code in a final PR (unless there is a real possibility it should be resurrected some day soonish and a preceding comment explains those circumstances).

} else if (x instanceof CpsCompilationErrorsException) {
// Defined in this plugin, to clone a message and stack trace
// from a MultipleCompilationErrorsException and be serializable.
// Grep it as text for "MethodTooLargeException" and "1 error"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it not make more sense to just enrich CpsCompilationErrorsException with whatever information you need? AFAICT all you are looking for ultimately is the MethodTooLargeException.message. So, we could just keep that in a field?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting idea actually. At the time this was written, I did not realize such a possibility on one hand, and probably wanted the changes to not metastacize all over the codebase on another.

Comment on lines +95 to +96
@Test public void methodTooLargeExceptionFabricated() throws Exception {
// Fabricate a MethodTooLargeException which "normally" happens when evaluated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to keep this test case, given the “realistic” test below?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think yes, this fabricated test is about coded reaction to the particular exception, which may be or not be the one thrown in realistic test below (if CPS VM does at all break such way there and with that amount of threads).

Comment on lines +123 to +124
// * java.lang.StackOverflowError varies per JDK platform
// (CI on Linux was unhappy with 255, on Windows with 1023)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can set a per-thread stack size, but unfortunately the unit of measurement is unspecified and presumably specific to JVM implementation details, so this is probably not that helpful.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Why would you would be getting a JVM-level SOE, anyway? This is all dealing with the CPS VM that does not use the native stack.)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saw some code in this plugin throwing it (for "excessively nested" cases at least), so thought it is worth keeping in mind.

@jglick jglick left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK I think, though I can barely follow most of the code here. @dwnusbaum did you expect to review?

@dwnusbaum

dwnusbaum commented Mar 27, 2025

Copy link
Copy Markdown
Member

I have no plans to review this. My impression from a very brief look at the code was that it seemed quite complicated, but I am not blocking it. IMO creating a page like https://www.jenkins.io/doc/book/pipeline/cps-method-mismatches/ explaining the situation and recommendations in detail seems like it could help, and then perhaps this code could be simplified to only check the stack trace for the relevant class types and add a suppressed exception that links to that page, accepting potential false positives and not adding the additional context currently added by this PR (but maybe that context is critically useful, IDK).

@jglick

jglick commented Mar 27, 2025

Copy link
Copy Markdown
Member

only check the stack trace for the relevant class types and add a suppressed exception

#817 (review) more or less. IIUC this PR offers the same actionable information as was already there, but formatted differently?

links to that page

Actually a redirect URL like in jenkins-infra/jenkins.io#2290.

@jimklimov

jimklimov commented Apr 25, 2025

Copy link
Copy Markdown
Author

I'm not sure how the simple redirect to a wiki page would be better?

Do we not-print a wall of text and redirect to a wiki saying "sometimes the script is too big, guess which one of yours that is"?

Or do we print the wall of text and redirect to a wiki that says same and "here's how to look for a needle in the haystack"?

Currently the changeset pinpoints which pipeline, step or JSL class has upset the parser (finds those needles in the haystack for us), so I am not sure how the other options are better. Surely a Wiki link can be posted "in addition" to this, but "instead" - I am not so excited about that path (even not due to author bias - just due to loss of usability improvement we use for over a year).

UPDATE: Looking back at the comment trail (it has been a while overall), maybe there's a way to simplify code to achieve a similar effect. Also unit tests would be nice, although it can take a while to conjure up some test pipeline/var/class files that do not contain an internal codebase we hit this with.

Not sure when/if I'd get to this - got a big higher-priority backlog of work not yet completed at work and in other projects, and this code (and many similarly stalled PRs) is at least completed as far as practical effect is concerned... just 90% of work remains to fulfill the maintainability (or more esoteric ritual) requirements of the project du-jour...

I guess for now I'll keep remerging master into the PR to use incremental builds, maybe will come back to this eventually (hopefully before retirement), anyone beating me to it and bringing this to completion is very welcome though :)

jimklimov and others added 6 commits August 4, 2025 12:11
…logging-exMTL

Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>
Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>
… to mention Pipeline Groovy library/PGL (plugin term)

@jglick> BTW the terminology in https://www.jenkins.io/doc/book/pipeline/shared-libraries/
is unfortunate. By definition a “library” is “shared”; why else would you create a library?
The plugin itself uses the term Pipeline Groovy library.

Signed-off-by: Jim Klimov <jimklimov+jenkinsci@gmail.com>
Apply suggestion from @jglick

Co-authored-by: Jesse Glick <jglick@cloudbees.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants