I know this is subjective question and it will be closed most probably. But I don't know where to ask this question to get answer.
There is one small annoying thing with maven android plugin - it modifies original manifest file and if you are running maven in working folder your vcs is proposing you to commit these changes.
Example: we have several environments to run if I build build with beta environment it will modify app name in AndroidManifest.xml.
This is could be easily solved by copying original manifest and give reference to the copy to the android maven plugin. But I've decided to make it's more easy for developer so plugin will do this automatically except situation when developer specifies that he wants this update to be done under original manifest.
It was easy to modify functionality (copy file and replace property that keeps reference to the File) but the problem is that I need to pass this property to other mojos.
The property defined in abstract mojo AbstractAndroidMojo which doesn't have execute method. And all other mojos extend this class. The definition look like this:
/**
* The <code>AndroidManifest.xml</code> file.
*
* #parameter default-value="${project.basedir}/AndroidManifest.xml"
*/
protected File androidManifestFile;
I followed this answer:
private void updatePluginConfiguration ( String newManifestFileValue )
{
for ( Plugin plugin : project.getBuild().getPlugins() )
{
if ( plugin.getArtifactId().equals( "android-maven-plugin" ) )
{
Xpp3Dom configuration = (Xpp3Dom) plugin.getConfiguration();
Xpp3Dom manifestFileParameter = configuration.getChild( "androidManifestFile" );
if ( manifestFileParameter == null )
{
manifestFileParameter = new Xpp3Dom( "androidManifestFile" );
configuration.addChild( manifestFileParameter );
}
manifestFileParameter.setValue( newManifestFileValue );
break;
}
}
}
But unfortunately this doesn't work. There are many explicit ways to make it working but all of them will require to change all current mojos.
I wonder if someone knows why the answer doesn't work or how to make it working.
The code of updated plugin could be found here:
https://github.com/emartynov/maven-android-plugin/tree/keep-android-manifest
Thanks for everyone who read till the end.
Are you running your goal within the same lifecycle phase? If not, in the post you provided it's written:
Note: Any configuration changes are discarded at the end of the current phase.
The other thing to consider: are the goals run in order you expect? Have a look at this post: http://www.mkyong.com/maven/maven-plugin-execution-order-in-same-phase/ - Perhaps it's the ordering of plugins that you're having problems with.
Other thing to consider: perhaps you'd prefer a cleaner solution - to add such feature to the android-maven-plugin? Manfred Moser is usually open to proposals backed by pull requests ;)
I'll be most propably doing the very same thing in my plugin. The only difference is that I'm reusing goals from maven-dependency-plugin to copy dependencies within my custom plugin lifecycle. I'm trying to make a plugin for InstallShield projects building.
Related
I try to configure my project from a custom plugin. I want to set a default URL and credentials for the publishing extension if plugin maven-publish is applied. I need know whether the plugin is applied or not.
In a function of my custom plugin I want to write something like this (not actual code)
project.afterPluginApply {
if (project.pluginc.any("maven-publish")) {
setDefaultUrl()
}
}
I don't want use project.pluginManager.withPlugin("maven-publish")
because I want see all applied plugins for the project (I want to configure many extensions and some value may change if whether or not other plugins are applied).
I don't want use subProject.afterEvaluate {} because, if I configured a field in build.gradle.kts I would overwrite it with my plugin.
I could write some dirty code like this
(it.pluginManager as DefaultPluginManager).idMappings[DefaultPluginId.unvalidated("maven-publish")] != null
But I'd rather like to find a better solution.
I have a gradle project with a gradle.properties file. One of the properties displays the current version of my project and I would like to include this proprerty in the project's README.md on github. How can I do this?
The Gradle Copy task is capable of such functionality. Simply use its expand method to specify the values to insert. Of course you'll need to define a template somewhere in your project:
task copy(type: Copy) {
from 'src/templates'
into "$buildDir"
include 'projectinfo.html.template'
rename { file -> 'projectinfo.html' }
expand(project: project, title: 'ProjectInfo', generated: new Date())
}
I took this example from a post of Mr. Hakis Blog.
This functionality is based on the Groovy SimpleTemplateEngine. Of course you can simply use this class or any other templating engine to implement the required functionality in your build script on your own.
#KrispyK,
I believe this would be possible. You could write a simple serverless script using webtask (or similar service) that reads your gradle properties file and creates a custom status badge using a badge service like shields.io. Finally, you would only need to add this badge to your markdown file.
Please refer to this webtask script that I created. This calls an external API and uses the data returned by that API to create a custom Shields badge.
I've then used this badge in my readme file.
Hope this helps.
I am building a whole suite of plugins for a new build pipeline. I have certain metadata that if it is not present in the build file, i want it to fail. for example
inventory_link: '124djsj39r'
This links the build back to our inventory system. If that tag is not present in the build, I don't want the developer to be able to do squat. no tests, no compiles, no builds, no nothing. I want the project to be a worthless group of files.
Now reading the docs, i understand the build lifecycle, sorta. There's an init, config, execute, clean. basically How do I configure a custom plugin (writing it as an independant jar) so that a validation task executes automatically that checks to make sure this tag is present at the end of the configuration phase of the build lifecycle?
how does multi-project builds effect this? each individual project of a multiproject build must have this tag as well.
EDIT
I was able to get back to this. I got this to run and it executes the closure, problem is project_hash always null. Now granted, I'm using testkit so i may be dealing with something weird in testkit. see anything wrong?:
#Override
void apply(Project project) {
this.project = project
def metadata = new Metadata()
// Create and install the extension object
project.extensions.create('metadata', MetadataExtension, metadata)
def ignore = project.tasks.create(METADATA_REPORT, MetadataReportTask)
ignore.group = PLUGIN_GROUP
ignore.description = 'Gets the detailed information for this project and formats it into a user readable report'
project.afterEvaluate {
throw new InvalidUserDataException(project.metadata.metadata.project_hash)
}
}
Any code you put in the main body of your build.gradle script will run during the configuration phase. If you want it done last, just put it at the bottom.
if (inventory_link == null) //or whatever check makes sense
throw new GradleException('Hey, you need to set the inventory_link')
Note that clean is not a "phase" in the gradle build lifecycle like init, config, execute. It is achieved via a task.
I am not using the new maven-publish plugin which looks awesome and would work perfectly for this use case because I keep reading how no one can get the signing of the jars to work (though I am open to an answer that explains that as well as I haven't found a blog on that saying it would work at this point).
Soooo, I would like easily to switch between publishing locally for testing and remotely. My current build.gradle file is
https://github.com/deanhiller/webpieces/blob/master/build.gradle
which has a commented out local repo and I keep flipping commenting on and off and would rather like to avoid that. ie. these repos...
//repository(url: "file://localhost/tmp/myRepo/")
repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
authentication(userName: sonatypeUsername, password: sonatypePassword)
}
I read a post on doing something here but this failed with cryptic closure errors...
Configuring multiple upload repositories in Gradle build
I put that in my subprojects section but that didn't work at all. Ideally, using the graph whenReady sounds the best as it would be cool to only use remote repo if I am doing the release target. I can't seem to get any of this to work though.
thanks,
Dean
EDIT: I was wrong, the below is only half working right now as when I ./gradlew jar, then I get this error... (so some targets work and others not...ouch)
Cannot cast object 'task ':uploadArchives'' with class 'org.gradle.api.DefaultTask_Decorated' to class 'org.gradle.api.tasks.Upload'
I did figure out a work around though it seems weird as targets in running tasks list are hidden now depending on if a variable is set which seems a little odd. I would think there is probably a better way of doing this so all tasks are still listed, but for now my build file works by just doing a
if(project.hasProperty('projVersion')) {
//task I want to be able to run
} else {
//other task I want to run when no projVersion
}
so it works...the tasks are just invisible now until I do ./gradlew -PprojVersion=X to view them.
I want to package a Grails application for different brands. While generating a war file, I want to pass some custom parameter that refers to a certain brand and styles the application by loading the stylesheet for the brand.
I read online and one approach I found was with maven. I tried working with maven but I am stuck while initially compiling the application. The error is
Failed to execute goal org.grails:grails-maven-plugin:2.2.1:maven-compile
(default-maven-compile) on project foreAction: Forked Grails VM exited with error.
I am stuck as to what approach to take now. I searched for the above error and tried different solutions but nothing seems to work.
If there is a different way without using Maven I am willing to give it a shot.
You could always hook into the events using scripts/_Events.groovy and replace the appropraite CSS/assets. The documentation explains how to hook into build events.
Your code inside scripts/_Events.groovy might look something like this:
// This is called after the staging dir is prepared but before the war is packaged.
eventCreateWarStart = { name, stagingDir ->
// place your code here that copies your resources to the appropriate location in the staging directory.
Ant.copy(
file: System.getProperty('somePassedInFile'),
toFile: "${stagingDir}/assets/stylesheets/whatever.css",
overwrite: true
)
}
Then you can pass in the value of the source file from grails prod war like this:
grails prod war -DsomePassedInFile=/path/to/file.css
Hope this helps at least give you an idea of how you can accomplish this. (All written off the top of my head so beware of typos etc.)