diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..32bf1e5
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,5 @@
+# Automatically normalize line endings for all text-based files
+* text=auto
+
+# set scripts to lf
+*.sh text eol=lf
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c9b7442
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,41 @@
+# Compiled source
+*.com
+*.class
+*.dll
+*.exe
+*.o
+*.so
+
+# Packages
+# it's better to unpack these files and commit the raw source
+# git has its own built in compression methods
+*.7z
+*.dmg
+*.gz
+*.iso
+*.jar
+*.rar
+*.tar
+*.zip
+
+# Logs and databases
+*.log
+*.sqlite
+
+# OS generated files
+.DS_Store
+ehthumbs.db
+Icon
+Thumbs.db
+
+# Idea
+.idea/*
+*.iml
+*.iws
+*.ipr
+
+# Maven
+target
+
+# Test resource
+!asset-zip-example.zip
diff --git a/.run/main-checkstyle[check].run.xml b/.run/main-checkstyle[check].run.xml
new file mode 100644
index 0000000..5ee2e9d
--- /dev/null
+++ b/.run/main-checkstyle[check].run.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/main-pmd[check].run.xml b/.run/main-pmd[check].run.xml
new file mode 100644
index 0000000..97d17c4
--- /dev/null
+++ b/.run/main-pmd[check].run.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/main[deploy].run.xml b/.run/main[deploy].run.xml
new file mode 100644
index 0000000..ae36bc7
--- /dev/null
+++ b/.run/main[deploy].run.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/main[install].run.xml b/.run/main[install].run.xml
new file mode 100644
index 0000000..1a868f2
--- /dev/null
+++ b/.run/main[install].run.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/main[test].run.xml b/.run/main[test].run.xml
new file mode 100644
index 0000000..2c798c7
--- /dev/null
+++ b/.run/main[test].run.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/main[verify].run.xml b/.run/main[verify].run.xml
new file mode 100644
index 0000000..b26772a
--- /dev/null
+++ b/.run/main[verify].run.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/plugin-example[install].run.xml b/.run/plugin-example[install].run.xml
new file mode 100644
index 0000000..9a31d39
--- /dev/null
+++ b/.run/plugin-example[install].run.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.run/plugin-example[run].run.xml b/.run/plugin-example[run].run.xml
new file mode 100644
index 0000000..7c9b72c
--- /dev/null
+++ b/.run/plugin-example[run].run.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MIT.LICENSE b/MIT.LICENSE
new file mode 100644
index 0000000..8883431
--- /dev/null
+++ b/MIT.LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2022 Michael Wiesendanger
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.md b/README.md
index c139a65..43d8d44 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,216 @@
# wago-release-maven-plugin
+
+> A maven plugin for creating Wago.io mods/addons releases
+
+[![Maven Central](https://img.shields.io/maven-central/v/com.ragedunicorn.tools.maven/wago-release-maven-plugin.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.ragedunicorn.tools.maven%22%20AND%20a:%wago-release-maven-plugin%22)
+
+## Usage
+
+Setup pom.xml in project
+
+```xml
+
+ [...]
+
+
+
+ com.ragedunicorn.tools.maven
+ wago-release-maven-plugin
+ [version]
+
+
+ default-cli
+
+ [projectId]
+
+ release description overwritten by release notes
+ src/main/resources/release-notes-example.md
+ [game-version]
+ [game-version]
+ [game-version]
+ stable
+ [path-to-packaged-addon]
+ [.m2/settings.xml server name]
+
+
+
+
+
+
+ [...]
+
+```
+| Parameter | Required | Default Value | Description |
+| --------------------- | -------- | ------------- | --------------------------------------------------------------------------------------------------------------------------- |
+| |
+| projectId | true | <> | The project id of the wago.io project (can be found on the developer dashboard) |
+| server | false | <> | References a server configuration in your .m2 settings.xml. This is the preferred way for using the generated wago.io token |
+| authToken | false | <> | Alternative of using a server configuration. The authToken can directly be placed in the plugin configuration |
+| label | false | addon | An optional label for the uploaded file |
+| changelog | false | <> | A string containing the changelog |
+| changelogFile | false | <> | Optional path to a changelog file - will override changelog |
+| supportedRetailPatch | false | <> | A number representing the retail supported version |
+| supportedBccPatch | false | <> | A number representing the burning crusade supported version |
+| supportedClassicPatch | false | <> | A number representing the classic supported version |
+| releaseType | false | release | One of "stable", "beta", "alpha" |
+| file | true | <> | The path to the addon to upload |
+
+### Execute Plugin
+
+```
+mvn wago-release:wago-release
+```
+
+
+## Setup Api Token
+
+Before the plugin can be used an API token has to be generated.
+
+See Wago.io [documentation](https://addons.wago.io/account/apikeys)
+
+Once the Api token is generated it can be stored inside the maven `.m2/settings.xml`.
+
+ ```xml
+
+ wago-token
+ token
+
+```
+
+Make sure to use `passphrase` instead of `username`and `password` otherwise the plugin will not be able to recognize the token.
+
+It is also possible to set the token with the parameter `authToken` directly inside the plugin configuration. This is however not recommended because those pom files are usually getting commited into source control and potentially leaking the token.
+However, using maven commandline this can be useful being able to overwrite this parameter with the `-D` option.
+
+```xml
+
+ ...
+ ${wago.auth-token}
+
+```
+
+Then invoking via the command line
+```
+mvn wago-release:wago-release -D wago.auth-token=[token]
+```
+
+## Test
+
+Basic tests can be executed with:
+
+```
+mvn test
+```
+
+Tests are kept basic because for most of the functionality the Wago.io backend is required.
+
+## Development
+
+##### IntelliJ Run Configurations
+
+The project contains IntelliJ run configurations that can be used for most tasks. All configurations can be found in the `.run` folder.
+
+##### Build Project
+
+wago-release-maven-plugin
+
+```
+clean install
+```
+
+#### Create a Release
+
+In maven `settings.xml` configure the ossrh account
+
+```
+
+ ossrh
+
+
+
+```
+
+#### Build and Release
+
+```
+mvn clean deploy -P deploy
+```
+
+#### Move Staging to Release
+
+If `autoReleaseAfterClose` is set to false in the `nexus-staging-maven-plugin` plugin an additional step is required to move the deployment from staging to release.
+
+```
+mvn nexus-staging:release
+```
+
+Or if the deployment didn't work out you can drop the artifact from the staging repository.
+
+```
+mvn nexus-staging:drop
+```
+
+**Note:** On MacOS the error `gpg: signing failed: Inappropriate ioctl for device` can be solved by setting the tty export variable for gpg.
+
+```
+export GPG_TTY=$(tty)
+```
+
+If you are using the IntelliJ console this might need to be set directly in that console.
+
+##### Run Example
+
+The example can be used for testing of the plugin during development. It requires some manual setup on GitHub before it can be run.
+
+* Setup wago token
+
+wago-release-maven-plugin/example
+
+```
+clean install
+```
+
+Executing the plugin from a different folder won't work without also fixing the path to the release notes and any additional assets configured.
+
+**Note:** The example module is deliberately not included as default module otherwise it would execute each time the project is built.
+Instead, the module can be considered separate and independent. It is an example of how to use the plugin, and it is helpful in testing the plugin during development.
+
+
+##### Checkstyle
+
+wago-release-maven-plugin/plugin
+
+```
+mvn checkstyle:checkstyle
+```
+
+##### PMD
+
+wago-release-maven-plugin/plugin
+
+```
+mvn pmd:pmd
+```
+
+## License
+
+Copyright (c) 2022 Michael Wiesendanger
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/RELEASE.md b/RELEASE.md
new file mode 100644
index 0000000..586ee88
--- /dev/null
+++ b/RELEASE.md
@@ -0,0 +1,18 @@
+# Release
+
+> This document explains how a new release is created for wago-release-maven-plugin
+
+* Remove snapshot from version and commit
+* Create a new git tag and push it
+ * `git tag vx.x.x`
+ * `git push origin --tags`
+* Draft new GitHub release with description
+ * Title should be the version e.g. vx.x.x
+ * Short description of what changed
+* Deploy release artifact to OSSRH
+ * mvn clean deploy -P deploy
+ * mvn nexus-staging:release when autoReleaseAfterClose is set to false
+ * Increase project version and add SNAPSHOT then commit (after a release the version should always be a snapshot version)
+ * Don't forget to update the example and the test pom with the same version
+
+**Note:** Snapshot versions can be deployed with the same command `mvn clean deploy -P deploy`
diff --git a/example/pom.xml b/example/pom.xml
new file mode 100644
index 0000000..4c7edff
--- /dev/null
+++ b/example/pom.xml
@@ -0,0 +1,86 @@
+
+
+ 4.0.0
+ com.ragedunicorn.tools.maven
+ wago-release-example
+ jar
+ 1.1.0-SNAPSHOT
+
+ ${project.groupId}:${project.artifactId}
+ Example project for Maven CurseForge release plugin
+ https://github.com/RagedUnicorn/github-wago-maven-plugin
+
+
+
+ MIT License
+ http://opensource.org/licenses/MIT
+ repo
+ A short, permissive software license. Basically, you can do whatever you want as long as you include the
+ original copyright and license notice in any copy of the software/source.
+
+
+
+
+
+ RagedUnicorn
+ http://ragedunicorn.com
+
+
+
+
+ mwiesendanger
+ Michael Wiesendanger
+ michael.wiesendanger@gmail.com
+ http://ragedunicorn.com
+ RagedUnicorn
+ http://ragedunicorn.com
+
+ developer
+
+ Switzerland/Zurich
+
+
+
+
+ UTF-8
+
+
+
+
+
+ com.ragedunicorn.tools.maven
+ wago-release-maven-plugin
+ 1.0.0-SNAPSHOT
+
+
+ default-cli
+
+ LvNAj96o
+
+ release description overwritten by release notes
+ src/main/resources/release-notes-example.md
+ 1.13.7
+ stable
+ src/main/resources/asset-zip-example.zip
+ wago-token
+
+
+
+
+
+
+
+
+
+
+
diff --git a/example/src/main/resources/asset-zip-example.zip b/example/src/main/resources/asset-zip-example.zip
new file mode 100644
index 0000000..57058b4
Binary files /dev/null and b/example/src/main/resources/asset-zip-example.zip differ
diff --git a/example/src/main/resources/release-notes-example.md b/example/src/main/resources/release-notes-example.md
new file mode 100644
index 0000000..a500fa8
--- /dev/null
+++ b/example/src/main/resources/release-notes-example.md
@@ -0,0 +1,7 @@
+# release notes example
+
+# release changes
+
+* change 1
+* change 2
+* ...
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..5b1d66c
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,286 @@
+
+
+ 4.0.0
+ com.ragedunicorn.tools.maven
+ wago-release-maven-plugin
+ 1.0.0-SNAPSHOT
+ maven-plugin
+
+ ${project.groupId}:${project.artifactId}
+ Maven plugin for creating Wago.io releases
+ https://github.com/RagedUnicorn/wago-release-maven-plugin
+
+
+
+ MIT License
+ http://opensource.org/licenses/MIT
+ repo
+ A short, permissive software license. Basically, you can do whatever you want as long as you include the
+ original copyright and license notice in any copy of the software/source.
+
+
+
+
+
+ RagedUnicorn
+ http://ragedunicorn.com
+
+
+
+
+ mwiesendanger
+ Michael Wiesendanger
+ michael.wiesendanger@gmail.com
+ http://ragedunicorn.com
+ RagedUnicorn
+ http://ragedunicorn.com
+
+ developer
+
+ Switzerland/Zurich
+
+
+
+
+ scm:git:git://github.com/RagedUnicorn/wago-release-maven-plugin.git
+ scm:git:ssh://github.com:RagedUnicorn/wago-release-maven-plugin.git
+ https://github.com/RagedUnicorn/wago-release-maven-plugin/tree/master
+
+
+
+
+ ossrh
+ https://oss.sonatype.org/content/repositories/snapshots
+
+
+ ossrh
+ https://oss.sonatype.org/service/local/staging/deploy/maven2
+
+
+
+
+ UTF-8
+ 488C9072D9E5426B
+ checkstyle.xml
+ LICENSE.txt
+
+
+
+
+ development
+
+ true
+
+
+ true
+ true
+ true
+
+
+
+ release
+
+ true
+ true
+ true
+
+
+
+ deploy
+
+ false
+ false
+ false
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.6.1
+
+
+ 1.8
+
+
+
+ org.apache.maven.plugins
+ maven-plugin-plugin
+ 3.5.2
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.6
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+ ${skip.sign.gpg}
+ ${gpg.keyname}
+ ${gpg.keyname}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 3.0.1
+
+
+ attach-sources
+
+ jar
+
+
+ ${skip.package.sources}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 3.0.1
+
+
+ attach-javadocs
+
+ jar
+
+
+ ${skip.package.javadoc}
+
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.8
+ true
+
+ ossrh
+ https://oss.sonatype.org/
+ false
+
+
+
+ org.apache.maven.plugins
+ maven-checkstyle-plugin
+ 3.1.0
+
+
+ com.ragedunicorn.tools.maven
+ maven-code-quality
+ 1.0.5
+
+
+ com.puppycrawl.tools
+ checkstyle
+ 8.29
+
+
+
+
+ org.apache.maven.plugins
+ maven-pmd-plugin
+ 3.10.0
+
+
+ pmd-ruleset.xml
+
+ true
+
+
+
+ com.ragedunicorn.tools.maven
+ maven-code-quality
+ 1.0.5
+
+
+ net.sourceforge.pmd
+ pmd-vm
+ 6.6.0
+
+
+ net.sourceforge.pmd
+ pmd-xml
+ 6.6.0
+
+
+
+
+
+
+
+
+ org.apache.maven
+ maven-plugin-api
+ 3.8.5
+
+
+ org.apache.maven
+ maven-core
+ 3.8.5
+
+
+ org.apache.maven
+ maven-compat
+ 3.8.5
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+ 3.6.4
+
+
+ org.slf4j
+ slf4j-simple
+ 1.7.36
+
+
+ com.google.code.gson
+ gson
+ 2.9.0
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.13
+
+
+ org.apache.httpcomponents
+ httpmime
+ 4.5.13
+
+
+ javax.ws.rs
+ jsr311-api
+ 1.1.1
+
+
+
+ junit
+ junit
+ 4.13.2
+ test
+
+
+ org.apache.maven.plugin-testing
+ maven-plugin-testing-harness
+ 3.3.0
+ test
+
+
+
diff --git a/src/main/java/com/ragedunicorn/tools/maven/WagoClient.java b/src/main/java/com/ragedunicorn/tools/maven/WagoClient.java
new file mode 100644
index 0000000..1096017
--- /dev/null
+++ b/src/main/java/com/ragedunicorn/tools/maven/WagoClient.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2022 Michael Wiesendanger
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.ragedunicorn.tools.maven;
+
+import com.google.common.collect.Lists;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+import org.apache.http.Header;
+import org.apache.http.HttpHeaders;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.LaxRedirectStrategy;
+import org.apache.http.message.BasicHeader;
+import org.apache.maven.plugin.MojoExecutionException;
+
+public class WagoClient {
+ private static final String USER_AGENT = "wago-release-plugin";
+
+ private String baseUri = "https://addons.wago.io/api/projects/:projectId/version";
+ // targeted project
+ private String projectId;
+ // token
+ private String token;
+
+ public String getBaseUri() {
+ return baseUri;
+ }
+
+ public void setBaseUri(String baseUri) {
+ this.baseUri = baseUri;
+ }
+
+ public String getProjectId() {
+ return projectId;
+ }
+
+ public void setProjectId(String projectId) {
+ this.projectId = projectId;
+ }
+
+ public String getToken() {
+ return token;
+ }
+
+ public void setToken(String token) {
+ this.token = token;
+ }
+
+ /**
+ * Create an http client.
+ *
+ * @return The created http client
+ */
+ public CloseableHttpClient getHttpClient() {
+ hasValidPreconditions();
+
+ return HttpClientBuilder
+ .create()
+ .useSystemProperties()
+ .setDefaultHeaders(getDefaultHeaders())
+ .setRedirectStrategy(new LaxRedirectStrategy())
+ .build();
+ }
+
+ private List getDefaultHeaders() {
+ return Lists.newArrayList(
+ new BasicHeader(HttpHeaders.USER_AGENT, USER_AGENT),
+ new BasicHeader("Authorization", "Bearer " + token),
+ new BasicHeader(HttpHeaders.ACCEPT, "application/json")
+
+ );
+ }
+
+ /**
+ * Prepare an endpoint url by replacing placeholders with real values.
+ *
+ * @param path The path to prepare
+ * @return The prepared URI
+ * @throws MojoExecutionException If failing to prepare the URI properly
+ */
+ public URI prepareEndpointUri(final String path) throws MojoExecutionException {
+ hasValidPreconditions();
+ String processedBaseUri = baseUri.replace(":projectId", projectId);
+
+ try {
+ return new URI(processedBaseUri);
+ } catch (URISyntaxException e) {
+ throw new MojoExecutionException("Failed to prepare endpoint URI", e);
+ }
+ }
+
+ /**
+ * Checks if all preconditions are fulfilled.
+ *
+ * @throws IllegalStateException If any of the preconditions is not fulfilled
+ */
+ private void hasValidPreconditions() {
+ if (token == null || token.isEmpty() || projectId == null || projectId.isEmpty()
+ || baseUri == null || baseUri.isEmpty()) {
+ throw new IllegalStateException("Wago client is in invalid state. Make sure to set token, "
+ + "projectId, baseUri and the game");
+ }
+ }
+}
diff --git a/src/main/java/com/ragedunicorn/tools/maven/WagoReleaseMojo.java b/src/main/java/com/ragedunicorn/tools/maven/WagoReleaseMojo.java
new file mode 100644
index 0000000..7606640
--- /dev/null
+++ b/src/main/java/com/ragedunicorn/tools/maven/WagoReleaseMojo.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2022 Michael Wiesendanger
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.ragedunicorn.tools.maven;
+
+import com.ragedunicorn.tools.maven.model.Metadata;
+import com.ragedunicorn.tools.maven.service.ReleaseService;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+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.settings.Server;
+import org.apache.maven.settings.Settings;
+
+
+
+
+@Mojo(name = "wago-release")
+public class WagoReleaseMojo extends AbstractMojo {
+
+ // The project id of the wago project (can be found on the projects page)
+ @Parameter(property = "projectId", required = true)
+ private String projectId;
+
+ // A label for the uploaded file
+ @Parameter(property = "label", defaultValue = "addon")
+ private String label;
+
+ // One of stable, beta, alpha
+ @Parameter(property = "stability", defaultValue = "stable")
+ private String stability;
+
+ // A string containing the changelog
+ @Parameter(property = "changelog")
+ private String changelog;
+
+ // Optional path to a changelog file - will override changelog
+ @Parameter(property = "changelogFile")
+ private String changelogFile;
+
+ // At least one of retail, classic or bcc patch must be set (multiple values allowed)
+
+ // The retail supported version number
+ @Parameter(property = "supportRetailPatch")
+ private String supportedRetailPatch;
+
+ // The bcc supported version number
+ @Parameter(property = "supportBccPatch")
+ private String supportedBccPatch;
+
+ // The classic supported version number
+ @Parameter(property = "supportClassicPatch")
+ private String supportedClassicPatch;
+
+ // The path to the addon to upload
+ @Parameter(property = "file", required = true)
+ private String file;
+
+ // Alternative of using a server configuration. The authToken can directly be placed in the
+ // plugin configuration
+ @Parameter(property = "authToken")
+ private String authToken;
+
+ // References a server configuration in your .m2 settings.xml. This is the preferred way for
+ // using the generated wago token
+ @Parameter(property = "server")
+ private String server;
+
+ @Parameter(defaultValue = "${settings}", readonly = true)
+ private Settings settings;
+
+ /**
+ * Plugin execution callback.
+ *
+ * @throws MojoExecutionException If any exception happens during the execution of the plugin
+ */
+ public void execute() throws MojoExecutionException {
+ validateRequiredInputParameters();
+
+ WagoClient wagoClient = createWagoClient();
+ createRelease(wagoClient);
+ }
+
+ /**
+ * Create a new release on Wago.io.
+ *
+ * @param wagoClient The Wago client
+ * @throws MojoExecutionException If any exception happens during the execution of the release
+ * service
+ */
+ private void createRelease(WagoClient wagoClient) throws MojoExecutionException {
+ final ReleaseService releaseService = new ReleaseService(wagoClient);
+ Metadata metadata = new Metadata();
+
+ metadata.setLabel(label);
+ metadata.setStability(stability);
+ metadata.setChangelog(getChangelog());
+ metadata.setSupportedRetailPatch(supportedRetailPatch);
+ metadata.setSupportedBccPatch(supportedBccPatch);
+ metadata.setSupportedClassicPatch(supportedClassicPatch);
+
+ releaseService.createReleaseOperation(metadata, file);
+ }
+
+ /**
+ * Retrieve the token for the Wago.io Api.
+ *
+ * @return A property object containing the Wago.io Api token
+ * @throws MojoExecutionException An exception occurring during the execution of a plugin
+ */
+ private String getCredentials() throws MojoExecutionException {
+ // prefer settings parameter over direct configuration in pom
+ if (settings != null && server != null) {
+ final Server serverEntry = settings.getServer(server);
+ if (serverEntry != null) {
+ authToken = serverEntry.getPassphrase();
+
+ if (authToken == null || authToken.isEmpty()) {
+ throw new MojoExecutionException("Found server entry in settings.xml "
+ + "but authToken parameter was missing or is empty");
+ }
+ } else {
+ getLog().warn("Unable to retrieve settings or server. Falling back to project settings");
+ }
+ }
+ // fallback to plugin configuration if credentials cannot be retrieved from maven settings.xml
+ if (authToken == null) {
+ throw new MojoExecutionException("Unable to read authentication configuration make "
+ + "sure to set the authToken property");
+ }
+
+ return authToken;
+ }
+
+ private String getChangelog() throws MojoExecutionException {
+ if (!changelogFile.isEmpty()) {
+ byte[] changelogContent;
+
+ try {
+ Path changelogPath = Paths.get(changelogFile);
+ if (getLog().isDebugEnabled()) {
+ getLog().debug("Changelog path: " + changelogFile);
+ }
+ changelogContent = Files.readAllBytes(changelogPath);
+
+ return new String(changelogContent, StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ throw new MojoExecutionException("Failed to read release notes", e);
+ }
+ } else if (!changelog.isEmpty()) {
+ return changelog;
+ }
+
+ return "";
+ }
+
+ /**
+ * Validate required input parameters.
+ *
+ * @throws MojoExecutionException An exception occurring during the execution of a plugin
+ */
+ private void validateRequiredInputParameters() throws MojoExecutionException {
+ if (projectId == null || projectId.isEmpty()) {
+ throw new MojoExecutionException("Missing required parameter projectId");
+ }
+
+ if (!hasValidSupportedVersion()) {
+ throw new MojoExecutionException("Missing required parameter supported patch. One of "
+ + "supportedRetailPatch, supportedBccPatch or supportedClassicPatch has to be set");
+ }
+
+ if (label == null || label.isEmpty()) {
+ throw new MojoExecutionException("Missing required parameter label");
+ }
+
+ if (stability == null || stability.isEmpty()) {
+ throw new MojoExecutionException("Missing required parameter stability");
+ }
+
+ if (file == null || file.isEmpty()) {
+ throw new MojoExecutionException("Missing required parameter file");
+ }
+ }
+
+ /**
+ * Check if at least on support patch version is set.
+ *
+ * @return Boolean
+ * true if at least one version is set
+ * false if none of the versions is set
+ */
+ private Boolean hasValidSupportedVersion() {
+ if (supportedRetailPatch != null && !supportedRetailPatch.isEmpty()) {
+ return true;
+ }
+
+ if (supportedBccPatch != null && !supportedBccPatch.isEmpty()) {
+ return true;
+ }
+
+ if (supportedClassicPatch != null && !supportedClassicPatch.isEmpty()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Create a new Wago.io client and set its owner and the targeted repository.
+ * Additionally the token for authenticating against the Wago.io Api is set.
+ *
+ * @return The created Wago.io client
+ * @throws MojoExecutionException An exception occurring during the execution of a plugin
+ */
+ private WagoClient createWagoClient() throws MojoExecutionException {
+ WagoClient wagoClient = new WagoClient();
+ wagoClient.setToken(getCredentials());
+ wagoClient.setProjectId(projectId);
+
+ return wagoClient;
+ }
+}
diff --git a/src/main/java/com/ragedunicorn/tools/maven/log/DefaultLog.java b/src/main/java/com/ragedunicorn/tools/maven/log/DefaultLog.java
new file mode 100644
index 0000000..75d2da0
--- /dev/null
+++ b/src/main/java/com/ragedunicorn/tools/maven/log/DefaultLog.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2022 Michael Wiesendanger
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.ragedunicorn.tools.maven.log;
+
+@SuppressWarnings("PMD")
+public class DefaultLog implements WagoReleaseLogger {
+ /**
+ * Define default logLevel.
+ * logLevels:
+ * 1 - Error
+ * 2 - Info
+ * 3 - Warning
+ * 4 - Debug
+ */
+ private int logLevel = 3;
+
+ public static final int LOG_LEVEL_ERROR = 1;
+ public static final int LOG_LEVEL_WARNING = 2;
+ public static final int LOG_LEVEL_INFO = 3;
+ public static final int LOG_LEVEL_DEBUG = 4;
+
+ public DefaultLog() {
+ // no op
+ }
+
+ public DefaultLog(int logLevel) {
+ this.logLevel = logLevel;
+ }
+
+ /**
+ * Log a debug message.
+ *
+ * @param content The content to log
+ */
+ public void debug(String content) {
+ if (this.logLevel >= LOG_LEVEL_DEBUG) {
+ System.out.println("[DEBUG] " + content);
+ }
+ }
+
+ /**
+ * Log a debug message.
+ *
+ * @param content The content to log
+ * @param error An error object
+ */
+ public void debug(String content, Throwable error) {
+ if (this.logLevel >= LOG_LEVEL_DEBUG) {
+ System.out.println("[DEBUG] " + content);
+ error.printStackTrace();
+ }
+ }
+
+ /**
+ * Log a debug message.
+ *
+ * @param error An error object
+ */
+ public void debug(Throwable error) {
+ if (this.logLevel >= LOG_LEVEL_DEBUG) {
+ error.printStackTrace();
+ }
+ }
+
+ /**
+ * Returns whether the debug logLevel is enabled or not.
+ *
+ * @return whether the logLevel is enabled or not
+ */
+ public boolean isDebugEnabled() {
+ return this.logLevel >= LOG_LEVEL_DEBUG;
+ }
+
+ /**
+ * Log a info message.
+ *
+ * @param content The content to log
+ */
+ public void info(String content) {
+ if (this.logLevel >= LOG_LEVEL_INFO) {
+ System.out.println("[INFO] " + content);
+ }
+ }
+
+ /**
+ * Log a info message.
+ *
+ * @param content The content to log
+ * @param error An error object
+ */
+ public void info(String content, Throwable error) {
+ if (this.logLevel >= LOG_LEVEL_INFO) {
+ System.out.println("[INFO] " + content);
+ error.printStackTrace();
+ }
+ }
+
+ /**
+ * Log a info message.
+ *
+ * @param error An error object
+ */
+ public void info(Throwable error) {
+ if (this.logLevel >= LOG_LEVEL_INFO) {
+ error.printStackTrace();
+ }
+ }
+
+ /**
+ * Returns whether the info logLevel is enabled or not.
+ *
+ * @return whether the logLevel is enabled or not
+ */
+ public boolean isInfoEnabled() {
+ return this.logLevel >= LOG_LEVEL_INFO;
+ }
+
+ /**
+ * Log a warn message.
+ *
+ * @param content The content to log
+ */
+ public void warn(String content) {
+ if (this.logLevel >= LOG_LEVEL_WARNING) {
+ System.out.println("[WARNING] " + content);
+ }
+ }
+
+ /**
+ * Log a warn message.
+ *
+ * @param content The content to log
+ * @param error An error object
+ */
+ public void warn(String content, Throwable error) {
+ if (this.logLevel >= LOG_LEVEL_WARNING) {
+ System.out.println("[WARNING] " + content);
+ error.printStackTrace();
+ }
+ }
+
+ /**
+ * Log a warn message.
+ *
+ * @param error An error object
+ */
+ public void warn(Throwable error) {
+ if (this.logLevel >= LOG_LEVEL_WARNING) {
+ error.printStackTrace();
+ }
+ }
+
+ /**
+ * Returns whether the warn logLevel is enabled or not.
+ *
+ * @return whether the logLevel is enabled or not
+ */
+ public boolean isWarnEnabled() {
+ return this.logLevel >= LOG_LEVEL_WARNING;
+ }
+
+ /**
+ * Log a error message.
+ *
+ * @param content The content to log
+ */
+ public void error(String content) {
+ if (this.logLevel >= LOG_LEVEL_ERROR) {
+ System.out.println("[ERROR] " + content);
+ }
+ }
+
+ /**
+ * Log a error message.
+ *
+ * @param content The content to log
+ * @param error An error object
+ */
+ public void error(String content, Throwable error) {
+ if (this.logLevel >= LOG_LEVEL_ERROR) {
+ System.out.println("[ERROR] " + content);
+ error.printStackTrace();
+ }
+ }
+
+ /**
+ * Log a error message.
+ *
+ * @param error An error object
+ */
+ public void error(Throwable error) {
+ if (this.logLevel >= LOG_LEVEL_ERROR) {
+ error.printStackTrace();
+ }
+ }
+
+ /**
+ * Returns whether the error logLevel is enabled or not.
+ *
+ * @return whether the logLevel is enabled or not
+ */
+ public boolean isErrorEnabled() {
+ return this.logLevel >= LOG_LEVEL_ERROR;
+ }
+}
diff --git a/src/main/java/com/ragedunicorn/tools/maven/log/WagoReleaseLogger.java b/src/main/java/com/ragedunicorn/tools/maven/log/WagoReleaseLogger.java
new file mode 100644
index 0000000..3c47ff8
--- /dev/null
+++ b/src/main/java/com/ragedunicorn/tools/maven/log/WagoReleaseLogger.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2022 Michael Wiesendanger
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.ragedunicorn.tools.maven.log;
+
+public interface WagoReleaseLogger {
+ void debug(String content);
+
+ void debug(String content, Throwable error);
+
+ void debug(Throwable error);
+
+ void info(String content);
+
+ void info(String content, Throwable error);
+
+ void info(Throwable error);
+
+ void warn(String content);
+
+ void warn(String content, Throwable error);
+
+ void warn(Throwable error);
+
+ void error(String content);
+
+ void error(String content, Throwable error);
+
+ void error(Throwable error);
+}
diff --git a/src/main/java/com/ragedunicorn/tools/maven/model/Errors.java b/src/main/java/com/ragedunicorn/tools/maven/model/Errors.java
new file mode 100644
index 0000000..03de2d6
--- /dev/null
+++ b/src/main/java/com/ragedunicorn/tools/maven/model/Errors.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2022 Michael Wiesendanger
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.ragedunicorn.tools.maven.model;
+
+import com.google.gson.annotations.SerializedName;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class Errors {
+ public List metadata = new ArrayList<>();
+ public List file = new ArrayList<>();
+ public List stability = new ArrayList<>();
+ @SerializedName(value = "supported_retail_patch")
+ public List supportedRetailPatch = new ArrayList<>();
+ @SerializedName(value = "supported_bc_patch")
+ public List supportedBccPatch = new ArrayList<>();
+ @SerializedName(value = "supported_classic_patch")
+ public List supportedClassicPatch = new ArrayList<>();
+
+ public List getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(List metadata) {
+ this.metadata = metadata;
+ }
+
+ public List getFile() {
+ return file;
+ }
+
+ public void setFile(List file) {
+ this.file = file;
+ }
+
+ public List getStability() {
+ return stability;
+ }
+
+ public void setStability(List stability) {
+ this.stability = stability;
+ }
+
+ public List getSupportedRetailPatch() {
+ return supportedRetailPatch;
+ }
+
+ public void setSupportedRetailPatch(List supportedRetailPatch) {
+ this.supportedRetailPatch = supportedRetailPatch;
+ }
+
+ public List getSupportedBccPatch() {
+ return supportedBccPatch;
+ }
+
+ public void setSupportedBccPatch(List supportedBccPatch) {
+ this.supportedBccPatch = supportedBccPatch;
+ }
+
+ public List getSupportedClassicPatch() {
+ return supportedClassicPatch;
+ }
+
+ public void setSupportedClassicPatch(List supportedClassicPatch) {
+ this.supportedClassicPatch = supportedClassicPatch;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Errors errors = (Errors) o;
+ return Objects.equals(metadata, errors.metadata)
+ && Objects.equals(file, errors.file)
+ && Objects.equals(stability, errors.stability)
+ && Objects.equals(supportedRetailPatch, errors.supportedRetailPatch)
+ && Objects.equals(supportedBccPatch, errors.supportedBccPatch)
+ && Objects.equals(supportedClassicPatch, errors.supportedClassicPatch);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(metadata, file, stability, supportedRetailPatch, supportedBccPatch, supportedClassicPatch);
+ }
+
+ @Override
+ public String toString() {
+ return "Errors{"
+ + "metadata=" + metadata
+ + ", file=" + file
+ + ", stability=" + stability
+ + ", supportedRetailPatch=" + supportedRetailPatch
+ + ", supportedBccPatch=" + supportedBccPatch
+ + ", supportedClassicPatch=" + supportedClassicPatch
+ + '}';
+ }
+}
diff --git a/src/main/java/com/ragedunicorn/tools/maven/model/Metadata.java b/src/main/java/com/ragedunicorn/tools/maven/model/Metadata.java
new file mode 100644
index 0000000..7bbcef0
--- /dev/null
+++ b/src/main/java/com/ragedunicorn/tools/maven/model/Metadata.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2022 Michael Wiesendanger
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.ragedunicorn.tools.maven.model;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+import java.util.Objects;
+
+public class Metadata {
+
+ @Expose
+ private String label;
+
+ @Expose
+ private String stability;
+
+ @Expose
+ private String changelog;
+
+ @Expose
+ @SerializedName(value = "supported_retail_patch")
+ private String supportedRetailPatch;
+
+ @Expose
+ @SerializedName(value = "supported_bc_patch")
+ private String supportedBccPatch;
+
+ @Expose
+ @SerializedName(value = "supported_classic_patch")
+ private String supportedClassicPatch;
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public String getStability() {
+ return stability;
+ }
+
+ public void setStability(String stability) {
+ this.stability = stability;
+ }
+
+ public String getChangelog() {
+ return changelog;
+ }
+
+ public void setChangelog(String changelog) {
+ this.changelog = changelog;
+ }
+
+ public String getSupportedRetailPatch() {
+ return supportedRetailPatch;
+ }
+
+ public void setSupportedRetailPatch(String supportedRetailPatch) {
+ this.supportedRetailPatch = supportedRetailPatch;
+ }
+
+ public String getSupportedBccPatch() {
+ return supportedBccPatch;
+ }
+
+ public void setSupportedBccPatch(String supportedBccPatch) {
+ this.supportedBccPatch = supportedBccPatch;
+ }
+
+ public String getSupportedClassicPatch() {
+ return supportedClassicPatch;
+ }
+
+ public void setSupportedClassicPatch(String supportedClassicPatch) {
+ this.supportedClassicPatch = supportedClassicPatch;
+ }
+
+ @Override
+ public String toString() {
+ return "Metadata{"
+ + "label='" + label + '\''
+ + ", stability='" + stability + '\''
+ + ", changelog='" + changelog + '\''
+ + ", supportedRetailPatch='" + supportedRetailPatch + '\''
+ + ", supportedBccPatch='" + supportedBccPatch + '\''
+ + ", supportedClassicPatch='" + supportedClassicPatch + '\''
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Metadata metadata = (Metadata) o;
+ return Objects.equals(label, metadata.label)
+ && Objects.equals(stability, metadata.stability)
+ && Objects.equals(changelog, metadata.changelog)
+ && Objects.equals(supportedRetailPatch, metadata.supportedRetailPatch)
+ && Objects.equals(supportedBccPatch, metadata.supportedBccPatch)
+ && Objects.equals(supportedClassicPatch, metadata.supportedClassicPatch);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(label, stability, changelog, supportedRetailPatch, supportedBccPatch, supportedClassicPatch);
+ }
+}
diff --git a/src/main/java/com/ragedunicorn/tools/maven/model/WagoApiClientError.java b/src/main/java/com/ragedunicorn/tools/maven/model/WagoApiClientError.java
new file mode 100644
index 0000000..d7f3799
--- /dev/null
+++ b/src/main/java/com/ragedunicorn/tools/maven/model/WagoApiClientError.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2022 Michael Wiesendanger
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.ragedunicorn.tools.maven.model;
+
+import java.util.Objects;
+
+public class WagoApiClientError {
+ private String message;
+
+ private Errors errors;
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Errors getErrors() {
+ return errors;
+ }
+
+ public void setErrors(Errors errors) {
+ this.errors = errors;
+ }
+
+ @Override
+ public String toString() {
+ return "WagoApiClientError{"
+ + "message='" + message + '\''
+ + ", errors=" + errors
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ WagoApiClientError that = (WagoApiClientError) o;
+ return Objects.equals(message, that.message) && Objects.equals(errors, that.errors);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(message, errors);
+ }
+}
diff --git a/src/main/java/com/ragedunicorn/tools/maven/service/ReleaseService.java b/src/main/java/com/ragedunicorn/tools/maven/service/ReleaseService.java
new file mode 100644
index 0000000..a6d255b
--- /dev/null
+++ b/src/main/java/com/ragedunicorn/tools/maven/service/ReleaseService.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2022 Michael Wiesendanger
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package com.ragedunicorn.tools.maven.service;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.ragedunicorn.tools.maven.WagoClient;
+import com.ragedunicorn.tools.maven.log.DefaultLog;
+import com.ragedunicorn.tools.maven.model.Metadata;
+import com.ragedunicorn.tools.maven.model.WagoApiClientError;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.apache.maven.plugin.MojoExecutionException;
+
+public class ReleaseService {
+ private static final String ENDPOINT = "/api/projects/:projectId/upload-file";
+ private static final String SUCCESS_RESPONSE = "OK";
+
+ private final DefaultLog logger = new DefaultLog();
+
+ private final WagoClient wagoClient;
+
+ public ReleaseService(WagoClient wagoClient) {
+ this.wagoClient = wagoClient;
+ }
+
+ /**
+ * Create a new release.
+ *
+ * @param metadata All metadata related to the upload
+ * @param file Path to the file to upload
+ * @throws MojoExecutionException If the request to the Wago.io Api failed
+ */
+ public void createReleaseOperation(Metadata metadata, String file)
+ throws MojoExecutionException {
+ final Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
+
+ HttpEntity entity = MultipartEntityBuilder
+ .create()
+ .addTextBody("metadata", gson.toJson(metadata))
+ .addBinaryBody("file", new File(file), ContentType.create("application/octet-stream"),
+ metadata.getLabel())
+ .build();
+
+ CloseableHttpClient httpClient = wagoClient.getHttpClient();
+
+ HttpPost httpPost = new HttpPost();
+ URI preparedEndpointUrl = wagoClient.prepareEndpointUri(ENDPOINT);
+ if (logger.isDebugEnabled()) {
+ logger.debug("Endpoint Uri: " + preparedEndpointUrl.getPath());
+ }
+ httpPost.setURI(preparedEndpointUrl);
+ httpPost.setEntity(entity);
+
+ try {
+ CloseableHttpResponse response = httpClient.execute(httpPost);
+ String responseString = responseHandler(response);
+
+ if (logger.isInfoEnabled() && responseString.equals(SUCCESS_RESPONSE)) {
+ logger.info("Upload successful");
+ }
+ } catch (IOException e) {
+ throw new MojoExecutionException("Upload to Wago.io failed", e);
+ }
+
+ try {
+ httpClient.close();
+ } catch (IOException e) {
+ throw new MojoExecutionException("Failed to close http client", e);
+ }
+ }
+
+ /**
+ * Check if the release request was successful and handle both failure and success.
+ *
+ * @param response The response from the Wago.io Api
+ * @return The response from the Wago.io Api as POJO
+ * @throws IOException If entity cannot be converted to a string
+ * @throws MojoExecutionException If creation of release failed
+ */
+ private String responseHandler(CloseableHttpResponse response)
+ throws IOException, MojoExecutionException {
+ final Gson gson = new Gson();
+ final HttpEntity entity = response.getEntity();
+ final String responseString = EntityUtils.toString(entity, StandardCharsets.UTF_8);
+ final int statusCode = response.getStatusLine().getStatusCode();
+
+ if (statusCode != HttpStatus.SC_CREATED) {
+ WagoApiClientError clientError = gson.fromJson(responseString, WagoApiClientError.class);
+ logger.error(clientError.toString());
+
+ throw new MojoExecutionException("Failed to create release - reason: "
+ + clientError);
+ } else {
+ return responseString;
+ }
+ }
+}
diff --git a/src/test/java/com/ragedunicorn/tools/maven/WagoReleaseMojoTest.java b/src/test/java/com/ragedunicorn/tools/maven/WagoReleaseMojoTest.java
new file mode 100644
index 0000000..7f90878
--- /dev/null
+++ b/src/test/java/com/ragedunicorn/tools/maven/WagoReleaseMojoTest.java
@@ -0,0 +1,36 @@
+package com.ragedunicorn.tools.maven;
+
+import org.apache.maven.plugin.testing.AbstractMojoTestCase;
+import java.io.File;
+
+public class WagoReleaseMojoTest extends AbstractMojoTestCase {
+
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ /**
+ * Tests the proper discovery and configuration of the mojo.
+ *
+ * @throws Exception If failing to extract plugin configuration
+ */
+ public void testBasicPluginConfiguration() throws Exception {
+
+ File testPom = new File("src/test/resources/plugin-config.xml" );
+ assertNotNull(testPom);
+ assertTrue(testPom.exists());
+
+ WagoReleaseMojo mojo = new WagoReleaseMojo();
+ mojo = (WagoReleaseMojo) configureMojo(
+ mojo, extractPluginConfiguration("wago-release-maven-plugin", testPom)
+ );
+
+ assertNotNull(mojo);
+
+ // mojo.execute(); execution requires wago backend
+ }
+}
diff --git a/src/test/java/com/ragedunicorn/tools/maven/WagoReleaseWagoClientTest.java b/src/test/java/com/ragedunicorn/tools/maven/WagoReleaseWagoClientTest.java
new file mode 100644
index 0000000..9e76037
--- /dev/null
+++ b/src/test/java/com/ragedunicorn/tools/maven/WagoReleaseWagoClientTest.java
@@ -0,0 +1,43 @@
+package com.ragedunicorn.tools.maven;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.net.URI;
+import java.util.Arrays;
+
+public class WagoReleaseWagoClientTest {
+ @Test
+ public void testEndpointUriPreparation() {
+ final String ENDPOINT = "https://addons.wago.io/api/projects/:projectId/version";
+ final String projectId = "111111";
+
+ WagoClient client = new WagoClient();
+ client.setProjectId(projectId);
+ client.setToken("test-token");
+
+ try {
+ URI preparedUri = client.prepareEndpointUri(ENDPOINT);
+ Assert.assertEquals(preparedUri.toString(), "https://addons.wago.io/api/projects/" + projectId + "/version");
+ } catch (MojoExecutionException e) {
+ Assert.fail("MojoExecutionException: " + Arrays.toString(e.getStackTrace()));
+ }
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testPrepareEndpointUriExpectedInvalidState() {
+ WagoClient client = new WagoClient();
+ try {
+ client.prepareEndpointUri("/some/url");
+ } catch (MojoExecutionException e) {
+ Assert.fail("MojoExecutionException: " + Arrays.toString(e.getStackTrace()));
+ }
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testGetClientUriExpectedInvalidState() {
+ WagoClient client = new WagoClient();
+ client.getHttpClient();
+ }
+}
diff --git a/src/test/resources/plugin-config.xml b/src/test/resources/plugin-config.xml
new file mode 100644
index 0000000..6527579
--- /dev/null
+++ b/src/test/resources/plugin-config.xml
@@ -0,0 +1,28 @@
+
+ 4.0.0
+ com.ragedunicorn.tools.maven
+ test
+ jar
+ 1.0.0
+
+
+
+
+ com.ragedunicorn.tools.maven
+ wago-release-maven-plugin
+ 1.0.0-SNAPSHOT
+
+ LvNAj96o
+
+ release description overwritten by release notes
+ src/main/resources/release-notes-example.md
+ 1.13.7
+ stable
+ src/main/resources/asset-zip-example.zip
+ wago-token
+
+
+
+
+