Skip to content

Commit

Permalink
Automatic project ID resolution & large code cleanup (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
triphora authored Jun 11, 2022
1 parent 8d513a8 commit e1bd440
Show file tree
Hide file tree
Showing 11 changed files with 302 additions and 226 deletions.
6 changes: 4 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ plugins {
id 'com.gradle.plugin-publish' version '1.0.0-rc-2'
}

version = '2.2.1'
version = '2.3.0'
group = 'com.modrinth.minotaur'
archivesBaseName = 'Minotaur'
description = 'Modrinth plugin for publishing builds to the website!'
Expand All @@ -26,11 +26,13 @@ repositories {
dependencies {
compileOnly gradleApi()

compileOnly group: "net.fabricmc", name: "fabric-loom", version: "0.12.48"
compileOnly group: 'net.fabricmc', name: 'fabric-loom', version: '0.12.48'

implementation group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.5.13'
implementation group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.13'
implementation group: 'com.google.code.gson', name: 'gson', version: '2.9.0'

compileOnly group: 'org.jetbrains', name: 'annotations', version: '+'
}

gradlePlugin {
Expand Down
15 changes: 13 additions & 2 deletions src/main/java/com/modrinth/minotaur/Minotaur.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,29 @@
import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.tasks.TaskContainer;
import org.jetbrains.annotations.ApiStatus;

import static com.modrinth.minotaur.Util.getExtension;

/**
* The main class for Minotaur.
*/
public class Minotaur implements Plugin<Project> {
/**
* Internal utility for grabbing the project which Minotaur is applied to
*/
@ApiStatus.Internal
public static Project project;

/**
* Creates the {@link ModrinthExtension} for the project and registers the {@code modrinth} and
* {@code modrinthSyncBody} tasks.
* @param project The Gradle project which Minotaur is applied to
*/
@Override
public void apply(final Project project) {
Minotaur.project = project;

project.getExtensions().create("modrinth", ModrinthExtension.class, project);
project.getLogger().debug("Created the `modrinth` extension.");

Expand All @@ -35,9 +46,9 @@ public void apply(final Project project) {
project.getLogger().debug("Registered the `modrinthSyncBody` task.");

project.afterEvaluate(evaluatedProject -> {
ModrinthExtension extension = evaluatedProject.getExtensions().getByType(ModrinthExtension.class);
ModrinthExtension extension = getExtension();
Task task = evaluatedProject.getTasks().getByName("modrinth");
task.dependsOn(extension.getUploadFile());
task.dependsOn(extension.getUploadFile().get());
for (Object file : extension.getAdditionalFiles().get()) {
task.dependsOn(file);
}
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/com/modrinth/minotaur/ModrinthExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public class ModrinthExtension extends DependencyDSL {
* The default API URL in use for uploading. Exposed as a fallback utility.
*/
public static final String DEFAULT_API_URL = "https://api.modrinth.com/v2";
/**
* The staging API URL if desired for testing.
*/
public static final String STAGING_API_URL = "https://staging-api.modrinth.com/v2";
/**
* The default token in use for uploading. Exposed as a fallback utility.
*/
Expand Down Expand Up @@ -107,7 +111,7 @@ public Property<String> getChangelog() {

/**
* @return The upload artifact file. This can be any object type that is resolvable by
* {@link TaskModrinthUpload#resolveFile(Project, Object)}.
* {@link Util#resolveFile(Object)}.
*/
public Property<Object> getUploadFile() {
return this.uploadFile;
Expand Down
81 changes: 36 additions & 45 deletions src/main/java/com/modrinth/minotaur/TaskModrinthSyncBody.java
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
package com.modrinth.minotaur;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.modrinth.minotaur.responses.ResponseError;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPatch;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.tasks.TaskAction;
import org.jetbrains.annotations.Nullable;

import javax.annotation.Nullable;
import java.io.IOException;
import static com.modrinth.minotaur.Util.getExtension;
import static com.modrinth.minotaur.Util.getUploadEndpoint;
import static com.modrinth.minotaur.Util.resolveId;

/**
* A task used to communicate with Modrinth for the purpose of syncing project body with, for example, a README.
Expand All @@ -27,12 +25,12 @@ public class TaskModrinthSyncBody extends DefaultTask {
/**
* Constant gson instance used for deserializing the API responses.
*/
private final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
private final Gson GSON = Util.createGsonInstance();

/**
* The extension used for getting the data supplied in the buildscript.
*/
private final ModrinthExtension extension = getProject().getExtensions().getByType(ModrinthExtension.class);
private final ModrinthExtension extension = getExtension();

/**
* The response from the API when the body failed to upload.
Expand All @@ -46,37 +44,36 @@ public class TaskModrinthSyncBody extends DefaultTask {
@TaskAction
public void apply() {
this.getLogger().lifecycle("Minotaur: {}", this.getClass().getPackage().getImplementationVersion());
try {
if (extension.getSyncBodyFrom().getOrNull() == null) {
this.getProject().getLogger().error("Sync project body task was called, but `syncBodyFrom` was null!");
throw new GradleException("Sync project body task was called, but `syncBodyFrom` was null!");
}

if (extension.getSyncBodyFrom().getOrNull() == null) {
this.getProject().getLogger().error("Sync project body task was called, but `syncBodyFrom` was null!");
throw new GradleException("Sync project body task was called, but `syncBodyFrom` was null!");
}

String excludeRegex = "(?m)<!-- modrinth_exclude\\.start -->(.|\n)*?<!-- modrinth_exclude\\.end -->";
String excludeRegex = "(?m)<!-- modrinth_exclude\\.start -->(.|\n)*?<!-- modrinth_exclude\\.end -->";

final HttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(RequestConfig.custom().setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build();
final HttpPatch patch = new HttpPatch(this.getUploadEndpoint());
final HttpClient client = Util.createHttpClient();
final HttpPatch patch = new HttpPatch(getUploadEndpoint() + "project/" + resolveId(extension.getProjectId().get()));

patch.addHeader("Authorization", extension.getToken().get());
patch.addHeader("Authorization", extension.getToken().get());

JsonObject data = new JsonObject();
data.addProperty("body", extension.getSyncBodyFrom().get().replaceAll(excludeRegex, "").replaceAll("\r\n", "\n"));
JsonObject data = new JsonObject();
data.addProperty("body", extension.getSyncBodyFrom().get().replaceAll(excludeRegex, "").replaceAll("\r\n", "\n"));

if (extension.getDebugMode().get()) {
this.getProject().getLogger().lifecycle("Full data to be sent for upload: {}", data);
this.getProject().getLogger().lifecycle("Minotaur debug mode is enabled. Not going to upload the body.");
return;
}
if (extension.getDebugMode().get()) {
this.getProject().getLogger().lifecycle("Full data to be sent for upload: {}", data);
this.getProject().getLogger().lifecycle("Minotaur debug mode is enabled. Not going to upload the body.");
return;
}

try {
patch.setEntity(new StringEntity(GSON.toJson(data), ContentType.APPLICATION_JSON));
} catch (StackOverflowError e) {
String error = "StackOverflowError whilst trying to parse modrinth_exclude tags; please make the amount of text within each of these tags smaller";
this.getProject().getLogger().error(error);
throw new GradleException(error, e);
}
try {
patch.setEntity(new StringEntity(GSON.toJson(data), ContentType.APPLICATION_JSON));
} catch (StackOverflowError e) {
String error = "StackOverflowError whilst trying to parse modrinth_exclude tags; please make the amount of text within each of these tags smaller";
this.getProject().getLogger().error(error);
throw new GradleException(error, e);
}

try {
final HttpResponse response = client.execute(patch);
final int status = response.getStatusLine().getStatusCode();

Expand All @@ -87,19 +84,13 @@ public void apply() {
this.getProject().getLogger().error("Syncing failed! Status: {} Error: {} Reason: {}", status, this.errorInfo.getError(), this.errorInfo.getDescription());
throw new GradleException("Syncing failed! Status: " + status + " Reason: " + this.errorInfo.getDescription());
}
} catch (final IOException e) {
this.getProject().getLogger().error("Failed to sync project body!", e);
throw new GradleException("Failed to sync project body!", e);
} catch (final Exception e) {
if (extension.getFailSilently().get()) {
this.getLogger().info("Failed to sync body to Modrinth. Check logs for more info.");
this.getLogger().error("Modrinth body sync failed silently.", e);
} else {
throw new GradleException("Failed to sync project body!", e);
}
}
}

/**
* Provides the upload API endpoint to use.
*
* @return The upload API endpoint.
*/
private String getUploadEndpoint() {
String apiUrl = extension.getApiUrl().get();
return apiUrl + (apiUrl.endsWith("/") ? "" : "/") + "project/" + extension.getProjectId().get();
}
}
Loading

0 comments on commit e1bd440

Please sign in to comment.