Deploying to Maven

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Deploying to Maven

Rwanou
Deploying to Maven

Hi all,

I'm trying to customize my Maven deploying tasks.

Here's what I would like to do in one task:

Generate the WAR file, generate the sources of the WAR project (including WEB-INF) and the sources of the depending project sources, upload to maven all 3 jar files (2 sources and WAR file).

Depending on command line arguments, the WAR release (and WAR source) could have a classifier.
I wish to block the release, if it's not a SNAPSHOT and the dependencies contains a SNAPSHOT.

I can do some of the things, but I'm stuck with others. I'll post all my work, so people can criticize if I'm too far from best practice, and give ideas to people having the same needs.

Root gradle:

subprojects {

    usePlugin 'java'
    version '2.2.0.DEV13-SNAPSHOT'

    task sourcesJar(type: Jar) {
        from sourceSets.main.allSource
        // wont work because of GRADLE-704
        classifier = 'sources'
    }
}

WAR gradle:

task initConfiguration << {
    // creates a ConfigSlurper containing all kinds of settings if an environment was set as a command line parameter.
    deployConfig = // whatever
}

war.doFirst {
    if (project.hasProperty('deployConfig') {
        // wont work because of GRADLE-704
        war.classifier = deployconfig.environment

        // Do some other things on the war
    }
}

sourcesJar {
    // How can I add the default WEB-INF directory to my sources?
}

artifacts {
    archives war
    archives sourcesJar
}

uploadArchives {
    repositories.mavenDeployer {
        configuration = configurations.release // when I will need to deploy using WEB-DAV, configuration called 'release' is declared.

        repository(url: 'file://d:/erwan-dev/tmp/REPO')
        snapshotRepository(url: 'file://d:/erwan-dev/tmp/REPO-SNAPSHOT')
    }
}

def isSnapshotDependent() {
    def containsSnapshot = false
    // TODO I want to run the following only if i am releasing on the main repo.
    // should I check the presence of the string 'SNAPSHOT' in the projects version? How does the maven plugin knows that I'm uploading a SNAPSHOT or a main version?

    configurations.default.allDependencies.each { dep ->
        if (dep.version.indexOf('SNAPSHOT') > 0)
            containsSnapshot = true
    }
    return containsSnapshot
}

task release(dependsOn: initConfiguration)  << {
    // check that i'm not depending on a SNAPSHOT
    if (isSnapshotDependent()) {
        throw new GradleException("cannot release since dependencies contains a SNAPSHOT")
    }
    uploadArchives.execute() // is there a bug? Executing the task with the command line runs the 'war' task. Executing the same command from another task will not launch the 'war' task.

    // unless a parameter says NO
    uploadSources.execute() // knowing that I would wish for both this project and the "service" project sources to be uploaded. Maybe ServiceProject.uploadSources.execute() ?

}


As you see, I'm a little stuck until issue 704 is fixed (I will DL the latest trunk version soon).
My main concern is to create a task that will launch the 'uploadArchives' task. As I explained in a comment, right now launching 'uploadArchives' from another task wont trigger the 'war' task. Maybe this is a bug. I could get away from that by including the dependency manually of my custom task on 'war' and 'sourcesJar' tasks.

I wish there was an easy way to detect that a library version is a SNAPSHOT, including my own project.

The documentation on Maven plugin is, how to say, evasive. Maybe I could post this draft on the wiki, so the community can bring their experience to it?

Thanks in advance for the community help,
Erwan

Reply | Threaded
Open this post in threaded view
|

Re: Deploying to Maven

hans_d
Administrator

On Nov 24, 2009, at 2:54 AM, <[hidden email]> <[hidden email]> wrote:

Hi all,

I'm trying to customize my Maven deploying tasks.

Here's what I would like to do in one task:

Generate the WAR file, generate the sources of the WAR project (including WEB-INF) and the sources of the depending project sources, upload to maven all 3 jar files (2 sources and WAR file).

Depending on command line arguments, the WAR release (and WAR source) could have a classifier.
I wish to block the release, if it's not a SNAPSHOT and the dependencies contains a SNAPSHOT.

I can do some of the things, but I'm stuck with others. I'll post all my work, so people can criticize if I'm too far from best practice, and give ideas to people having the same needs.

Root gradle:

subprojects {

    usePlugin 'java'
    version '2.2.0.DEV13-SNAPSHOT'

    task sourcesJar(type: Jar) {
        from sourceSets.main.allSource
        // wont work because of GRADLE-704

GRADLE-704 is fixed in trunk.

        classifier = 'sources'
    }
}

WAR gradle:

task initConfiguration << {
    // creates a ConfigSlurper containing all kinds of settings if an environment was set as a command line parameter.
    deployConfig = // whatever
}

war.doFirst {
    if (project.hasProperty('deployConfig') {
        // wont work because of GRADLE-704
        war.classifier = deployconfig.environment

        // Do some other things on the war
    }
}

sourcesJar {
    // How can I add the default WEB-INF directory to my sources?

       from(projectDir) {
           include "path_to_webinf"
       }
       // simply include "path_to_webinf" should do the job also. But there is a bug that prevents this from working ATM.

}

artifacts {
    archives war
    archives sourcesJar
}

uploadArchives {
    repositories.mavenDeployer {
        configuration = configurations.release // when I will need to deploy using WEB-DAV, configuration called 'release' is declared.

        repository(url: 'file://d:/erwan-dev/tmp/REPO')
        snapshotRepository(url: 'file://d:/erwan-dev/tmp/REPO-SNAPSHOT')
    }
}

def isSnapshotDependent() {
    def containsSnapshot = false
    // TODO I want to run the following only if i am releasing on the main repo.
    // should I check the presence of the string 'SNAPSHOT' in the projects version? How does the maven plugin knows that I'm uploading a SNAPSHOT or a main version?

    configurations.default.allDependencies.each { dep ->
        if (dep.version.indexOf('SNAPSHOT') > 0)
            containsSnapshot = true
    }
    return containsSnapshot
}

We use the Ant Maven tasks under the hood for deploying. The check the full artifact name for the 'SNAPSHOT' pattern and decide based on that whether to deploy to 'repository' or 'snapshotRepository'. But they don't make this information available. 

task release(dependsOn: initConfiguration)  << {
    // check that i'm not depending on a SNAPSHOT
    if (isSnapshotDependent()) {
        throw new GradleException("cannot release since dependencies contains a SNAPSHOT")
    }
    uploadArchives.execute() // is there a bug? Executing the task with the command line runs the 'war' task. Executing the same command from another task will not launch the 'war' task.

    // unless a parameter says NO
    uploadSources.execute() // knowing that I would wish for both this project and the "service" project sources to be uploaded. Maybe ServiceProject.uploadSources.execute() ?

}

What I would do is the following:

uploadArchives {
   if (gradle.taskGraph.hasTask('release') {
      if (isSnapshotDependent()) throw ...
   }
   ...
}

task release{dependsOn: initConfiguration, uploadArchives) {
   // do nothing at the moment. 
}

uploadArchives will upload all artifacts that are only distinguished by the classifier.


As you see, I'm a little stuck until issue 704 is fixed (I will DL the latest trunk version soon).
My main concern is to create a task that will launch the 'uploadArchives' task. As I explained in a comment, right now launching 'uploadArchives' from another task wont trigger the 'war' task. Maybe this is a bug.

I don't think this is a bug. There are other, cleaner, ways to achieve this I think. Usually you shouldn't be forced to use the execute method at all.

I could get away from that by including the dependency manually of my custom task on 'war' and 'sourcesJar' tasks.

I wish there was an easy way to detect that a library version is a SNAPSHOT, including my own project.

I guess the Maven plugin could provide such a functionality. Could you file a Jira?

The documentation on Maven plugin is, how to say, evasive. Maybe I could post this draft on the wiki, so the community can bring their experience to it?

That would be excellent.

- Hans

--
Hans Dockter
Gradle Project Manager

Thanks in advance for the community help,
Erwan


Reply | Threaded
Open this post in threaded view
|

RE: Deploying to Maven

Rwanou
Thanks for the answers Hans.
As promissed, I created a page inside the examples section of Gradle's Confluence. I cover there not only the Maven deploy part, but also environment configuration, which I started to speak about earlier this year.
For all of you who are interested in the problems raised by this topic, please have a look here for some answers:
 
 
But of course you're not gonna get out of here so easily as I have some other questions :) (most of them raised as TODOs in the previous link). I'll try to ask only the ones that would take me too long dig for, and I'll update the WIKI with the answer I get from myself eventually.
 
1) any SVN plugin? Anyway to Gradelly commit, tag or even branch something?
2) Anyway to change the project version number from the command line?
3) disable the disabling of tests. Meaning that skipping the tests would NOT be possible when running some definite tasks?
 
4) I noticed some behaviour with my multiproject tasks.
Here's roughly the structure:
ROOT/
    SERVICE/
    WEB-LAYER/
        WAR-PROJECT/
 
WEB-LAYER is not a project, just a folder containing projects. When I run at the root "$gradle release", then the output would be:
:RASFF-core:compileJava
:RASFF-core:bind
[ant:echo] Binding with jibx...
:RASFF-core:processResources
:RASFF-core:classes
:RASFF-core:jar
:RASFF-core:uploadDefaultInternal
:RASFF-core:uploadArchives
:RASFF-core:release
:RASFF-web:compileJava  ???????
:RASFF-web:processResources  ????????
:RASFF-web:classes  ??????????
:RASFF-web:jar SKIPPED ?????????
:RASFF-web:uploadArchives SKIPPED ???????
:RASFF-web:release ?????????
:RASFF-web:RASFF-web:compileJava
:RASFF-web:RASFF-web:processResources
:RASFF-web:RASFF-web:classes
:RASFF-web:RASFF-web:initConfiguration
no environment specified, skipping.
:RASFF-web:RASFF-web:war
version is: 2.2.0.DEV13-BUILD-6-SNAPSHOT
:RASFF-web:RASFF-web:uploadArchives
:RASFF-web:RASFF-web:release
 
As you see, I had to manually disable the 'RASFF-web' tasks. Why would Gradle run the tasks though I never declared RASFF-web as a project? This is not a blocker since I disabled the tasks, just a question of mine.
 
Thanks for your help,
Erwan
Reply | Threaded
Open this post in threaded view
|

RE: Deploying to Maven

Rwanou
OK, some other question are being raised for this "Maven deploy" feature.
 
I've solved the version issue by parsing my properties in a "gradle.taskGraph.whenReady" closure. Look at example for more details. Other questions still remain.
 
But I have another one here that is a bit tricky to me. Reading chapter 31 didn't really help.
In a multiple project environment, is it possible to have a task depend on a task from all the others? let me explain, imagine this:
Project/
    Service/
    Web/ (depends on Service)
 
task release(dependsOn: [test, uploadArchives]{}
 
executing this will have (roughly)
service:test
service:uploadArchives
service:release
web:test
web:uploadArchives
web:release
 
So, what if web:test has errors? well service is still released... Maven will suffer an incomplete release.
 
anyway to have things done this way?
(service:build)
service:test
(web:build)
web:test
service:uploadArchives
service:release
web:uploadArchives
web:release
 
I don't really see how I should manipulate the DAG without defining manually the depends to all projects...
 
Thanks for your help


From: [hidden email] [mailto:[hidden email]]
Sent: Wednesday, November 25, 2009 3:25 PM
To: [hidden email]
Subject: RE: [gradle-user] Deploying to Maven

Thanks for the answers Hans.
As promissed, I created a page inside the examples section of Gradle's Confluence. I cover there not only the Maven deploy part, but also environment configuration, which I started to speak about earlier this year.
For all of you who are interested in the problems raised by this topic, please have a look here for some answers:
 
 
But of course you're not gonna get out of here so easily as I have some other questions :) (most of them raised as TODOs in the previous link). I'll try to ask only the ones that would take me too long dig for, and I'll update the WIKI with the answer I get from myself eventually.
 
1) any SVN plugin? Anyway to Gradelly commit, tag or even branch something?
2) Anyway to change the project version number from the command line?
3) disable the disabling of tests. Meaning that skipping the tests would NOT be possible when running some definite tasks?
 
4) I noticed some behaviour with my multiproject tasks.
Here's roughly the structure:
ROOT/
    SERVICE/
    WEB-LAYER/
        WAR-PROJECT/
 
WEB-LAYER is not a project, just a folder containing projects. When I run at the root "$gradle release", then the output would be:
:RASFF-core:compileJava
:RASFF-core:bind
[ant:echo] Binding with jibx...
:RASFF-core:processResources
:RASFF-core:classes
:RASFF-core:jar
:RASFF-core:uploadDefaultInternal
:RASFF-core:uploadArchives
:RASFF-core:release
:RASFF-web:compileJava  ???????
:RASFF-web:processResources  ????????
:RASFF-web:classes  ??????????
:RASFF-web:jar SKIPPED ?????????
:RASFF-web:uploadArchives SKIPPED ???????
:RASFF-web:release ?????????
:RASFF-web:RASFF-web:compileJava
:RASFF-web:RASFF-web:processResources
:RASFF-web:RASFF-web:classes
:RASFF-web:RASFF-web:initConfiguration
no environment specified, skipping.
:RASFF-web:RASFF-web:war
version is: 2.2.0.DEV13-BUILD-6-SNAPSHOT
:RASFF-web:RASFF-web:uploadArchives
:RASFF-web:RASFF-web:release
 
As you see, I had to manually disable the 'RASFF-web' tasks. Why would Gradle run the tasks though I never declared RASFF-web as a project? This is not a blocker since I disabled the tasks, just a question of mine.
 
Thanks for your help,
Erwan