Jenkins Pipeline Shared library, that contains additional features for Git, Maven, etc. in an object-oriented manner as well as some additional pipeline steps.
Best practice: Use a defined version (e.g. a git commit hash or a git tag, such as 6cd41e0 or 1.49.0 in the example above) and not a branch such as develop. Otherwise, your build might change when the there is a new commit on the branch. Using branches is like using snapshots!
When build executors are docker containers and you intend to use their Docker host in the Pipeline: Please see #8.
Syntax completion
You can get syntax completion in your Jenkinsfile when using the ces-build-lib, by adding it as dependency to your project.
<dependency>
<!-- Shared Library used in Jenkins. Including this in maven provides code completion in Jenkinsfile. -->
<groupId>com.github.cloudogu</groupId>
<artifactId>ces-build-lib</artifactId>
<!-- Keep this version in sync with the one used in Jenkinsfile -->
<version>888733b</version>
<!-- Don't ship this dependency with the app -->
<optional>true</optional>
<!-- Don't inherit this dependency! -->
<scope>provided</scope>
</dependency>
Or you can download the file (and sources) manually and add them to your IDE. For example:
It is also possible to not specify a JDK tool and use the Java Runtime on the Build agent's PATH. However,
experience tells us that this is absolutely non-deterministic and will result in unpredictable behavior.
So: Better set an explicit Java tool to be used or use MavenWrapperInDocker.
Run maven in a docker container. This can be helpful, when
constant ports are bound during the build that cause port conflicts in concurrent builds. For example, when running
integration tests, unit tests that use infrastructure that binds to ports or
one maven repo per builds is required For example when concurrent builds of multi module project install the same
snapshot versions.
Plain Maven In Docker
The builds are run inside the official maven containers from Dockerhub
Since Oracle's announcement of shorter free JDK support, plenty of JDK images have appeared on public container image
registries, where adoptopenjdk is just one option. The choice is yours.
Advanced Maven in Docker features
The following features apply to plain Maven as well as Maven Wrapper in Docker.
Maven starts new containers
If you run Docker from your maven build, because you use the
docker-maven-plugin for example, you can connect the docker socket
through to your docker in maven like so:
stage('Unit Test') {
// The UI module build runs inside a docker container, so pass the docker host to the maven container
mvn.enableDockerHost = true
mvn docker:start
// Don't expose docker host more than necessary
mvn.enableDockerHost = false
}
There are some security-related concerns about this. See Docker.
Local repo
Maven in Docker
If you would like to use Jenkin's local maven repo (or more accurate the one of the build executor, typically at /home/jenkins/.m2)
instead of a maven repo per job (within each workspace), you can use the following options:
Maven mvn = new MavenInDocker(this, "3.5.0-jdk-8")
mvn.useLocalRepoFromJenkins = true
This speed speeds up the first build and uses less memory.
However, concurrent builds of multi module projects building the same version (e.g. a SNAPSHOT), might overwrite their dependencies, causing non-deterministic build failures.
Maven without Docker
The default is the default maven behavior /home/jenkins/.m2 is used.
If you want to use a separate maven repo per Workspace (e.g. in order to avoid concurrent builds overwriting
dependencies of multi module projects building the same version (e.g. a SNAPSHOT) the following will work:
Lazy evaluation / execute more steps inside container
If you need to execute more steps inside the maven container you can pass a closure to your maven instance that is
lazily evaluated within the container. The String value returned are the maven arguments.
If you specified one or more <repository> in your pom.xml that requires authentication, you can pass these
credentials to your ces-build-lib Maven instance like so:
Note that the id must match the one specified in your pom.xml and the credentials ID must belong to a username and
password credential defined in Jenkins.
Deploying to Nexus repository
Deploying artifacts
ces-build-lib makes deploying to nexus repositories easy, even when it includes signing of the artifacts and usage of
the nexus staging plugin (as necessary for Maven Central or other Nexus repository pro instances).
Simple deployment
The most simple use case is to deploy to a nexus repo (not Maven Central):
Just set the repository using Maven.useRepositoryCredentials() by passing a nexus username and password/access token
as jenkins username and password credential and
either a repository ID that matches a <distributionManagement><repository> (or <snapshotRepository>, examples
bellow) defined in your pom.xml (then, no url or type parameters are needed)
(distributionManagement > snapshotRepository or repository (depending on the version) > id)
or a repository ID (you can choose) and the URL.
In this case you can alos specifiy a type: 'Nexus2' (defaults to Nexus3) - as the base-URLs differ.
This approach is deprecated and might be removed from ces-build-lib in the future.
Call Maven.deployToNexusRepository(). And that is it.
Simple Example:
# <distributionManagement> in pom.xml (preferred)
mvn.useRepositoryCredentials([id: 'ces', credentialsId: 'nexusSystemUserCredential'])
# Alternative: Distribution management via Jenkins (deprecated)
mvn.useRepositoryCredentials([id: 'ces', url: 'https://ecosystem.cloudogu.com/nexus', credentialsId: 'nexusSystemUserCredential', type: 'Nexus2'])
# Deploy
mvn.deployToNexusRepository()
Note that if the pom.xml's version contains -SNAPSHOT, the artifacts are automatically deployed to the
snapshot repository (e.g. on oss.sonatype.org). Otherwise,
the artifacts are deployed to the release repository (e.g. on oss.sonatype.org).
Signing artifacts (e.g. Maven Central)
If you want to sign the artifacts before deploying, just set the credentials for signing before deploying, using
Maven.setSignatureCredentials() passing the secret key as ASC file (as jenkins secret file credential) and the
passphrase (as jenkins secret text credential).
An ASC file can be exported via gpg --export-secret-keys -a ABCDEFGH > secretkey.asc.
See Working with PGP Signatures
Deploying with staging (e.g. Maven Central)
Another option is to use the nexus-staging-maven-plugin instead of the default maven-deploy-plugin.
This is useful if you deploy to a Nexus repository pro, such as Maven Central.
Just use the Maven.deployToNexusRepositoryWithStaging() instead of Maven.deployToNexusRepository().
When deploying to Maven Central, make sure that your pom.xml adheres to the requirements by Maven Central, as stated
here.
That is, you need to specify them in your pom.xml, they cannot be passed by the ces-build-lib. So for example for maven
central you need to add the following:
Either way, the repository ID (here: ossrh) and the base nexus URL (here: https://oss.sonatype.org) in
distributionManagement and nexus-staging-maven plugin must conform to each other.
Summing up, here is an example for deploying to Maven Central:
// url is optional, if described in nexus-staging-maven-plugin in pom.xml
mvn.useRepositoryCredentials([id: 'ossrh', url: 'https://oss.sonatype.org', credentialsId: 'mavenCentral-UsernameAndAcccessTokenCredential', type: 'Nexus2'])
mvn.setSignatureCredentials('mavenCentral-secretKey-asc-file','mavenCentral-secretKey-Passphrase')
mvn.deployToNexusRepositoryWithStaging()
Note that the staging of releases might well take 10 minutes. After that, the artifacts are in the
release repository, which is later (feels like nightly)
synced to Maven Central.
Another option for deployToNexusRepositoryWithStaging() and deployToNexusRepository() is to pass additional maven
arguments to the deployment like so: mvn.deployToNexusRepositoryWithStaging('-X') (enables debug output).
Maven Utilities
Available from both local Maven and Maven in Docker.
Since Oracle's announcement of shorter free JDK support, plenty of JDK images have appeared on public container image
registries, where adoptopenjdk is just one option. The choice is yours.
Git
An extension to the git step, that provides an API for some commonly used git commands and utilities.
Mostly, this is a convenient wrapper around using the sh 'git ...' calls.
Example:
Git git =newGit(this)
stage('Checkout') {
git 'https://your.repo'/* Don't remove folders starting in "." like .m2 (maven), .npm, .cache, .local (bower), etc. */
git.clean('".*/"')
}
Credentials
You can optionally pass usernamePassword (i.e. a String containing the ID that refers to the
Jenkins credentials) to Git during construction.
These are then used for cloning and pushing.
Note that the username and passwort are processed by a shell. Special characters in username or password might cause
errors like Unterminated quoted string. So it's best to use a long password that only contains letters and numbers
for now.
Git annonymousGit = new Git(this)
Git gitWithCreds = new Git(this, 'ourCredentials')
annonymousGit 'https://your.repo'
gitWithCreds 'https://your.repo' // Implicitly passed credentials
Git Utilities
Read Only
git.clean() - Removes all untracked and unstaged files.
git.clean('".*/"') - Removes all untracked and unstaged files, except folders starting in "." like .m2 (maven),
.npm, .cache, .local (bower), etc.
git.commitMessage - Last commit message e.g. Implements new functionality...
git.commitHash - e.g. fb1c8820df462272011bca5fddbe6933e91d69ed
git.commitHashShort - e.g. fb1c882
git.areChangesStagedForCommit() - true if changes are staged for commit. If false, git.commit() will fail.
git.repositoryUrl - e.g. https://github.com/orga/repo.git
git.gitHubRepositoryName - e.g. orga/repo
Tags - Note that the git plugin might not fetch tags for all builds. Run sh "git fetch --tags" to make sure.
git.tag - e.g. 1.0.0 or empty if not set
git.isTag() - is there a tag on the current commit?
Changes to local repository
Note that most changing operations offer parameters to specify an author.
Theses parameters are optional. If not set the author of the last commit will be used as author and committer.
You can specify a different committer by setting the following fields:
It is recommended to set a different committer, so it's obvious those commits were done by Jenkins in the name of
the author. This behaviour is implemented by GitHub for example when committing via the Web UI.
git.checkout('branchname')
git.checkoutOrCreate('branchname') - Creates new Branch if it does not exist
git.setTag('tag', 'message') - uses default author/committer (see above).
git.fetch()
git.pull() - pulls, and in case of merge, uses default author/committer (see above).
git.pull('refspec') - pulls specific refspec (e.g. origin master), and in case of merge, uses the name and email
of the last committer as author and committer.
git.merge('develop') - uses default author/committer (see above).
git.mergeFastForwardOnly('master')
Changes to remote repository
git.push('origin master') - pushes origin
Note: This always prepends origin if not present for historical reasonse (see #44).
That is, right now it is impossible to push other remotes.
This will change in the next major version of ces-build-lib.
This limitation does not apply to other remote-related operations such as pull(), fetch() and pushAndPullOnFailure()
So it's recommended to explicitly mention the origin and not just the refsepc:
Do: git.push('origin master')
Don't: git.push('master') because this will no longer work in the next major version.
git.pushAndPullOnFailure('refspec') - pushes and pulls if push failed e.g. because local and remote have diverged,
then tries pushing again
Docker
The Docker class provides the default methods of the global docker variable provided by docker plugin:
请发表评论