I'm running a CI pipeline in Azure DevOps with a Maven build step called "Download provided dependency JARs".
This step was working before, however it's suddenly giving me this error:
org.apache.maven.repository.LocalRepositoryNotAccessibleException: Could not create local repository at /testartifacts/m2repository
I'm also getting a warning:
##[warning]Could not parse the effective POM.
This is what it looks like in DevOps:
I've set it to clean the working directory before the build is run, but this didn't help.
From what I've read, it seems to be a permissions issue.
Shouldn't the build agent already have permissions?
I appreciate your help.
This is my pom.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>au.com.mycompany.perfunittests</groupId>
<artifactId>myapplication</artifactId>
<version>1.0-SNAPSHOT</version>
<profiles>
<!-- Load Test -->
<profile>
<id>profile.loadTest</id>
<!-- Test will only be chosen when -DtestType=load -->
<activation>
<!-- Test will be chosen when property testname is not supplied, i.e. the default -->
<property>
<name>!testname</name>
</property>
</activation>
<properties>
<testname>loadtest.myapplication</testname>
<isbenchmarktest>false</isbenchmarktest>
</properties>
</profile>
<!-- Benchmark Test for Common -->
<profile>
<id>profile.benchmarkTest.Common</id>
<activation>
<property>
<name>testname</name>
<value>unittest.myapplication.common</value>
</property>
</activation>
<properties>
<testname>unittest.myapplication.common</testname>
<isbenchmarktest>true</isbenchmarktest>
</properties>
</profile>
<!-- Benchmark Test for Configuration -->
<profile>
<id>profile.benchmarkTest.Configuration</id>
<activation>
<property>
<name>testname</name>
<value>unittest.myapplication.configuration</value>
</property>
</activation>
<properties>
<testname>unittest.myapplication.configuration</testname>
<isbenchmarktest>true</isbenchmarktest>
</properties>
</profile>
<!-- Benchmark Test for Dashboard - note this is legacy Dashboard API calls -->
<profile>
<id>profile.benchmarkTest.Dashboard</id>
<activation>
<property>
<name>testname</name>
<value>unittest.myapplication.dashboard</value>
</property>
</activation>
<properties>
<testname>unittest.myapplication.dashboard</testname>
<isbenchmarktest>true</isbenchmarktest>
</properties>
</profile>
<!-- Benchmark Test for Management -->
<profile>
<id>profile.benchmarkTest.Management</id>
<activation>
<property>
<name>testname</name>
<value>unittest.myapplication.management</value>
</property>
</activation>
<properties>
<testname>unittest.myapplication.management</testname>
<isbenchmarktest>true</isbenchmarktest>
</properties>
</profile>
</profiles>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- No need to run deploy lifecycle -->
<maven.deploy.skip>true</maven.deploy.skip>
<!-- No need to create a JAR -->
<jar.skipIfEmpty>true</jar.skipIfEmpty>
<maven.install.skip>true</maven.install.skip>
<!-- Run in perftest env unless overridden using -Denv -->
<env>perf</env>
</properties>
<repositories>
<repository>
<id>mycompanyproject-visualstudio.com-maven</id>
<url>https://mycompanyproject.pkgs.visualstudio.com/_packaging/maven/maven/v1</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>com.lazerycode.jmeter</groupId>
<artifactId>jmeter-maven-plugin</artifactId>
<version>2.8.6</version>
<executions>
<execution>
<id>jmeter-tests</id>
<goals>
<goal>jmeter</goal>
</goals>
</execution>
</executions>
<configuration>
<jmeterVersion>5.0</jmeterVersion>
<!-- JMX file for unittests lives in the same directory as pom.xml -->
<testFilesDirectory>${project.basedir}</testFilesDirectory>
<testFilesIncluded>
<jMeterTestFile>${testname}.jmx</jMeterTestFile>
</testFilesIncluded>
<!-- Need to save in CSV format for lightning plugin -->
<resultsFileFormat>csv</resultsFileFormat>
<!-- Don't append timestamp to JTL file, so lightning can find it more easily -->
<testResultsTimestamp>false</testResultsTimestamp>
<!-- Don't stop the test on a failure -->
<ignoreResultFailures>true</ignoreResultFailures>
<propertiesUser>
<env>${env}</env>
<url.myapplication>perfweb.myapplication.com</url.myapplication>
<unittest.path.resources>${project.basedir}</unittest.path.resources>
<unittest.path.testdata>${project.basedir}/data</unittest.path.testdata>
</propertiesUser>
<!-- Additional output JTL format for lightning plugin -->
<propertiesJMeter>
<httpclient.reset_state_on_thread_group_iteration>false</httpclient.reset_state_on_thread_group_iteration>
<jmeter.save.saveservice.print_field_names>true</jmeter.save.saveservice.print_field_names>
<jmeter.save.saveservice.successful>true</jmeter.save.saveservice.successful>
<jmeter.save.saveservice.label>true</jmeter.save.saveservice.label>
<jmeter.save.saveservice.time>true</jmeter.save.saveservice.time>
</propertiesJMeter>
<customPropertiesFiles>
<file>${project.basedir}/${testname}.threadgroups.conf</file>
</customPropertiesFiles>
<!-- Additional libraries (mostly) from jmeter-plugins.org -->
<jmeterExtensions>
<artifact>au.com.mycompany:timinglistener:0.2-SNAPSHOT</artifact>
<artifact>com.google.code.gson:gson:2.8.2</artifact>
<artifact>com.opencsv:opencsv:4.1</artifact>
<artifact>com.sumologic.plugins.log4j:sumologic-log4j2-appender:1.7</artifact>
</jmeterExtensions>
<jMeterProcessJVMSettings>
<xms>2048</xms>
<xmx>2048</xmx>
<arguments>
<argument>-Dunittest.path.logs=${project.build.directory}/jmeter/logs</argument>
<argument>-Dunittest.testname=${testname}</argument>
<argument>-Dlog4j.configurationFile=file://${project.basedir}/log4j2.xml</argument>
</arguments>
</jMeterProcessJVMSettings>
<downloadExtensionDependencies>true</downloadExtensionDependencies>
</configuration>
</plugin>
<plugin>
<groupId>uk.co.automatictester</groupId>
<artifactId>jmeter-lightning-maven-plugin</artifactId>
<version>1.5.0</version>
<executions>
<execution>
<goals>
<goal>lightning</goal>
</goals>
<configuration>
<mode>verify</mode>
<!-- Lightning XML definition file lives in the same directory as pom.xml -->
<testSetXml>${project.basedir}/${testname}.xml</testSetXml>
<!-- Test output JTL file written to target/jmeter/results/<testname>.csv -->
<jmeterCsv>${project.build.directory}/jmeter/results/${testname}.csv</jmeterCsv>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
It looks you ran your pipeline on self-hosted agent. Or you configured the maven to retrieve the dependencies from the local repository(in mvnsettings.xml, or .m2/settings.xml ). If you ran your pipeline on self-hosted agent. You can check if the local repo /testartifacts/m2repository exists.
If you run your pipeline on cloud agents, you need to find which setting files configured the the local repo, And remove the localRepository.
Then you might need to use Maven Authenticate task to provides credentials for Azure Artifacts feeds and external Maven repositories.
Add Maven Authenticate task at the top of your pipeline. And select your azure maven feed from the Feeds dropdown list
This task will store the credentials on a temp settings.xml file(with feed name as the server id, see below) on the agent, which will be used to authenticate the maven repository in the following maven task.
Noted: The repository id you specified in your pom.xml file(ie. see below highlighted) should be the same with the name of your azure artifacts maven feed. Or it will still fail to authenticate the feed in the follow maven task. for the server id in the temp settings.xml file created above is the feed name.
Turns out all I had to do was change the Agent Specification from ubuntu-18.04 to vs2017-win2016.
Related
I was trying to change configuration of the pom based on the active profile (dev, test, qa, prod). but every time it was calling the default one (prod)
I have given the profile info in VM arguments in intellij
arguments : -Dspring.profiles.active=dev
Decleration (in POM.xml)
<profiles>
<profile>
<id>dev</id>
<properties>
<currentRegion>run build_dev</currentRegion>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<currentRegion>run build_test</currentRegion>
</properties>
</profile>
<profile>
<id>qa</id>
<properties>
<currentRegion>run build_qa</currentRegion>
</properties>
</profile>
<profile>
<id>prod</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<currentRegion>run build_prod</currentRegion>
</properties>
</profile>
</profiles>
Usage(in POM.xml)
<build>
<plugins>
<plugin>
<executions>
<execution>
<configuration>
<arguments>${currentRegion}</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Every time, this is retuning run build_prod (the default one)
Actually i have combined the spring boot and angular for some testing purpose and i want to run the angular on environment with different environment.ts file , when i hardcode the arguments in pom like run build_dev/test it works file , i want to automate it arguments based on the active profile .
Any Suggestions/Solution is highly appreciated.
I want to override a particular plugin configuration that's defined in the pom.xml. I don't want to modify the pom.xml for various reasons. Is there a way to define a config attribute for that plugin in settings.xml that override corresponding pom.xml plugin config?
In the below example, you'll notice that the plugin xx-plugin is defined in profile1 in pom.xml. In my settings.xml I've already defined profile2 to override property prop1 from pom.xml. But how to override config3. I apologize if this is a silly question. I am a little new to maven.
This is what my pom.xml looks like:
<profile>
<id>profile1</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.xx.yyy</groupId>
<artifactId>xx-plugin</artifactId>
<executions>
<execution>
<id>xx-install</id>
<phase>install</phase>
<goals>
<goal>xx-install</goal>
</goals>
<configuration>
<config1>AAA</config1>
<config2>BBB</config2>
<config3>CCC</config3> <!-- I want to override this with value DDD -->
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
This is what my settings.xml looks like:
<profile>
<id>profile2</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<prop1>overriden-value</prop1> <!-- This works -->
</properties>
<!-- Somehow override config3 here -->
<!-- <config3>DDD</config3> -->
</profile>
AFAIK you can only override properties with settings.xml profiles. You'd have to change your plugin's configuration to use a property instead of a fixed value:
<!-- define your property -->
<properties>
<prop1>CCC</prop1>
</properties>
<profile>
<id>profile1</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.xx.yyy</groupId>
<artifactId>xx-plugin</artifactId>
<executions>
<execution>
<id>xx-install</id>
<phase>install</phase>
<goals>
<goal>xx-install</goal>
</goals>
<configuration>
<config1>AAA</config1>
<config2>BBB</config2>
<config3>${prop1}</config3> <!-- I want to override this with value DDD -->
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
Remember that profiles with activeByDefault set to true will get deactivated if any other profile gets activated in your build invocation. See http://maven.apache.org/guides/introduction/introduction-to-profiles.html
If you do not want to change the pom.xml for a plugin you can set the configuration as JVM parameter when running maven as stated in the Generic Configuration chapter of the Maven Guide to Configuring Plugins.
Example:
mvn my-plugin:my-goal -Dplugin.property=ABC
Example for the wildfly plugin (this is where I needed it and did not want to change the pom.xml of a demo project when deploying to a server group in a domain context):
mvn clean install wildfly:deploy -Dwildfly.serverGroups=<server-group-name>
The maven documentation also states that most plugins define help goals to explain users how to configure them.
Exaple for the wildfly plugin:
mvn wildfly:help -Dgoal=deploy -Ddetail
We have a gateway-client project that is part of a multi-module maven project. The gateway-client pom.xml is configured to create two main artifacts: gateway-client.jar and gateway-services-client.jar and deploy them to two separate Nexus repositories: the Releases repo and the 3rd Party repo respectively. This is done through a profile that is active by default:
<profile>
<!-- ====================================================================== -->
<!-- default Profile -->
<!-- This is the default profile which will run by default. This profile -->
<!-- produces two client artifacts: gateway-client and gateway-services-client -->
<!-- for the releases and thirdparty repositories respectively. -->
<!-- ====================================================================== -->
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<!-- ====================================================================== -->
<!-- default Profile Build plugins -->
<!-- ====================================================================== -->
<build>
<plugins>
<!-- ====================================================================== -->
<!-- default Profile Maven deploy plugin -->
<!-- ====================================================================== -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>deploy-thirdparty-jar</id>
<phase>deploy</phase>
<goals>
<goal>deploy-file</goal>
</goals>
<configuration>
<url>${nexus.url}/content/repositories/thirdparty</url>
<repositoryId>thirdparty</repositoryId>
<file>${project.build.directory}/${project.build.finalName}.${project.packaging}</file>
<groupId>${project.groupId}</groupId>
<artifactId>gateway-services-client</artifactId>
<version>${project.version}</version>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
</execution>
<execution>
<id>deploy-release-jar</id>
<phase>deploy</phase>
<goals>
<goal>deploy-file</goal>
</goals>
<configuration>
<url>${nexus.url}/content/repositories/releases</url>
<repositoryId>releases</repositoryId>
<file>${project.build.directory}/${project.build.finalName}.${project.packaging}</file>
<groupId>${project.groupId}</groupId>
<artifactId>gateway-client</artifactId>
<version>${project.version}</version>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
The problem is that because this profile is active by default, if we try to run a mvn deploy and the version of the GAV coordinates is a -SNAPSHOT, the build unintentionally still tries to deploy to Nexus 3rd Party and Releases repos and fails because of course it won't accept -SNAPSHOT artifact versions. To get around this, I setup a profile specifically for -SNAPSHOT versions which will only deploy to the Snapshot repository:
<profile>
<!-- ====================================================================== -->
<!-- snapshot Profile -->
<!-- Activating this profile will automatically deactivate the default profile. -->
<!-- The purpose of this profile is to produce a a gateway-services-client and gateway-client -->
<!-- snapshot artifacts and deploy them to the snapshots Nexus repository where they can -->
<!-- act as the latest development dependencies for other projects -->
<!-- ====================================================================== -->
<id>snapshot</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<!-- ====================================================================== -->
<!-- snapshot profile Build plugins -->
<!-- ====================================================================== -->
<build>
<plugins>
<!-- ====================================================================== -->
<!-- snapshot profile Maven deploy plugin -->
<!-- ====================================================================== -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>deploy-thirdparty-snapshot-jar</id>
<phase>deploy</phase>
<goals>
<goal>deploy-file</goal>
</goals>
<configuration>
<url>${nexus.url}/content/repositories/snapshots</url>
<repositoryId>snapshots</repositoryId>
<file>${project.build.directory}/${project.build.finalName}.${project.packaging}</file>
<groupId>${project.groupId}</groupId>
<artifactId>gateway-services-client</artifactId>
<version>${project.version}</version>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
The problem with this is that you must specify the profile when executing the Maven command: mvn deploy -P 'snapshot'. My question is what can I do so that all I have to do is run mvn deploy without specifying the snapshot profile and have the build automatically deploy to the snapshot repository or to the 3rd Party and Releases repositories all based on the presense of -SNAPSHOT in the version of the GAV coordinates?
The only solution that comes to my mind is using properties and adding three executions during deployment. The ugly thing is that in case of SNAPSHOT your artifact would be deployed twice to the same repository.
Here is what you could do:
<plugin>
<groupId>org.codehaus.groovy.maven</groupId>
<artifactId>gmaven-plugin</artifactId>
<version>1.0</version>
<executions>
<execution>
<id>eval-repo</id>
<phase>initialize</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<source>
if (project.version.endsWith("-SNAPSHOT")){
project.properties.repoId = "snapshots";
project.properties.repoUrl = "snapshots url";
project.properties.thirdPartyRepoId = "snapshots";
project.properties.thirdPartyRepoUrl = "snapshots url";
}
else {
project.properties.repoId = "releases";
project.properties.repoUrl = "releases url";
project.properties.thirdPartyRepoId = "thirdparty";
project.properties.thirdPartyRepoUrl = "thirdparty url";
}
</source>
</configuration>
</execution>
</executions>
</plugin>
Then add three executions with the following configurations:
<configuration>
<artifactId>gateway-client</artifactId>
<url>${repoUrl}</url>
<repositoryId>${repoId}</repositoryId>
...
<configuration>
<artifactId>gateway-services-client</artifactId>
<url>${repoUrl}</url>
<repositoryId>${repoId}</repositoryId>
...
<configuration>
<artifactId>gateway-services-client</artifactId>
<url>${thirdPartyRepoId}</url>
<repositoryId>${thirdPartyRepoUrl}</repositoryId>
...
You can't do it with profiles. From the maven doc:
A profile can be triggered/activated in several ways:
Explicitly
Through Maven settings
Based on environment variables
OS settings
Present or missing files
So you can't do it the way you want it. However, we do this all the time. Our setup is we use the following in our super-pom
<distributionManagement>
<repository>
<id>deploymentRepo</id><!-- key in settings.xml -->
<name>Releases</name>
<uniqueVersion>false</uniqueVersion>
<url>${repos.release}</url>
<layout>default</layout>
</repository>
<snapshotRepository>
<id>deploymentRepo</id>
<name>Snapshots</name>
<uniqueVersion>true</uniqueVersion>
<url>${repos.snapshot}</url>
<layout>default</layout>
</snapshotRepository>
</distributionManagement>
Note the id is the same because both repos use the same credential.
We are also using nexus where each repo is configured as snapshot or release and just with this, maven is capable of knowing that *-SNAPSHOT goes to the snapshot repo.
In other words, just give both options at the same time, don't put them in mutually exclusive profiles, and maven will know which way to send them. If it doesn't, try a repo manager
I know how to Clover in Maven (in local Eclipse or Jenkins), the problem is it's not a good idea to ask everyone put clover license in the same directory. Is there any suggestion for it?
<properties>
<clover.version>3.1.8</clover.version>
<clover.license>C:\xxx\clover_license</clover.license>
</properties>
<build>
<plugins>
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-clover2-plugin</artifactId>
<version>${clover.version}</version>
<configuration>
<license>${clover.license}</license>
</configuration>
</plugin>
</plugins>
</build>
I think use Maven parameter to pass the variable is possible, but I need to set it in every project in Jenkins. And if I change the file in Jenkins server, I need to modify every project.
-Dclover.license=C:\xxx\clover_license
See How to configure your clover.license for advice here. I recommend the suggestion to "Set up your .m2/settings.xml file", so you can define that property once:
<profiles>
<profile>
<id>my-clover-profile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<!-- You can define the path to a license file: -->
<maven.clover.licenseLocation>/path/to/clover.license</maven.clover.licenseLocation>
<!-- Or you can embed license key (remember to keep newline characters): -->
<maven.clover.license><![CDATA[
...
]]></maven.clover.license>
</properties>
</profile>
</profiles>
Is there a way to define my maven profiles outside POM file but not in .m2/settings.xml?
I want to define them in a separate xml file inside the application (way to work efficiently with maven 2 and 3) because I am using maven 2 and intend to switch to 3 soon.
Until Maven 2.2.1 you could define your profiles into the profiles.xml file as a separate file but with Maven 3 this opportunity has been removed. The question ist why do you need a separate file for the profiles?
You may want to go through this maven documentation on build profiles, which describes the types of profiles and how each can be used.
As I see it, profiles cannot be defined outside pom.xml or settings.xml, if you want to use maven 3.
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<build.profile.id>dev</build.profile.id>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<build.profile.id>prod</build.profile.id>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<build.profile.id>test</build.profile.id>
</properties>
</profile>
</profiles>
And add a filter
<filters>
<filter>src/test/resources/${build.profile.id}/config.properties</filter>
</filters>
And add any directory (dev, prod, test)
I was recently migrating an application to maven3 from maven2. With maven 3 there is no possibility to have external profiles. But what can be done is to have external property files. This can be achieved by maven-properties-plugin
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.0-alpha-2</version>
<executions>
<!-- Associate the read-project-properties goal with the initialize phase,
to read the properties file. -->
<execution>
<phase>initialize</phase>
<goals>
<goal>read-project-properties</goal>
</goals>
<configuration>
<files>
<file>../com.tak/build.properties</file>
</files>
</configuration>
</execution>
</executions>
</plugin>
So here I have explained how to do that http://programtalk.com/java/migrate-from-maven2x-to-maven3x/