Setting dynamic password from Maven - maven

We've started using an AWS CodeArtifact Maven repository. Before connecting, developers must run a command ("aws") to acquire a temporary access token. How can I configure Maven to acquire and use this token automatically, without requiring running a script, configuring an IDE or changing the simple command line "mvn install"?
Maybe there's a trick I'm overlooking.
The token must be "interpolated" in the element <server>/<password> in settings.xml. This file will pre-process either an environment variable ({$env.token}) or a Java system property ({$token}). It will not process a project property.
The repository password cannot be specified within the POM file.
The settings.xml file cannot use project properties.
The exec-maven-plugin cannot set an environment variable in the parent process (Windows). It can write to a file.
The properties-maven-plugin cannot set a dynamic system property (e.g., from a file or script output).
The surefire plugin binds to the test phase and forks a JVM.
The Windows setx command does not affect the running process.
UPDATE: Maven downloads repository metadata before the first phase, so no plugin will solve the problem.

Related

Jenkins job unable to access an environment variable

I have a project that is setup as a job to build in Jenkins.
This project has multiple Maven modules.
One of the Maven module has a Maven task, which runs a Java program.
This Java program requires an environment variable which is available in the system.
When I run the Maven build cycle for that module locally in the terminal of the same system, the Java program is able to read the environment variable.
However in the Jenkins build, the Maven task fails as it is not being able to access that environment variable.
Is there anything else that I need to make this env variable visible to Jenkins Maven. I have tried restarting Jenkins after setting the env var, but to no avail.

Where to save the setting-security.xml file to use Maven encryption?

We are using TeamCity 9.1 and the default bundled Maven version 3.0.5
In the build, we are using Maven to interact with a Nexus server.
We would like to encrypt the password in the Maven settings.xml file as described in this article:
http://maven.apache.org/guides/mini/guide-encryption.html
This requires a settings-security.xml file which should be in the same folder as the Maven settings.xml one.
The setting.xml file is saved in TeamCity, and deployed to the server as a custom "User settings selection" file - so I don't know where it is being deploy to on the agent.
Where should we save the settings-security.xml file ?
Should this be manually deployed to all the agents? and if so, in which folder should it be?
(We have both Windows and Linux agents)
I'm not sure what is the best practice to use an encrypted Maven password in TeamCity, so I'd appriciate any help.
Thanks
"I don't know where it is being deploy to on the agent" .. You can find this within the build log output .. Just search for settings.. With User settings file, they are typically stored in a temp directory in the build agent.
When you attempt to encrypt your password using (as per the encryption guide):
mvn --encrypt-password my_password
It expects to find: settings-security.xml; if this isn't present you will get.
[ERROR] Error executing Maven.
[ERROR] java.io.FileNotFoundException: /home/krbuild/.m2/settings-security.xml (No such file or directory)
[ERROR] Caused by: /home/krbuild/.m2/settings-security.xml (No such file or directory)
So the security file needs to be stored on each agent on which you intend to run your build configuration (not in VCS). There is still no dedicated support for this feature; see TW-39595
The work around would be to set an agent property, e.g.
path.to.maven.security=/path/to/file/security-settings.xml
Then refer to it in your Maven build step:
-Dsettings.security=%path.to.maven.security%

How do I set up a TeamCity build job to execute a maven job with no pom

We have an in-house developed MOJO that generates content and doesn't require you to have an existing project or POM. Think of the maven archetype plugin, where you can just run mvn [mojo]:[goal] and have maven just execute that goal without a POM.
This MOJO connects to a specific database instance in a specific environment, and generates some metadata for the contents of the database, so our testers can inspect the metadata and locate production-like data that has certain attributes they need for a given test.
When you execute the metadata mojo, maven resolves the MOJO from the available repo's (in our case an Artifactory repo), and it then does its work and returns. It does not create any artifacts or other outputs.
We use TeamCity as our CI server, but it also has metadata generation jobs so with one click a dev can kick of a metadata generation job against a specific database.
The problem with this is the Maven runner in TeamCity requires a POM. If TC hasn't already checked out a project from a VCS, or the project it's checked out doesn't have a POM, the maven runner won't do anything. In this case, there is nothing to check out (the MOJO is resolved from Artifactory) so there is no POM.
I can set up the TC job to use the Command Line runner and have it execute, say, mvn com.example:metadata-generate -DenvironmentName=UAT1, but then it's impossible to specify the maven settings file that maven should use.
So my question is, how do I do this? Is it possible to have the maven runner execute an arbitrary maven command without needing a POM? Alternatively, using the Command line runner, is it possible to have a TC job copy a specific maven settings file to the build agent so it can be referenced in the maven command as mvn com.example:metadata-generate -DenvironmentName=UAT1 -s {path-to-settings-file}?
So its turns out that TC handles pom-less maven builds just fine. My problem was that the MOJO was not declared to not require a project.
Comparing my MOJO with the MavenArchetypePlugin source, I needed to declare my MOJO with the class level javadoc tag #requiresProject false.
Once I had that in place, TC ran my pom-less job perfectly well. All I had to do was clear the Path to POM file: field in the TC build configuration and leave it blank.
You can customize the name of the pom file that you use as an argument into the maven build-step in the teamcity and use this as the second "build step".Lets call the parameter as pom.file.name
In the first step , resolve all the in-house dependencies that you have and set the name of the pom file you want to execute into the variable pom.file.name
If you want to know more about how to change tha value of a variable in teamcity, you can read about it here

Maven local repository setting being overridden

My local maven build has been failing due to plugin dependencies not resolving. I've found on SO that this is likely caused by the correct settings not being picked up. So I ran mvn clean install -X to check which settings files are being used. The relevant part of the output from debug is:
[DEBUG] Reading global settings from c:\Maven\apache-maven-3.2.5\conf\settings.xml
[DEBUG] Reading user settings from h:\.m2\settings.xml
[DEBUG] Using local repository at C:\Maven\apache-maven-3.2.5\repo
The local repository is defined in both the global and local settings.xml as:
<localRepository>C:\.m2\repository\</localRepository>
I've been able to build successfully by overriding the local repository via the command line:
mvn clean install -Dmaven.repo.local=my/local/repo
My M2_HOME environment variable is C:\Maven\apache-maven-3.2.5
The command line fix is fine as a workaround but it's not ideal. The local repository is not being defined in the pom.xml.
Other than the settings file, is there anywhere else that the local repository can be defined, and is therefore overriding the configuration in settings.xml?
There are three (and a half) ways how you can configure your local repo:
Globally in <MAVEN_HOME>/conf/settings.xml
per User in <USER_HOME>/.m2/settings.xml
per command line arg: mvn clean install -Dmaven.repo.local=my/local/repo
per environment Variable MAVEN_OPTS: You can set your MAVEN_OPTS to set the maven.repo.local variable for maven operations. It's kind of like passing the environment variable directly, but for all mvn calls. See Is there a way to tell maven where to place the artifacts?
The MAVEN_OPTSway should be what you're looking for.

Jenkins - How to pass values from pom.xml to downstream job (free style)

I've set up 2 free style jobs, build-app and deploy-app. build-app poll the scm and builds the app, which is Maven based, and install the artifact in a web server (internal repository server), then it calls deploy-app. I would like to pass the version of the pom file () to the downstream job so it can download the correct artifact and install it on the machine. I found some answers suggesting put the version string in a properties file and use InjectEnv plugin, but I prefer read it from the pom itself. Any ideas?
Thanks!
When you build inside Maven, you have access to the pom file version as ${program.version} and can do anything you wish with it.
The downstream freestyle job can also run Maven using the same pom but a different target. The version should be the same if you take care to keep it from changing in the interim. (This suggests a procedure that should always be followed.)
So, for example, that Maven target can run a Groovy script or an Ant script that will pick up the correct file from the repo and deploy it.

Resources