Trying to push the Gradle project to Github package registry, but not working as expected.
Using io.freefair.github.package-registry-maven-publish plugin for Gradle.
Configure GitHub in build.gradle with data needed to publish - code below. And run the publishing task publishAllPublicationsToGutHub. Getting no error but I can't see my package in GitHub package registry.
github {
slug
username = "myGitUserName"
token = "myTokenWithRightAccess"
tag = "HEAD"
travis = true
}
Expecting some examples of how to publish to Github package registry with Gradle or what I'm doing wrong when publishing
New answer:
GitHub has published the official guide: Configuring Gradle for use with GitHub Packages.
Old answer:
It seems like the plugin is not very stable yet. Take a look at the repository I've created that has everything set up. I managed to publish a few packages with that plugin here.
Even the packages are published, Gradle shows task as failed, due to some issues with maven-metadata.xml:
> Task :publishMainPublicationToGitHub madhead Maven PackagesRepository FAILED
Could not transfer metadata so57323260:test/maven-metadata.xml from/to remote (https://maven.pkg.github.com/madhead): Could not get resource 'so57323260/test/maven-metadata.xml'
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':publishMainPublicationToGitHub madhead Maven PackagesRepository'.
> Failed to publish publication 'main' to repository 'GitHub madhead Maven Packages'
> Could not GET 'https://maven.pkg.github.com/madhead/so57323260/test/maven-metadata.xml'. Received status code 422 from server: Unprocessable Entity
But that's ok, probably will be fixed one day.
I've noticed, that the packages might not be published (see the linked issue) because of the incorrect groupId of a Maven publication. It seems like right now it should be equal to the Github's project name. So, in my case, I had to use so57323260 as a groupId for a madhead/so57323260 project. That's not how packages work in Maven generally, so that might be your issue.
I was able to publish to the Github Package Registry using the maven-publish plugin. It seems to work just fine now.
My build.gradle file looks like this:
buildscript {
repositories {
mavenCentral()
}
}
plugins {
id 'java'
id 'maven-publish'
}
group 'com.company.project'
archivesBaseName = 'library-name'
version '0.1.0'
repositories {
mavenCentral()
}
dependencies {
// java dependencies
}
publishing {
repositories {
maven {
name = "Github"
url = uri("https://maven.pkg.github.com/<OWNER>/<REPO>")
credentials {
username = findProperty("github.username")
password = findProperty("github.token")
}
}
}
publications {
register("jar", MavenPublication) {
from(components["java"])
pom {
url.set("https://github.com/<OWNER>/<REPO>.git")
}
}
}
}
Put your github username and token into the gradle.properties file.
Also worth setting up a github action to publish to the github package repo:
name: Publish package to GitHub Packages
on:
release:
types: [created]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- uses: actions/setup-java#v1
with:
java-version: 1.8
- name: Publish package
run: gradle -Pversion=${{ github.event.release.tag_name }} build publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
This publishes a package every time we create a release tag with that tag as the version.
GitHub has published the official document for How to use Gradle with GitHub packager
https://help.github.com/en/github/managing-packages-with-github-packages/configuring-gradle-for-use-with-github-packages#authenticating-to-github-packages
Complete those properties correctly
OWNER
REPOSITORY
USERNAME (or gradle property gpr.user)
PASSWORD (or gradle property gpr.key)
#See demo
https://github.com/youngerier/packagesdemo
https://help.github.com/en/github/managing-packages-with-github-packages/configuring-gradle-for-use-with-github-packages
Related
I have a multi-module project which supports maven and gradle builds hence it contains pom.xml files along side with build.gradle. I'm working on a demo and I would like to show how to build and deploy to nexus the same project using either gradle or maven. That's why I have two different build systems in case you wonder why.
You may see the project structure below.
You may look into the code here.
I've configured the gradle maven-publish plugin in order to publish all modules to my local nexus repository however when I run gradle publish I hit this error:
Execution failed for task ':publishMavenJavaPublicationToMavenRepository'.
> Failed to publish publication 'mavenJava' to repository 'maven'
> Artifact machinery-config-0.0.1.jar wasn't produced by this build.
The issue is related with having the publishing section within $rootDir/build.gradle.
It's confusing maven-publish somehow which is trying to publish an artifact that doesn't exist machinery-config-0.0.1.jar, machinery-config is the name of the rootProject.
One workaround could be to remove the publishing section from the rootProject and duplicate it in the sub-projects. I don't like that approach cuz I will end up with a lot of duplicated code.
Could you point me out a better way to use maven-publish within a multi-module project ?
After some digging I realized that I had two issues:
publishing section was outside of subprojects section, then gradle tried to deploy an artifact using rootProject.name ignoring the included modules.
group & version properties were outside subprojects therefore deployed artifacts had undefined as version number, e.g machinery-config-core-undefined.jar
In order to fix issue number two I had moved group & version into subprojects section.
My build also produces a BOM artifact hence I need two publications from components.java and from components.javaPlatform, so I wrote this script gradle/ext/publish-common.gradle which exports two functions I will use later on both publications to keep code duplication at bay.
def pom(it) {
it.licenses {
license {
name = 'The Apache License, Version 2.0'
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
it.developers {
developer {
id = 'eljaiek'
name = 'Eduardo Eljaiek'
email = 'eduardo.eljaiek#gmail.com'
}
}
it.scm {
connection = 'scm:git:git://github.com/eljaiek/machinery-config.git'
developerConnection = 'scm:git:git#github.com:eljaiek/machinery-config.git'
url = 'https://github.com/eljaiek/machinery-config'
}
}
def nexusRepository(it) {
it.url = version.endsWith('SNAPSHOT') ? project.nexusSnapshotsUrl : project.nexusReleasesUrl
it.credentials {
username project.nexusUser
password project.nexusPasswd
}
}
ext {
pom = this.&pom
nexusRepository = this.&nexusRepository
}
I had added from components.javaPlatform publication into machinery-config-dependencies/build.gradle in order to deploy the BOM artifact
apply plugin: 'maven-publish'
apply from: "$rootDir/gradle/ext/publish-common.gradle"
publishing {
publications {
mavenBom(MavenPublication) {
from components.javaPlatform
pom { x -> pom(x)}
}
}
repositories {
maven { x -> nexusRepository(x) }
}
}
apply from: "$rootDir/gradle/ext/publish-common.gradle" will aplly the script I wrote, this is required in order to import pom() and nexusRepository() functions into my build script.
To deploy from components.java artifacts I had added a publishing section in subprojects under if (it.name != 'machinery-config-dependencies') statement into $rootDir/build.gradle
apply plugin: 'ru.vyarus.pom'
apply from: "$rootDir/gradle/ext/publish-common.gradle"
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
pom { x -> pom(x)}
}
}
repositories {
maven { x -> nexusRepository(x) }
}
}
I had used Gradle POM plugin instead of maven-publish. It provides maven's dependencies declaration simplicity and implicitly applies maven-publish plugin.
See the code here
References
Extract common methods from Gradle build script
The Java Platform Plugin
I am currently in the process of re-organizing and re-structuring some of the projects we use at work.
One of my goals is to integrate a project's unit tests correctly. I have upgraded the root projects Gradle to the latest version (5.6.2) and I have made all the necessary DSL changes.
Right now I'm in the process of including the project's integration tests under its source code. For this I created a new subproject.
So far so good but when I attempt to build the project it fails with following exception:
Caused by: groovy.lang.MissingPropertyException: Could not get unknown property 'StartServerTask' for project ':integration-tests' of type org.gradle.api.Project.
at org.gradle.internal.metaobject.AbstractDynamicObject.getMissingProperty(AbstractDynamicObject.java:84)
at org.gradle.groovy.scripts.BasicScript$ScriptDynamicObject.getMissingProperty(BasicScript.java:156)
at org.gradle.internal.metaobject.AbstractDynamicObject.getProperty(AbstractDynamicObject.java:61)
at org.gradle.groovy.scripts.BasicScript.getProperty(BasicScript.java:65)
Now, the task in question comes for a Gradle plugin a colleague created in the past. Said plugin is fetched from a maven repository as a dependency like so:
buildscript {
repositories {
maven { url 'maven_link' }
}
dependencies {
classpath 'fts.gradle:start-server:0.3'
}
}
plugins {
id 'java'
id 'application'
id 'eclipse'
}
And applied like
apply plugin: 'fts.gradle'
I have tried almost everything, even changing the package structure of the plugin, but I am unable to include it properly in the build file.
If I copy paste the code directly within the project's build.gradle everything works fine but it doesn't so if I try to remote fetch and include the plugin.
Can anyone provide any insight to this?
I am the mantainer of the Java 8 java.time JSP tags library. I have little experience publishing libraries on my own. For the publication of this library I did some research and ended with a gradle build script that you can check in GitHub. The process is a bit clunky but it works in the end.
There seem to be a general understanding that the jcenter() repository is gaining a lot of attention. Probably because of android. Anyway I saw an encouraging blog post and decided to give it a try and migrate that library to JCenter publishing insted of Maven Central. Should be easy.
It is not, for me at least. Probably my fault as my knowledge of Maven, artifacts and all that stuff is poor. Anyway I gave it some hours of research and come up with a new gradle build to publish to my Bintray maven repository. Which, if I'm not wrong, is the first step towards publishing to JCenter.
This is what I have so far:
plugins {
id "com.jfrog.bintray" version "1.6"
}
apply plugin: 'java'
apply plugin: 'maven-publish'
group = 'net.sargue'
version = '1.1.2'
sourceCompatibility = 1.8
compileJava.options.encoding = 'UTF-8'
compileTestJava.options.encoding = 'UTF-8'
repositories {
jcenter()
}
configurations {
testCompile.extendsFrom compileOnly
}
dependencies {
compileOnly 'javax.servlet:javax.servlet-api:3.0.1'
compileOnly 'javax.servlet.jsp:javax.servlet.jsp-api:2.2.1'
compileOnly 'javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:1.2.1'
testCompile 'junit:junit:4.12'
testCompile 'org.springframework:spring-test:4.1.7.RELEASE'
}
jar {
manifest {
attributes 'Implementation-Title': 'Java 8 java.time JSP tags',
'Implementation-Version': version
}
}
task javadocJar(type: Jar) {
classifier = 'javadoc'
from javadoc
}
task sourcesJar(type: Jar) {
classifier = 'sources'
from sourceSets.main.allSource
}
publishing {
publications {
MyPublication(MavenPublication) {
from components.java
artifact sourcesJar
artifact javadocJar
artifactId 'java-time-jsptags'
pom.withXml {
asNode().children().last() + {
resolveStrategy = Closure.DELEGATE_FIRST
name 'Java 8 java.time JSP tags'
description 'JSP tag support for Java 8 java.time (JSR-310)'
url 'https://github.com/sargue/java-time-jsptags'
scm {
connection 'scm:git:git#github.com:sargue/java-time-jsptags.git'
developerConnection 'scm:git:git#github.com:sargue/java-time-jsptags.git'
url 'git#github.com:sargue/java-time-jsptags.git'
}
licenses {
license {
name 'The Apache License, Version 2.0'
url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
}
}
developers {
developer {
id 'sargue'
name 'Sergi Baila'
email 'sargue#gmail.com'
}
}
}
}
}
}
}
bintray {
user = BINTRAY_USER
key = BINTRAY_KEY
publications = ['MyPublication']
pkg {
repo = 'maven'
name = 'java-time-jsptags'
licenses = ['Apache-2.0']
vcsUrl = 'https://github.com/sargue/java-time-jsptags.git'
version {
name = project.version
desc = 'Java 8 java.time JSP tags'
gpg {
sign = true
passphrase = BINTRAY_GPG
}
}
}
}
You can find the result of the latest publication on my public Bintray maven repository. You can compare it to the files for the same version currently available on Maven Central.
Congratulations if you are reading this so far, because I haven't formulated ANY question yet. Sorry about that.
My questions:
Is the gradle build script correct and the proper/canonical way? Given that the library is quite simple I found the build script huge and clunky. It is supposed to be easier and it even has a gradle plugin. But the new script is longer than the maven central one.
What about the *.md5 and *.sha1 files? Will be generated by JCenter, Maven Central, the sync proces... or should I do it?
There is some way of testing all these without publishing an actual version of the library given that there is no unpublish capabilities on the repositories? (and for a good reason, eh? leftpad anyone?).
First, great job figuring it out. It looks good and works good.
It's bigger than the other one not because you use Bintray instead of Central, but because you use maven-publish plugin instead of maven, and being more powerful, the config is a bit more verbose. You can use Bintray (and the bintray plugin) with both maven and maven-publish, whatever you prefer.
Re testing it – you can always run a test build against your private repository (click in the Set Me Up button to get instructions on how to set up your Maven and/or Gradle to resolve from it).
Another validation will be syncing to Maven Central. It will fail if something is wrong with your package metadata.
Re md5 and sha1, we don't see a reason to store computable metadata as files on a modern distribution platform, but we send them to Maven Central when we sync.
My project has dependencies configured through gradle. I would like to add the following dependency:
compile group: 'org.restlet.jse', name: 'org.restlet.ext.apispark', version: '2.3.1'
Which can be found in the following repository (which I have added to my build.gradle):
maven {
url "http://maven.restlet.org"
}
However when I do that I get the following error:
Could not find org.restlet.jse:org.restlet.lib.swagger-models:1.5.0-SNAPSHOT.
http://maven.restlet.org/org/restlet/jse/org.restlet.lib.swagger-models/1.5.0-SNAPSHOT/maven-metadata.xml
http://maven.restlet.org/org/restlet/jse/org.restlet.lib.swagger-models/1.5.0-SNAPSHOT/org.restlet.lib.swagger-models-1.5.0-null-null.pom
http://maven.restlet.org/org/restlet/jse/org.restlet.lib.swagger-models/1.5.0-SNAPSHOT/org.restlet.lib.swagger-models-1.5.0-null-null.jar
Required by: org.restlet.jse:org.restlet.ext.apispark:2.3.1
I can see that the jar is in fact in the repository however Gradle is not looking for it in the right location for reasons unknown to me. Why is it not using the version in the filename but rather 1.5.0-null-null.
I have made a made a Maven project with the same dependency defined in the pom.xml which works.
Link to working pom.xml that has same dependency
How can this issue be resolved? I'm at this point also interesting in more manual solutions :) Thank you.
Diagnosis
It seems to be related to snapshot "uniqueness". For information on Maven repositories, snapshots artifacts can be deployed "unique" or "non-unique".
Unique snapshots: Each time you deploy a snapshot, it is tagged with a timestamp and a buildNumber, these timestamp and buildNumber are written in the maven-metadata.xml file and they are appended to its name that ends up like: artifactName-version-timestamp-buildNumber.jar.
Non-unique snapshots: Each time you deploy a snapshot it overwrites the previous version, his name ends up like: artifactName-version.jar.
It is recommended to use unique snapshot as one can refer precisely to one version of the artifact if needed.
The problem is that "http://maven.restlet.org" seems to use non-unique snapshots and sadly, gradle seems to have problems to deal with non-unique snapshots: https://issues.gradle.org/browse/GRADLE-3164.
If you look at http://maven.restlet.com/org/restlet/jse/org.restlet.lib.org.restlet.lib.swagger-models/1.5.0-SNAPSHOT/maven-metadata.xml you can clearly see null in timestamp and buildNumber tags:
<metadata>
[...]
<versioning>
<snapshot>
<timestamp>null</timestamp>
<buildNumber>null</buildNumber>
</snapshot>
<lastUpdated>null</lastUpdated>
</versioning>
</metadata>
I think that's where the "null-null" comes from.
Solution 1 - flatDir
To deal with it you can manually download the artifact, put it in a directory, for example "lib" and create a flatDir repository:
repositories {
[...]
flatDir {
dirs 'lib'
}
[...]
}
It's not an ideal solution, but it works.
Solution 2 - jcenter repository
Suggested by Opal
Add the jcenter repository that contains your missing dependency and that Gradle handles well.
Since Gradle 1.7 you can simply define it with:
repositories {
[...]
jcenter()
[...]
}
It seems that you need other repositories to download all the dependencies. Probably maven handle this transparently. The following script downloads all dependencies successfully when cp task is run:
apply plugin: 'java'
configurations {
lol
}
repositories {
jcenter()
mavenCentral()
maven {
url "http://maven.restlet.org"
}
maven {
url "https://repository.mulesoft.org/nexus/content/repositories/public/"
}
}
dependencies {
lol group: 'org.restlet.jse', name: 'org.restlet.ext.apispark', version: '2.3.1'
}
task cp(type: Copy) {
from configurations.lol
into 'deps'
}
How to Publish (deploy) local (.war .jar) files to Artifactory using Gradle version 1.12?
Dear all
I'm having a hard time trying to make this because of the older version of Gradle that I can not change because specifications, I would be very gratefully if someone can help me with this code.
What I have done till now:
buildscript {
repositories {
maven { url 'http://jcenter.bintray.com' }
}
dependencies {
classpath(group: 'org.jfrog.buildinfo', name: 'build-info-extractor-gradle', version: '3.0.1')
}
}
apply plugin: com.jfrog.artifactory-upload'
artifactory {
contextUrl = 'http://my.domain.com/artifactory/'
resolve {
repository {
repoKey = 'remote-deploy'
maven = true
}
}
}
NOTE: I don't know how to set my the local files to be uploaded but I read that I can use something like this "$rootDir\build\lib\buildProject.war"
With the suggestions I made this changes in my code:
apply plugin: 'com.jfrog.artifactory-upload'
apply plugin: 'maven-publish'
apply plugin: 'maven'
apply plugin: 'distribution'
buildscript {
repositories {
maven { url 'http://jcenter.bintray.com' }
}
dependencies {
classpath(group: 'org.jfrog.buildinfo', name: 'build-info-extractor-gradle', version: '2.2.5')
}
configurations {
published
}
}
artifactoryPublish.skip = true
task sourceJar(type: Jar){
from file("build/libs/"+project.archivesBaseName2+".jar")
classifier = 'sources'
}
artifacts{
archives sourceJar
published sourceJar
}
artifactory {
contextUrl = 'http://www site com/artifactory/'
publish {
contextUrl = 'http://www site com/artifactory/' //The base Artifactory URL for the publisher
//A closure defining publishing information
repository {
repoKey = 'jarDeploy'
username = 'user'
password = 'pass'
}
defaults{
//This closure defines defaults for all 'artifactoryPublish' tasks of all projects the plugin is applied to
properties{
//Optional closure to attach properties to artifacts based on a list of artifact patterns per project publication
mavenJava 'org.jfrog:*:*:*#*', key1: 'val1'
publicationName 'group:module:version:classifier#type', key1:'value1', key2:'value2'
}
publishBuildInfo = true //Publish build-info to Artifactory (true by default)
publishArtifacts = true //Publish artifacts to Artifactory (true by default)
publishPom = true //Publish generated POM files to Artifactory (true by default).
publishIvy = false //Publish generated Ivy descriptor files to Artifactory (true by default).
}
}
resolve{
contextUrl = 'http://www site com/artifactory/' //The base Artifactory URL for the resolver
repository{
repoKey = 'jarDeploy' //The Artifactory (preferably virtual) repository key to resolve from
username = 'user' //Optional resolver user name (leave out to use anonymous resolution)
password = 'pass' //The resolver password
maven = true //Resolve Maven-style artifacts and descriptors (true by default)
}
}
}
Now I see Build publications on Arctifactory but are empty no files to download
[buildinfo] Properties file path was not found! (Relevant only for builds running on a CI Server)
Creating properties on demand (a.k.a. dynamic properties) has been deprecated and is scheduled to be removed
in Gradle 2.0. Please read http://gradle.org/docs/current/dsl/org.gradle.api.plugins.ExtraPropertiesExtensi
on.html for information on the replacement for dynamic properties.
Deprecated dynamic property: "publishPom" on "task ':api:artifactoryPublish'", value: "true".
Deprecated dynamic property: "publishIvy" on "task ':api:artifactoryPublish'", value: "false".
Deprecated dynamic property "publishPom" created in multiple locations.
Deprecated dynamic property "publishIvy" created in multiple locations.
:webapp:artifactoryPublish
Deploying build info to: http://www site com/artifactory/api/build
Build successfully deployed. Browse it in Artifactory under http://tc-scm.bitnamiapp.com/artifactory/webapp/
builds/leadgnome-services/1423748387989/2015-02-12T09:39:45.642-0400/
BUILD SUCCESSFUL
Artifactory plugin uploads a file set that is prepared by another plugin. Considering your version of Gradle, that will probably be the maven plugin.
maven plugin creates and populates a configuration (usually called archives) which contains the files it built. This configuration needs to be specified in the artifactory closure.
You can see number of examples here.
P.S. The 3.0.1 version of the plugin won't probably work with such and old Gradle. Please check the docs for the compatibility matrix.