Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ To use the plugin you need to configure it in your `pom.xml` like so
<description>Description of your release</description>
<releaseName>1.0 Final</releaseName>
<tag>${project.version}</tag>

<!-- If your project has additional artifacts, such as ones produced by
the maven-assembly-plugin, you can define the following
(requires version 1.1.1 of the plugin or higher): -->
Expand Down Expand Up @@ -48,4 +48,27 @@ These credentials can be overridden by setting `username` and `password` as syst

Thanks to a contribution from rowanseymour you can also use your API token by adding it as `<privateKey>` to your server definition in the `settings.xml`.

## GitHub Enterprise users

It is also possible to upload to GitHub Enterprise. For that, two additional options are available
in the configuration: `githubHostname`, `githubApiUrlPrefix` and `githubApiUploadUrlPrefix`. They can be used like this:

```
<plugin>
<groupId>de.jutzig</groupId>
<artifactId>github-release-plugin</artifactId>
<version>1.1.1</version>
<configuration>
<description>Description of your release</description>
<releaseName>1.0 Final</releaseName>
<tag>${project.version}</tag>
<!-- GitHub Enterprise settings -->
<githubHostname>github-enterprise.domain</githubHostname>
<githubApiUrlPrefix>http://github-enterprise.domain/api/v3</githubApiUrlPrefix>
<githubApiUploadUrlPrefix>https://github-enterprise.domain/api/v3</githubApiUploadUrlPrefix>
...
</configuration>
</plugin>
```

The plugin is available on Maven central
40 changes: 37 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.3</version>
<configuration>
<goalPrefix>github-release</goalPrefix>
</configuration>
</plugin>
</plugins>
</build>

Expand Down Expand Up @@ -154,26 +162,52 @@
<dependency>
<groupId>org.kohsuke</groupId>
<artifactId>github-api</artifactId>
<version>1.49</version>
<version>1.75-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.1.0</version>
<version>3.3.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.1.0</version>
<version>3.3.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
<version>3.3.9</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.apache.maven.plugin-testing</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
<version>3.3.0</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
133 changes: 92 additions & 41 deletions src/main/java/de/jutzig/github/release/plugin/UploadMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
import org.apache.maven.model.FileSet;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Server;
import org.apache.maven.settings.Settings;
import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
Expand All @@ -50,100 +54,133 @@

/**
* Goal which attaches a file to a GitHub release
*
* @goal release
*
* @phase deploy
*/
@Mojo( name="release", defaultPhase = LifecyclePhase.DEPLOY)
public class UploadMojo extends AbstractMojo implements Contextualizable{

private final static String DEFAULT_GITHUBHOSTNAME = "github.com";
private final static String DEFAULT_GITAPIURLPREFIX = "https://api.github.com";

/**
*
* //@parameter default-value="github" expression="github"
* Server id for github access.
*
* @parameter default-value="github" expression="github"
*/
private String serverId;
@Parameter( defaultValue = "github")
private String serverId;

/**
* The tag name this release is based on.
*
* @parameter expression="${project.version}"
*
* //@parameter expression="${project.version}"
*/
@Parameter( property = "project.version" )
private String tag;

/**
* The name of the release
*
* @parameter expression="${release.name}"
*
* //@parameter expression="${release.name}"
*/
private String releaseName;
@Parameter( property = "release.name" )
private String releaseName;

/**
* The release description
*
* @parameter expression="${project.description}"
*
* //@parameter expression="${project.description}"
*/
@Parameter( property = "project.description" )
private String description;

/**
* The github id of the project. By default initialized from the project scm connection
*
* @parameter default-value="${project.scm.connection}" expression="${release.repositoryId}"
*
* //@parameter default-value="${project.scm.connection}" expression="${release.repositoryId}"
* @required
*/
@Parameter( defaultValue = "${project.scm.connection}", property = "release.repositoryId")
private String repositoryId;

/**
* The Maven settings
*
* @parameter expression="${settings}
* //@parameter expression="${settings}
*/
@Parameter( defaultValue = "${settings}", readonly = true)
private Settings settings;

/**
* The Maven session
*
* @parameter expression="${session}"
* //@parameter expression="${session}"
*/
@Parameter( defaultValue = "${session}", readonly = true)
private MavenSession session;

/**
* The file to upload to the release. Default is ${project.build.directory}/${project.artifactId}-${project.version}.${project.packaging} (the main artifact)
*
* @parameter default-value="${project.build.directory}/${project.artifactId}-${project.version}.${project.packaging}" expression="${release.artifact}"
* //@parameter default-value="${project.build.directory}/${project.artifactId}-${project.version}.${project.packaging}" expression="${release.artifact}"
*/
@Parameter( defaultValue = "${project.build.directory}/${project.artifactId}-${project.version}.${project.packaging}",
property = "release.artifact")
private String artifact;

/**
* A specific <code>fileSet</code> rule to select files and directories for upload to the release.
*
* @parameter
* //@parameter
*/
private FileSet fileSet;

/**
* A list of <code>fileSet</code> rules to select files and directories for upload to the release.
*
* @parameter
* //@parameter
*/
private List<FileSet> fileSets;

/**
* Flag to indicate to overwrite the asset in the release if it already exists. Default is false
*
* @parameter default-value=false
* //@parameter default-value=false
*/
@Parameter( defaultValue = "false" )
private Boolean overwriteArtifact;

/**
* Github (Enterprise) hostname. Default is 'github.com'
*
* ////@parameter default-value="github.com"
*/
@Parameter( defaultValue = DEFAULT_GITHUBHOSTNAME )
private String githubHostname;

/**
* Github (Enterprise) API URL (prefix). Default is 'https://api.github.com'
*/
@Parameter( defaultValue = DEFAULT_GITAPIURLPREFIX )
private String githubApiUrlPrefix;

/**
* URL prefix to upload the release to Github. Default is 'https://uploads.github.com/'
*
* ////@parameter default-value="https://uploads.github.com/"
*/
@Parameter( defaultValue = "https://uploads.github.com/")
private String githubApiUploadUrlPrefix;

@Requirement
private PlexusContainer container;

/**
* If this is a prerelease. By default it will use <code>true</code> if the tag ends in -SNAPSHOT
*
* @parameter
*
* //@parameter
*
*/
@Parameter
private Boolean prerelease;

public void execute() throws MojoExecutionException {
Expand Down Expand Up @@ -188,7 +225,7 @@ public void execute() throws MojoExecutionException {
uploadAssets(release, set);

} catch (IOException e) {

getLog().error(e);
throw new MojoExecutionException("Failed to upload assets", e);
}
Expand All @@ -197,14 +234,12 @@ public void execute() throws MojoExecutionException {

private void uploadAsset(GHRelease release, File asset) throws IOException {
getLog().info("Processing asset "+asset.getPath());
URL url = new URL(MessageFormat.format("https://uploads.github.com/repos/{0}/releases/{1}/assets?name={2}",repositoryId,Long.toString(release.getId()),asset.getName()));

List<GHAsset> existingAssets = release.getAssets();
for ( GHAsset a : existingAssets ){
if (a.getName().equals( asset.getName() )){
if(overwriteArtifact) {
getLog().info(" Deleting existing asset");
a.delete();
a.delete();
}
else
{
Expand All @@ -216,7 +251,7 @@ private void uploadAsset(GHRelease release, File asset) throws IOException {

getLog().info(" Upload asset");
// for some reason this doesn't work currently
release.uploadAsset(asset, "application/zip");
release.uploadAsset(asset, "application/zip", ensureNoTrailingSlash(githubApiUploadUrlPrefix));
}

private void uploadAssets(GHRelease release, FileSet fileset) throws IOException {
Expand All @@ -239,17 +274,18 @@ private GHRelease findRelease(GHRepository repository, String releaseName2) thro
return null;
}

/**
* @see <a href="https://maven.apache.org/scm/scm-url-format.html">SCM URL Format</a>
*/
private static final Pattern REPOSITORY_PATTERN = Pattern.compile(
public String computeRepositoryId(String id) {

String githubHostnameForRegexp = githubHostname.replace(".", "\\.");

final Pattern REPOSITORY_PATTERN = Pattern.compile(
"^(scm:git[:|])?" + //Maven prefix for git SCM
"(https?://github\\.com/|git@github\\.com:)" + //GitHub prefix for HTTP/HTTPS/SSH/Subversion scheme
"(https?://" + githubHostnameForRegexp + "/|git@" + githubHostnameForRegexp + ":)" + //GitHub prefix for HTTP/HTTPS/SSH/Subversion scheme
"([^/]+/[^/]*?)" + //Repository ID
"(\\.git)?$" //Optional suffix ".git"
, Pattern.CASE_INSENSITIVE);
, Pattern.CASE_INSENSITIVE);
getLog().debug("using following repository pattern: " + REPOSITORY_PATTERN.toString());

public static String computeRepositoryId(String id) {
Matcher matcher = REPOSITORY_PATTERN.matcher(id);
if (matcher.matches()) {
return matcher.group(3);
Expand All @@ -263,10 +299,10 @@ public GitHub createGithub(String serverId) throws MojoExecutionException, IOExc
String passwordProperty = System.getProperty("password");
if(usernameProperty!=null && passwordProperty!=null)
{
getLog().debug("Using server credentials from system properties 'username' and 'password'");
getLog().debug("Using server credentials from system properties 'username' and 'password'");
return GitHub.connectUsingPassword(usernameProperty, passwordProperty);
}

Server server = getServer(settings, serverId);
if (server == null)
throw new MojoExecutionException(MessageFormat.format("Server ''{0}'' not found in settings", serverId));
Expand All @@ -285,16 +321,18 @@ public GitHub createGithub(String serverId) throws MojoExecutionException, IOExc
String serverPassword = server.getPassword();
String serverAccessToken = server.getPrivateKey();
if (StringUtils.isNotEmpty(serverUsername) && StringUtils.isNotEmpty(serverPassword))
return GitHub.connectUsingPassword(serverUsername, serverPassword);
return DEFAULT_GITHUBHOSTNAME.equals(githubHostname) ? GitHub.connectUsingPassword(serverUsername, serverPassword)
: GitHub.connectToEnterprise(githubApiUrlPrefix, serverUsername, serverPassword);
else if (StringUtils.isNotEmpty(serverAccessToken))
return GitHub.connectUsingOAuth(serverAccessToken);
return DEFAULT_GITHUBHOSTNAME.equals(githubHostname) ? GitHub.connectUsingOAuth(serverAccessToken)
: GitHub.connectToEnterprise(githubApiUrlPrefix, serverAccessToken);
else
throw new MojoExecutionException("Configuration for server " + serverId + " has no login credentials");
}

/**
* Get server with given id
*
*
* @param settings
* @param serverId
* must be non-null and non-empty
Expand All @@ -316,4 +354,17 @@ protected Server getServer(final Settings settings, final String serverId) {
public void contextualize(Context context) throws ContextException {
container = (PlexusContainer) context.get( PlexusConstants.PLEXUS_KEY );
}

/**
* @param str
* @return trimmed str minus the trailing '/', if any
*/
String ensureNoTrailingSlash(String str) {
if(str == null || str.isEmpty()) {
return str;
}
String strTrimmed = str.trim();
return strTrimmed.endsWith("/") ? strTrimmed.substring(0, strTrimmed.length() - 1) : strTrimmed;
}

}
Loading