This maven plugin provides a build lifecycle for dotnet. It is intended fpr situations where you need to build one or more dotnet binaries inside a maven build. Such situations arise if you have a java application that does contain some code that ports it to .Net.
To activate this build lifecycle add this plugin to your pom and set packaging to nuget:
<?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>my.group.id</groupId>
<artifactId>my-artifact-id</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>nuget</packaging>
<build>
<plugins>
<plugin>
<groupId>de.eitco.cicd</groupId>
<artifactId>dotnet-maven-plugin</artifactId>
<version>0.0.3</version>
<extensions>true</extensions> <!-- (1) -->
</plugin>
</plugins>
</build>
</project>๐ you need to activate extensions for this plugin (1)
When maven is started this will activate a build lifecycle that calls the dotnet executable to build the current project. A valid sln or csproj file must be in the same path as the pom.
By default, the plugin assumes dotnet is available in the PATH environment variable. Three modes are supported:
No configuration needed. The plugin calls dotnet/dotnet.exe directly, and the OS resolves it via PATH.
Set the <dotnetExecutable> parameter to point at a pre-installed dotnet executable:
<plugin>
<groupId>de.eitco.cicd</groupId>
<artifactId>dotnet-maven-plugin</artifactId>
<version>1.0.0</version>
<extensions>true</extensions>
<configuration>
<dotnetExecutable>/usr/local/dotnet-custom/dotnet</dotnetExecutable>
</configuration>
</plugin>Set the <dotnetSdkVersion> parameter and the plugin will download and cache the specified .NET SDK version locally:
<plugin>
<groupId>de.eitco.cicd</groupId>
<artifactId>dotnet-maven-plugin</artifactId>
<version>1.0.0</version>
<extensions>true</extensions>
<configuration>
<dotnetSdkVersion>8.0.404</dotnetSdkVersion>
</configuration>
</plugin>The SDK is downloaded using Microsoft's official dotnet-install script and stored in a versioned cache directory (default: ~/.m2/repository/.maven-dotnet-sdk-local/<rid>/<version>) without any system-wide installation. The same version is reused across repeated builds and is safe for concurrent builds.
Supported versions:
- Exact versions (e.g.
8.0.424,9.0.100,9.0.100-preview.1): Uses--version, downloads the exact SDK. - Channel-style values (e.g.
8.0,9.0,LTS,STS,latest,current): Uses--channel, pins to the latest patch of that channel at first successful download. Later patches for that channel are not auto-picked unless the cache is cleared or an exact version is used.
Caching caveat: A channel-style value like dotnetSdkVersion=8.0 pins whatever exact SDK version that channel resolved to on first successful provisioning into the cache directory (.../sdk/8.0/). Subsequent builds reuse that pinned patch, so you don't pick up new upstream patches automatically โ this is intentional for determinism. If you want latest patches to be picked up, clear the cache directory or use exact versions instead.
Note: <dotnetExecutable> and <dotnetSdkVersion> are mutually exclusive. Configuring both will fail the build immediately.
Override the cache location (defaults to ${settings.localRepository}/.maven-dotnet-sdk-local):
<configuration>
<dotnetSdkVersion>8.0.404</dotnetSdkVersion>
<dotnetSdkCacheBaseDirectory>~/.dotnet-sdks</dotnetSdkCacheBaseDirectory>
<dotnetSdkCacheName>myproject-sdks</dotnetSdkCacheName>
</configuration>Do not point <dotnetSdkCacheBaseDirectory> at a network filesystem (NFS/SMB). The plugin uses advisory file locking for concurrent-build safety, which is unreliable over network filesystems. Use a local directory instead.
A complete reference of the available goals and parameters can be found here.
The following goals are bound to the build lifecycle:
The initialize goal is bound to the initialize phase. This goal registers nuget source repositories. A special one
that helps mimic mavens local repository and additionally all repositories that are configured. For example:
<?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>
...
<build>
<plugins>
<plugin>
<groupId>de.eitco.cicd</groupId>
<artifactId>dotnet-maven-plugin</artifactId>
<version>0.0.3</version>
<extensions>true</extensions>
<configuration>
<nugetSources>
<organization-repository-id>https://repo1.organization.org/nuget</organization-repository-id>
<project-repository-id>https:///epo1.organization.org/project-nuget</project-repository-id>
</nugetSources>
</configuration>
</plugin>
</plugins>
</build>
</project>This will add two custom nuget sources one named organization-repository-id that is assumed to be located at
https://repo1.organization.org/nuget and another one named project-repository-id that is assumed to be located at
https://repo1.organization.org/project-nuget.
๐ Should you have registered any
<service>elements in your settings.xml having the source name asid, those credentials will be added to the corresponding nuget source.
โ ๏ธ On non-windows platforms dotnet/nuget is unable to store credentials encrypted. On these platforms the credentials will be stored in plain text
Additionally, a source maven-nuget-local pointing to the local directory ~/.m2/repository will be added. Should any
of these sourced already be added, they will be updated with their current config.
The initialize goal also creates a local directory as nuget source, where a later goal will 'install' its artifacts to.
This enables a maven builds, where two different dotnet modules of the same build reactor have a dependency between them.
By default, the name of this source is maven-nuget-local and its location is ${settings.localRepository}. Those
can be overridden with the <localMavenNugetRepositoryName> and <localMavenNugetRepositoryBaseDirectory> parameters, respectively.
The build goal is bound to the compile phase. It will call dotnet build on the current project, be that a .sln
or .csproj file. It will always add the command line option -p:Version=<projectVersion> with projectVersion being
the goals parameter of the same name. This way the version of the build artifacts are managed in the pom.
The test goal is bound to the test phase. It will call dotnet test to execute test. It will add the command line
parameter --no-build, since the compile phase will already be called before the test phase. It will always configure
the trx logger and transform the results to a valid junit description - enabling ci servers to collect the tests
results in the default format for maven builds. The goal will honour the reactors failure behaviour. Also, it honours the
property skipTests, skipping its execution when set to true.
The pack goal is bound to the package phase. It calls dotnet pack creating nuget packages (*.nupgk). The goal will
call dotnet with --no-build as the project was already built in the compile phase. As the build goal it will set
the dotnet Version property to the goals projectVersion parameter, managing the version in the pom. Also, it will set
the --output command line argument to the goals targetDirectory parameter, which defaults to ${project.build.directory}/dotnet
thus being deleted by a mvn clean command.
The install goal is bound to the install phase. It does not call dotnet at all. Since the package phase was
already executed, it assumes the builds delivery artifacts to be located in the directory denoted by the goals
targetDirectory parameter. It will simply copy all *.nupkg files located there to directory configured to be the
local nuget directory
The push goal is bound to the deploy phase. It calls nuget push on every nupgk file located in the configured
targetDirectory.
This plugin also provides a clean lifecycle. It is pretty simple: Additionally to the maven default clean goal, a
custom clean goal is called, which simply calls dotnet clean
Examples can be found with the integration tests
When calling dotnet this plugin will always set the environment variable DOTNET_CLI_TELEMETRY_OPTOUT to TRUE if
not overwritten by the environmentVariables parameter.