A library change reaches every pipeline that loads it, so treat it as a published package. The version after @ may be a branch, a tag or a commit. A branch such as main gives every build whatever was merged last; annotated semantic-version tags (v1.0.0 for seedCheck, v1.1.0 for imageTag) let each Jenkinsfile move forward deliberately. With Allow default version to be overridden on, a Jenkinsfile branch can try @Library('booknest-lib@feature-x') _ or @pull/<number>/head before a tag exists: Replay cannot edit trusted libraries.
Faster feedback comes from unit tests without Jenkins 8,793 . JenkinsPipelineUnit 1,586 (github.com/jenkinsci/JenkinsPipelineUnit (https://github.com/jenkinsci/JenkinsPipelineUnit 1,586 ), MIT, 1.31 from July 2026) loads vars/ scripts with mocked steps and records every call. It runs on Groovy 2.4.21, the version inside Jenkins, which the library's build.gradle also compiles src/ with, next to JUnit 6.1.1 48,319 :
void setUp() {
super.setUp()
helper.addShMock("grep -c '\"title\"' db/seed.json", '6\n', 0) // no real shell
}
...
@Test
void seedCheckFailsOnTheWrongCount() {
loadScript('vars/seedCheck.groovy').call(expected: 7)
assertJobStatusFailure()
assertTrue(helper.callStack.any { it.methodName == 'error' })
}The official gradle:jdk21 image (Gradle 9.8.0 19,597 ) runs them, so nothing is installed on the host:
docker run --rm -u 1000:1000 -v "$PWD":/work -w /work -e GRADLE_USER_HOME=/work/.gradle \
gradle:jdk21 gradle test --no-daemon --console=plain... BookNestLibTest > imageTagIsDockerSafe() PASSED BookNestLibTest > seedCheckFailsOnTheWrongCount() PASSED BookNestLibTest > seedCheckPassesWithSixBooks() PASSED BUILD SUCCESSFUL in 14s
The first run took 37 seconds, mostly downloads. One trap: the mocked error marks the build failed but does not throw, so the test checks the call stack rather than expecting an exception. A Jenkinsfile in the library's repository running this command would test every library pull request.