Publishing artifacts

A software project can contain artifacts that we want to publish. An artifact can be a ZIP or JAR archive file or any other file. In Gradle, we can define more than one artifact for a project. We can publish these artifacts in a central repository so that other developers can use our artifacts in their projects. These central repositories can be available on the company intranet, network drive, or via the Internet.

In Gradle, we group artifacts through configurations, just like dependencies. A configuration can contain both dependencies and artifacts. If we add the Java plugin to our project, we also have two extra tasks per configuration to build and upload the artifacts belonging to the configuration. The task to build the artifacts is called build<configurationName> and the task to upload the artifacts is called upload<configurationName>.

The Java plugin also adds the archives configuration that can be used to assign artifacts. The default JAR artifact for a Java project is already assigned to this configuration. We can assign more artifacts to this configuration for our project. We can also add new configurations to assign artifacts in a project.

For our Java project, we will define the following sample build file:

apply plugin: 'java' 
 
archivesBaseName = 'gradle-sample' 
version = '1.0' 

As we use the Java plugin, we have the archives configuration available. When we execute the buildArchives task, our Java code is compiled and a JAR file is created in the build/libs directory, called gradle-sample-1.0.jar.

To publish our JAR file, we can execute the uploadArchives task, but we must first configure where to publish the artifact. The repositories that we have defined for the dependencies are not used to upload the artifacts. We have to define the upload repository in the uploadArchives task. We can reference a repository that is already defined in our project or define the repositories in the task.

The following sample build file defines an upload repository at project level and task level:

apply plugin: 'java' 
 
archivesBaseName = 'gradle-sample' 
version = '1.0' 
 
repositories { 
    flatDir { 
        name 'uploadRepository' 
        dirs 'upload' 
    } 
} 
 
uploadArchives { 
    repositories { 
        // Use repository defined in project 
        // for uploading the JAR file. 
        add project.repositories.uploadRepository 
 
        // Extra upload repository defined in 
        // the upload task. 
        flatDir { 
            dirs 'libs' 
        } 
    } 
} 

If we invoke the uploadArchives task, the JAR file is created and copied to the libs and upload directories in our project root directory. An ivy.xml configuration file is also created and copied to the directories, as follows:

$ gradle uploadArchives
:compileJava
:processResources
:classes
:jar
:uploadArchives
BUILD SUCCESSFUL
Total time: 0.753 secs
$ ls libs/
gradle-sample-1.0.jar
gradle-sample-1.0.jar.sha1
ivy-1.0.xml
ivy-1.0.xml.sha1
$ ls upload/
gradle-sample-1.0.jar
gradle-sample-1.0.jar.sha1
ivy-1.0.xml
ivy-1.0.xml.sha1

We can use all the Ivy resolvers to define upload repositories.

Uploading our artifacts to a Maven repository

If we want to upload to a Maven repository, we must create a Maven Project Object Model (POM) file. The Maven POM file contains all the necessary information about our artifact. Gradle can generate the POM file for us. We must add the Maven plugin to our project in order to make this work.

We must configure the repository for our uploadArchives task via a closure argument of the mavenDeployer() method. In the following sample build file, we will define a Maven repository with the file protocol:

apply plugin: 'java' 
apply plugin: 'maven' 
 
archivesBaseName = 'gradle-sample' 
group = 'gradle.sample' 
version = '1.0' 
 
uploadArchives { 
    repositories { 
        mavenDeployer { 
            repository(url: 'file:./maven') 
        } 
    } 
} 

Note that we set the group property of our project so that it can be used as groupId of the Maven POM. The version property is used as version and the archivesBaseName property is used as the artifact ID. We can invoke the uploadArchives task to deploy our artifact, as follows:

$ gradle uploadArchives
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar UP-TO-DATE
:uploadArchives
BUILD SUCCESSFUL
Total time: 1.121 secs
$ ls maven/gradle/sample/gradle-sample/1.0/
gradle-sample-1.0.jar
gradle-sample-1.0.jar.md5
gradle-sample-1.0.jar.sha1
gradle-sample-1.0.pom
gradle-sample-1.0.pom.md5
gradle-sample-1.0.pom.sha1

The contents of the generated gradle-sample-1.0.pom POM file are as follows:

<?xml version="1.0" encoding="UTF-8"?> 
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
  <modelVersion>4.0.0</modelVersion> 
  <groupId>gradle.sample</groupId> 
  <artifactId>gradle-sample</artifactId> 
  <version>1.0</version> 
</project> 

Gradle uses the native Maven ANT tasks to deploy the artifacts to a Maven repository. The file protocol is supported without any extra configuration; but if we want to use other protocols, we must configure the libraries on which these protocols depend on:

Protocol

Library

http

org.apache.maven.wagon:wagon-http:1.0-beta-2

ssh

org.apache.maven.wagon:wagon-ssh:1.0-beta-2

ssh-external

org.apache.maven.wagon:wagon-ssh-external:1.0-beta-2

scp

org.apache.maven.wagon:wagon-scp:1.0-beta-2

ftp

org.apache.maven.wagon:wagon-ftp:1.0-beta-2

webdav

org.apache.maven.wagon:wagon-webdav-jackrabbit:1.0-beta-2

file

-

In the following sample build file, we will use the scp protocol to define a Maven repository and use it to upload the project's artifact:

apply plugin: 'java' 
apply plugin: 'maven' 
 
archivesBaseName = 'gradle-sample' 
group = 'gradle.sample' 
version = '1.0' 
 
configurations { 
    mavenScp 
} 
 
repositories { 
    jcenter() 
} 
 
dependencies { 
    mavenScp 'org.apache.maven.wagon:wagon-scp:1.0-beta-2' 
} 
 
uploadArchives { 
    repositories { 
      mavenDeployer { 
        configuration = configurations.mavenScp 
          repository(url: 'scp://localhost/mavenRepo') { 
            authentication(userName: 'user', privateKey: 'id_sha') 
            } 
        } 
    } 
} 

The Maven plugin also adds the install task to our project. With the install task, we can install the artifact to our local Maven repository. Gradle will use the default location of the local Maven repository or the location that is defined in a settings.xml Maven file.

Working with multiple artifacts

Until now, we have uploaded a single artifact to a repository. In a Gradle project, we can define multiple artifacts and deploy them. We need to define an archive task and assign it to a configuration. We will use the artifacts{} script block to define a configuration closure in order to assign an artifact to a configuration. The artifact is then deployed to a repository when we execute the upload task.

In the following sample build, we will create JAR files with the source code and Javadoc documentation. We will assign both JAR files as artifacts to the archives configuration:

apply plugin: 'java' 
 
archivesBaseName = 'gradle-sample' 
version = '1.0' 
 
// New task to archive the source files. 
task sourcesJar(type: Jar) { 
    classifier = 'sources' 
    from sourceSets.main.allSource 
} 
 
// New task to archive the documentation. 
task docJar(type: Jar, dependsOn: javadoc) { 
    classifier = 'docs' 
    from javadoc.destinationDir 
} 
 
artifacts { 
    // Assign the output of the sourcesJar 
    // task to the archives configuration. 
    archives sourcesJar 
 
    // Assign the output of the docJar 
    // task to the archives configuration. 
    archives docJar 
} 
 
uploadArchives { 
    repositories { 
        flatDir { 
            dirs 'upload' 
        } 
    } 
} 

Signing artifacts

We can digitally sign artifacts in Gradle with the signing plugin. The plugin only has support to generate the Pretty Good Privacy (PGP) signature, which is the signature format required for publication to the Maven Central Repository. To create a PGP signature, we must install some PGP tools on our computers. Installation of the tools is different for each operating system. With the PGP software, we need to create a key pair that we can use to sign our artifacts.

We need to configure the signing plugin with the information about our key pair. We need the hexadecimal representation of the public key, the path to the secret key ring file with our private key, and the passphrase used to protect the private key. The values of these properties are assigned to the signing.keyIdsigning.secretKeyRingFile, and signing.password Gradle project properties. The values of these properties are best kept secret, so it is better to store them in our gradle.properties file in the Gradle user directory and apply secure file permissions to the file. It is best to make the file read-only for a single user.

The following gradle.properties sample file has the signing properties set. The values of the properties shown are sample values. These will be different for other users:

signing.keyId=4E12C354 
signing.secretKeyRingFile=/Users/current/.gnupg/secring.gpg 
signing.password=secret phassphrase 

We are ready to sign our artifacts. We need to configure the artifacts that we want signed. The signing plugin has a DSL that we can use to define the tasks or configurations that we want signed.

In our sample Java project, we have the archives configuration with artifacts of our project. To sign the artifacts, we can use the signing() method and a closure to configure that all artifacts of the archives configuration need to be signed. The following sample build file shows how we can do this:

apply plugin: 'java' 
apply plugin: 'signing' 
 
archivesBaseName = 'gradle-sample' 
version = '1.0' 
 
signing { 
    sign configurations.archives 
} 

The signing plugin adds a new signArchives task to our project as we have configured that we want the archives configuration to be signed. The signing plugin adds tasks with the sign<configurationName> pattern to our project, for each configuration we configure to be signed.

We can invoke the signArchives task to sign our JAR artifact or use the Jar task, which is automatically dependent on the signArchives task, as follows:

$ gradle signArchives
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar UP-TO-DATE
:signArchives
BUILD SUCCESSFUL


Total time: 1.649 secs
$ ls build/libs/gradle-sample-1.0.jar*
build/libs/gradle-sample-1.0.jar
build/libs/gradle-sample-1.0.jar.asc

Note that the gradle-sample-1.0.jar.asc signature file is placed next to the artifact.

If the artifact we want to sign is not part of a configuration, we can use the signing DSL to configure a task to be signed. The task must create an archive file in order to be used for signing. After we have configured the task to be signed, the signing plugin adds a new task with the  sign<taskName> naming pattern. We can execute this task to sign the output of the configured task.

The following build file has the sourcesJar task to create a new archive with the source files of our project. We will use the signing DSL to configure our task for signing:

apply plugin: 'java' 
apply plugin: 'signing' 
 
archivesBaseName = 'gradle-sample' 
version = '1.0' 
 
task sourcesJar(type: Jar) { 
    classifier = 'sources' 
    from sourceSets.main.allSource 
} 
 
signing { 
    sign sourcesJar 
} 

We can invoke the signSourcesJar task to digitally sign our JAR file with the sources of our project. The generated signature file is placed next to the JAR file in the build/libs directory. We can also invoke the assemble task to create the digitally-signed JAR file as this task is made dependent on all our archive tasks, including the signing tasks:

$ gradle signSourcesJar
:sourcesJar
:signSourcesJar
BUILD SUCCESSFUL
Total time: 0.87 secs
$ ls build/libs/gradle-sample-1.0-sources.jar*
build/libs/gradle-sample-1.0-sources.jar
build/libs/gradle-sample-1.0-sources.jar.asc
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.235.23