• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

cloudogu/ces-build-lib: Jenkins pipeline shared library adding features for Mave ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称(OpenSource Name):

cloudogu/ces-build-lib

开源软件地址(OpenSource Url):

https://github.com/cloudogu/ces-build-lib

开源编程语言(OpenSource Language):

Groovy 100.0%

开源软件介绍(OpenSource Introduction):

Cloudogu logo

ces-build-lib

Jenkins Pipeline Shared library, that contains additional features for Git, Maven, etc. in an object-oriented manner as well as some additional pipeline steps.

Table of contents

Usage

@Library('github.com/cloudogu/ces-build-lib@6cd41e0')
import com.cloudogu.ces.cesbuildlib.*
  • 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.

You can get the source.jar from JitPack.

With Maven this can be done like so:

  • Define the JitPack repository:
    <repositories>
        <repository>
            <id>jitpack.io</id>
            <url>https://jitpack.io</url>
        </repository>
    </repositories>
  • And the ces-build-lib dependency:
    <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:

  • https://jitpack.io/com/github/cloudogu/ces-build-lib/9fa7ac4/ces-build-lib-9fa7ac4.jar
  • https://jitpack.io/com/github/cloudogu/ces-build-lib/9fa7ac4/ces-build-lib-9fa7ac4-sources.jar

Current version is .
For further details and options refer to the JitPack website.

This is confirmed to work with IntelliJ IDEA.

Maven

Maven from local Jenkins tool

Run maven from a local tool installation on Jenkins.

See MavenLocal

def mvnHome = tool 'M3'
def javaHome = tool 'OpenJDK-8'
Maven mvn = new MavenLocal(this, mvnHome, javaHome)

stage('Build') {
    mvn 'clean install'
}

Maven Wrapper

Run maven using a Maven Wrapper from the local repository.

With local JDK tool

Similar to MavenLocal you can use the Maven Wrapper with a JDK from a local tool installation on Jenkins:

def javaHome = tool 'OpenJDK-8'
Maven mvn = new MavenWrapper(this, javaHome)

stage('Build') {
    mvn 'clean install'
}

With the JDK provided by the build agent

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.

Maven mvn = new MavenWrapper(this)

stage('Build') {
    mvn 'clean install'
}

Maven in Docker

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

See MavenInDocker

Maven mvn = new MavenInDocker(this, "3.5.0-jdk-8")

stage('Build') {
    mvn 'clean install'
}

Maven Wrapper In Docker

It's also possible to use the MavenWrapper in a Docker Container. Here, the Docker container is responsible for providing the JDK.

See MavenWrapperInDocker

Maven mvn = MavenWrapperInDocker(this, 'adoptopenjdk/openjdk11:jdk-11.0.10_9-alpine')

stage('Build') {
    mvn 'clean install'
}

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:

mvn.additionalArgs += " -Dmaven.repo.local=${env.WORKSPACE}/.m2"

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.

Maven mvn = new MavenInDocker(this, "3.5.0-jdk-8"),
echo "Outside Maven Container! ${new Docker(this).findIp()}"
mvn {
    echo "Insinde Maven Container! ${new Docker(this).findIp()}"
    'clean package -DskipTests'
}

Repository Credentials

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:

mvn.useRepositoryCredentials([id: 'ces', credentialsId: 'nexusSystemUserCredential'],
                             [id: 'another', credentialsId: 'nexusSystemUserCredential'])

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.

Note that as of nexus-staging-maven-plugin version 1.6.8, it does seem to read the distribution repositories from pom.xml only.

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:

<distributionManagement>
    <snapshotRepository>
        <id>ossrh</id>
        <url>https://oss.sonatype.org/content/repositories/snapshots</url>
    </snapshotRepository>
    <repository>
        <id>ossrh</id>
        <url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
    </repository>
</distributionManagement>

In addition you either have to pass an url to useRepositoryCredentials() or specify the nexus-staging-maven plugin in your pom.xml:

  <plugin>
    <groupId>org.sonatype.plugins</groupId>
    <artifactId>nexus-staging-maven-plugin</artifactId>
    <!-- ... -->
    <configuration>
      <serverId>ossrh</serverId>
      <nexusUrl>https://oss.sonatype.org/</nexusUrl>
    </configuration>
  </plugin>

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.

For an example see cloudogu/command-bus.

Deploying sites

Similar to deploying artifacts as described above, we can also easily deploy a Maven site to a "raw" maven repository.

Note that the site plugin does not provide options to specify the target repository via the command line. That is, it has to be configured in the pom.xml like so:

<distributionManagement>
    <site>
        <id>ces</id>
        <name>site repository cloudogu ecosystem</name>
        <url>dav:https://your.domain/nexus/repository/Site-repo/${project.groupId}/${project.artifactId}/${project.version}/</url>
    </site>
</distributionManagement>

Where Site-repo is the name of the raw repository that must exist in Nexus to succeed.

Then, you can deploy the site as follows:

mvn.useRepositoryCredentials([id: 'ces', credentialsId: 'nexusSystemUserCredential'])
mvn.deploySiteToNexus()

Where

  • the id parameter must match the one specified in the pom.xml(ces in the example above),
  • the nexus username and password/access token are passed as jenkins username and password credential (nexusSystemUserCredential).
  • there is no difference between Nexus 2 and Nexus 3 regarding site deployments.

For an example see cloudogu/continuous-delivery-slides-example

Passing additional arguments

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.

  • mvn.getVersion()
  • mvn.getArtifactId()
  • mvn.getGroupId()
  • mvn.getMavenProperty('project.build.sourceEncoding')

See Maven

Gradle

Gradle Wrapper in Docker

It's also possible to use a GradleWrapper in a Docker Container. Here, the Docker container is responsible for providing the JDK.

See GradleWrapperInDocker

Example:

String gradleDockerImage = 'openjdk:11.0.10-jdk'
Gradle gradlew = new GradleWrapperInDocker(this, gradleDockerImage)

stage('Build') {
    gradlew "clean build"
}

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 = new Git(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.branchName - e.g. feature/xyz/abc
  • git.simpleBranchName - e.g. abc
  • git.commitAuthorComplete - e.g. User Name <[email protected]>
  • git.commitAuthorEmail - e.g. [email protected]
  • git.commitAuthorName - e.g. User Name
  • 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.add('.')
  • git.commit('message', 'Author', '[email protected])
  • git.commit('message') - uses default author/committer (see above).
  • git.setTag('tag', 'message', 'Author', '[email protected])
  • 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.pull('refspec', 'Author', '[email protected])
  • git.merge('develop', 'Author', '[email protected])
  • 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:

Docker methods provided by the docker plugin

  • withRegistry(url, credentialsId = null, Closure body): Spe

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap