move RPM plugin package, add new Sonatype Publish plugin
This commit is contained in:
parent
9784dc72d7
commit
017df58da6
26 changed files with 484 additions and 18 deletions
|
@ -1,16 +1,14 @@
|
||||||
|
|
||||||
group = 'org.xbib.gradle.plugin'
|
|
||||||
|
|
||||||
wrapper {
|
wrapper {
|
||||||
gradleVersion = libs.versions.gradle.get()
|
gradleVersion = libs.versions.gradle.get()
|
||||||
distributionType = Wrapper.DistributionType.BIN
|
distributionType = Wrapper.DistributionType.BIN
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
user = 'jprante'
|
name = rootProject.name
|
||||||
name = 'gradle-plugins'
|
|
||||||
description = 'Gradle plugins'
|
description = 'Gradle plugins'
|
||||||
inceptionYear = '2021'
|
inceptionYear = '2021'
|
||||||
|
user = 'jprante'
|
||||||
url = 'https://github.com/' + user + '/' + name
|
url = 'https://github.com/' + user + '/' + name
|
||||||
scmUrl = 'https://github.com/' + user + '/' + name
|
scmUrl = 'https://github.com/' + user + '/' + name
|
||||||
scmConnection = 'scm:git:git://github.com/' + user + '/' + name + '.git'
|
scmConnection = 'scm:git:git://github.com/' + user + '/' + name + '.git'
|
||||||
|
|
|
@ -35,7 +35,7 @@ if (project.hasProperty('gradle.publish.key')) {
|
||||||
version = project.version
|
version = project.version
|
||||||
description = 'Java implementation for RPM packaging'
|
description = 'Java implementation for RPM packaging'
|
||||||
displayName = 'Java implementation for RPM packaging'
|
displayName = 'Java implementation for RPM packaging'
|
||||||
implementationClass = 'org.xbib.gradle.plugin.RpmPlugin'
|
implementationClass = 'org.xbib.gradle.plugin.rpm.RpmPlugin'
|
||||||
tags.set(['rpm'])
|
tags.set(['rpm'])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package org.xbib.gradle.plugin
|
package org.xbib.gradle.plugin.rpm
|
||||||
|
|
||||||
import org.gradle.api.internal.file.copy.CopyAction
|
import org.gradle.api.internal.file.copy.CopyAction
|
||||||
import org.gradle.api.tasks.Input
|
import org.gradle.api.tasks.Input
|
|
@ -1,4 +1,4 @@
|
||||||
package org.xbib.gradle.plugin
|
package org.xbib.gradle.plugin.rpm
|
||||||
|
|
||||||
import groovy.util.logging.Log
|
import groovy.util.logging.Log
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
|
@ -1,4 +1,4 @@
|
||||||
package org.xbib.gradle.plugin
|
package org.xbib.gradle.plugin.rpm
|
||||||
|
|
||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
|
@ -1,9 +1,10 @@
|
||||||
package org.xbib.gradle.plugin
|
package org.xbib.gradle.plugin.rpm.test
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.testfixtures.ProjectBuilder
|
import org.gradle.testfixtures.ProjectBuilder
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.xbib.gradle.plugin.rpm.Rpm
|
||||||
import org.xbib.rpm.RpmReader
|
import org.xbib.rpm.RpmReader
|
||||||
import org.xbib.rpm.RpmReaderResult
|
import org.xbib.rpm.RpmReaderResult
|
||||||
import org.xbib.rpm.format.Format
|
import org.xbib.rpm.format.Format
|
|
@ -1,4 +1,4 @@
|
||||||
package org.xbib.gradle.plugin
|
package org.xbib.gradle.plugin.rpm.test
|
||||||
|
|
||||||
import org.gradle.testkit.runner.BuildResult
|
import org.gradle.testkit.runner.BuildResult
|
||||||
import org.gradle.testkit.runner.GradleRunner
|
import org.gradle.testkit.runner.GradleRunner
|
|
@ -1,9 +1,10 @@
|
||||||
package org.xbib.gradle.plugin
|
package org.xbib.gradle.plugin.rpm.test
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.testfixtures.ProjectBuilder
|
import org.gradle.testfixtures.ProjectBuilder
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.xbib.gradle.plugin.rpm.Rpm
|
||||||
import org.xbib.rpm.RpmReader
|
import org.xbib.rpm.RpmReader
|
||||||
import org.xbib.rpm.changelog.ChangelogParser
|
import org.xbib.rpm.changelog.ChangelogParser
|
||||||
import org.xbib.rpm.format.Format
|
import org.xbib.rpm.format.Format
|
|
@ -1,9 +1,10 @@
|
||||||
package org.xbib.gradle.plugin
|
package org.xbib.gradle.plugin.rpm.test
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.testfixtures.ProjectBuilder
|
import org.gradle.testfixtures.ProjectBuilder
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.xbib.gradle.plugin.rpm.Rpm
|
||||||
import org.xbib.rpm.RpmReader
|
import org.xbib.rpm.RpmReader
|
||||||
import org.xbib.rpm.signature.SignatureTag
|
import org.xbib.rpm.signature.SignatureTag
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
|
@ -1,17 +1,16 @@
|
||||||
package org.xbib.gradle.plugin
|
package org.xbib.gradle.plugin.rpm.test
|
||||||
|
|
||||||
import groovy.util.logging.Log
|
import groovy.util.logging.Log
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.testfixtures.ProjectBuilder
|
import org.gradle.testfixtures.ProjectBuilder
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.xbib.gradle.plugin.rpm.Rpm
|
||||||
import org.xbib.rpm.RpmReaderResult
|
import org.xbib.rpm.RpmReaderResult
|
||||||
import org.xbib.rpm.RpmReader
|
import org.xbib.rpm.RpmReader
|
||||||
import org.xbib.rpm.format.Format
|
import org.xbib.rpm.format.Format
|
||||||
|
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.util.logging.Level
|
|
||||||
import java.util.logging.Logger
|
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat
|
import static org.hamcrest.MatcherAssert.assertThat
|
||||||
import static org.hamcrest.CoreMatchers.*
|
import static org.hamcrest.CoreMatchers.*
|
0
gradle-plugin-sonatype-publish/NOTICE.txt
Normal file
0
gradle-plugin-sonatype-publish/NOTICE.txt
Normal file
42
gradle-plugin-sonatype-publish/build.gradle
Normal file
42
gradle-plugin-sonatype-publish/build.gradle
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
plugins {
|
||||||
|
id 'java-gradle-plugin'
|
||||||
|
alias(libs.plugins.publish)
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'java-gradle-plugin'
|
||||||
|
apply plugin: 'com.gradle.plugin-publish'
|
||||||
|
|
||||||
|
apply from: rootProject.file('gradle/compile/java.gradle')
|
||||||
|
apply from: rootProject.file('gradle/test/junit5.gradle')
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api gradleApi()
|
||||||
|
testImplementation gradleTestKit()
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = 'localRepository'
|
||||||
|
url = 'build/local-repository'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (project.hasProperty('gradle.publish.key')) {
|
||||||
|
gradlePlugin {
|
||||||
|
website = 'https://xbib.org/joerg/gradle-plugins/src/branch/main/gradle-plugin-sonatype-publish'
|
||||||
|
vcsUrl = 'https://xbib.org/joerg/gradle-plugins'
|
||||||
|
plugins {
|
||||||
|
sonatypePublishPlugin {
|
||||||
|
id = 'org.xbib.gradle.plugin.sonatype.publish'
|
||||||
|
group = project.group
|
||||||
|
version = project.version
|
||||||
|
description = 'Sonatype publishing plugin'
|
||||||
|
displayName = 'Sonatype publishing plugin'
|
||||||
|
implementationClass = 'org.xbib.gradle.plugin.sonatype.publish.SonatypePublishPlugin'
|
||||||
|
tags.set(['sonatype', 'publish', 'mavencentral'])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
gradle-plugin-sonatype-publish/gradle.properties
Normal file
2
gradle-plugin-sonatype-publish/gradle.properties
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
name = gradle-plugin-sonatype-publish
|
||||||
|
version = 1.0.0
|
|
@ -0,0 +1,62 @@
|
||||||
|
package org.xbib.gradle.plugin.sonatype.publish;
|
||||||
|
|
||||||
|
import org.gradle.api.file.DirectoryProperty;
|
||||||
|
import org.gradle.api.model.ObjectFactory;
|
||||||
|
import org.gradle.api.provider.Property;
|
||||||
|
|
||||||
|
import static org.xbib.gradle.plugin.sonatype.publish.SonatypePublishHelper.STATUS_URL;
|
||||||
|
import static org.xbib.gradle.plugin.sonatype.publish.SonatypePublishHelper.UPLOAD_URL;
|
||||||
|
|
||||||
|
public class DefaultSonatypePublishExtension implements SonatypePublishExtension {
|
||||||
|
|
||||||
|
private static final Integer MAX_WAIT_SECONDS = 60;
|
||||||
|
|
||||||
|
private final Property<String> uploadUrl;
|
||||||
|
|
||||||
|
private final Property<String> publishingType;
|
||||||
|
|
||||||
|
private final Property<String> statusUrl;
|
||||||
|
|
||||||
|
private final Property<String> authToken;
|
||||||
|
|
||||||
|
private final DirectoryProperty repoDir;
|
||||||
|
|
||||||
|
private final Property<Integer> maxWait;
|
||||||
|
|
||||||
|
public DefaultSonatypePublishExtension(ObjectFactory objectFactory) {
|
||||||
|
uploadUrl = objectFactory.property(String.class).convention(UPLOAD_URL);
|
||||||
|
statusUrl = objectFactory.property(String.class).convention(STATUS_URL);
|
||||||
|
publishingType = objectFactory.property(String.class).convention(PublishingType.AUTOMATIC.name());
|
||||||
|
authToken = objectFactory.property(String.class);
|
||||||
|
repoDir = objectFactory.directoryProperty();
|
||||||
|
maxWait = objectFactory.property(Integer.class).convention(MAX_WAIT_SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Property<String> getUploadUrl() {
|
||||||
|
return uploadUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Property<String> getPublishingType() { return publishingType; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Property<String> getStatusUrl() {
|
||||||
|
return statusUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Property<String> getAuthToken() {
|
||||||
|
return authToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DirectoryProperty getRepoDir() {
|
||||||
|
return repoDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Property<Integer> getMaxWait() {
|
||||||
|
return maxWait;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package org.xbib.gradle.plugin.sonatype.publish;
|
||||||
|
|
||||||
|
enum DeploymentStatus {
|
||||||
|
FAILED, PUBLISHING, PUBLISHED, PENDING, VALIDATED;
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.xbib.gradle.plugin.sonatype.publish;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether to publish the artifact immediately, or to hold it back behind Publish button
|
||||||
|
* in the Sonatype Central Portal panel.
|
||||||
|
*/
|
||||||
|
public enum PublishingType {
|
||||||
|
/**
|
||||||
|
* The Publish button will be pressed for you immediately after a successful validation. This is
|
||||||
|
* the default.
|
||||||
|
*/
|
||||||
|
AUTOMATIC,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Publish button will be there for you to press in the Sonatype Central Portal panel.
|
||||||
|
*/
|
||||||
|
USER_MANAGED,
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package org.xbib.gradle.plugin.sonatype.publish;
|
||||||
|
|
||||||
|
import org.gradle.api.file.DirectoryProperty;
|
||||||
|
import org.gradle.api.provider.Property;
|
||||||
|
|
||||||
|
public interface SonatypePublishExtension {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload URL for uploading a deployment bundle.
|
||||||
|
*
|
||||||
|
* @return URL string
|
||||||
|
*/
|
||||||
|
Property<String> getUploadUrl();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to publish automatically or manually after a successful upload.
|
||||||
|
*
|
||||||
|
* @return Publishing type
|
||||||
|
*/
|
||||||
|
Property<String> getPublishingType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The URL for retrieving status of a deployment.
|
||||||
|
*
|
||||||
|
* @return URL string
|
||||||
|
*/
|
||||||
|
Property<String> getStatusUrl();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The authorization toke for calling central portal APIs
|
||||||
|
*
|
||||||
|
* @return Token string
|
||||||
|
*/
|
||||||
|
Property<String> getAuthToken();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The repository directory for zipping the bundle.
|
||||||
|
* It is usually a local directory published by the Maven publish plugin.
|
||||||
|
*
|
||||||
|
* @return Repository directory
|
||||||
|
*/
|
||||||
|
DirectoryProperty getRepoDir();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Max wait time for status API to get 'PUBLISHING' or 'PUBLISHED' status when the
|
||||||
|
* publishing type is 'AUTOMATIC', or additionally 'VALIDATED' when the publishing type is
|
||||||
|
* 'USER_MANAGED'.
|
||||||
|
*
|
||||||
|
* @return Duration in seconds
|
||||||
|
*/
|
||||||
|
Property<Integer> getMaxWait();
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
package org.xbib.gradle.plugin.sonatype.publish;
|
||||||
|
|
||||||
|
import groovy.json.JsonSlurper;
|
||||||
|
import org.gradle.api.GradleException;
|
||||||
|
import org.gradle.api.logging.Logger;
|
||||||
|
import org.gradle.api.logging.Logging;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpRequest.BodyPublisher;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.net.http.HttpResponse.BodyHandlers;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static java.net.http.HttpRequest.BodyPublishers.noBody;
|
||||||
|
import static java.net.http.HttpRequest.BodyPublishers.ofFile;
|
||||||
|
import static java.net.http.HttpRequest.BodyPublishers.ofString;
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
public class SonatypePublishHelper {
|
||||||
|
|
||||||
|
private static final Logger logger = Logging.getLogger(SonatypePublishHelper.class);
|
||||||
|
|
||||||
|
private static final String CRLF = "\r\n";
|
||||||
|
|
||||||
|
static final String UPLOAD_URL = "https://central.sonatype.com/api/v1/publisher/upload";
|
||||||
|
|
||||||
|
static final String STATUS_URL = "https://central.sonatype.com/api/v1/publisher/status";
|
||||||
|
|
||||||
|
static final String CHECKING_URL = "https://central.sonatype.com/publishing/deployments";
|
||||||
|
|
||||||
|
private final HttpClient httpClient;
|
||||||
|
|
||||||
|
public SonatypePublishHelper() {
|
||||||
|
httpClient = HttpClient.newHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String uploadBundle(String url,
|
||||||
|
String publishingType,
|
||||||
|
String token,
|
||||||
|
Path uploadFile) throws IOException, InterruptedException {
|
||||||
|
String boundary = UUID.randomUUID().toString().replace("-", "");
|
||||||
|
BodyPublisher filePartPublisher = getFilePartPublisher(boundary, uploadFile);
|
||||||
|
HttpRequest request = HttpRequest.newBuilder(URI.create(url + "?publishingType=" + publishingType))
|
||||||
|
.header("Authorization", "Bearer " + token)
|
||||||
|
.header("Content-Type", "multipart/form-data; boundary=" + boundary)
|
||||||
|
.POST(filePartPublisher)
|
||||||
|
.build();
|
||||||
|
logger.info("request = " + request);
|
||||||
|
HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString(UTF_8));
|
||||||
|
int statusCode = response.statusCode();
|
||||||
|
String body = response.body();
|
||||||
|
if (statusCode == 201) {
|
||||||
|
logger.lifecycle("Upload success, response body: {}", body);
|
||||||
|
return body;
|
||||||
|
} else {
|
||||||
|
throw new GradleException(String.format("upload failed, status code: %d, response body: %s", statusCode, body));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDeploymentStatus(String url,
|
||||||
|
String token,
|
||||||
|
String deploymentId) throws IOException, InterruptedException {
|
||||||
|
HttpRequest request = HttpRequest.newBuilder(URI.create(url + "?id=" + deploymentId))
|
||||||
|
.header("Authorization", "Bearer " + token)
|
||||||
|
.POST(noBody())
|
||||||
|
.build();
|
||||||
|
logger.info("request = " + request);
|
||||||
|
HttpResponse<String> response = httpClient.send(request, BodyHandlers.ofString(UTF_8));
|
||||||
|
int statusCode = response.statusCode();
|
||||||
|
String body = response.body();
|
||||||
|
if (statusCode == 200) {
|
||||||
|
logger.lifecycle("checking deployment status, response body: {}", body);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, Object> jsonObject = (Map<String, Object>) new JsonSlurper().parseText(body);
|
||||||
|
return (String) jsonObject.get("deploymentState");
|
||||||
|
} else {
|
||||||
|
throw new GradleException(String.format("status failed, status code: %d, response body: %s", statusCode, body));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BodyPublisher getFilePartPublisher(String boundary, Path file) throws FileNotFoundException {
|
||||||
|
String boundaryStart = CRLF + "--" + boundary + CRLF;
|
||||||
|
String boundaryEnd = CRLF + "--" + boundary + "--";
|
||||||
|
String partMeta = getFilePartMeta(boundaryStart, file.getFileName());
|
||||||
|
return HttpRequest.BodyPublishers.concat(ofString(partMeta), ofFile(file), ofString(boundaryEnd));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getFilePartMeta(String boundaryStart, Path fileName) {
|
||||||
|
return boundaryStart +
|
||||||
|
"Content-Disposition: form-data; name=\"bundle\"; filename=\"" + fileName + "\"" + CRLF +
|
||||||
|
"Content-Type: application/octet-stream" + CRLF +
|
||||||
|
CRLF;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package org.xbib.gradle.plugin.sonatype.publish;
|
||||||
|
|
||||||
|
import org.gradle.api.Plugin;
|
||||||
|
import org.gradle.api.Project;
|
||||||
|
import org.gradle.api.tasks.bundling.Zip;
|
||||||
|
|
||||||
|
public class SonatypePublishPlugin implements Plugin<Project> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(Project project) {
|
||||||
|
SonatypePublishExtension extension = project.getExtensions()
|
||||||
|
.create(SonatypePublishExtension.class, "sonatypePublish", DefaultSonatypePublishExtension.class, project.getObjects());
|
||||||
|
Zip zipTask = project.getTasks().register("bundleForPublish", Zip.class).get();
|
||||||
|
zipTask.setGroup("publishing");
|
||||||
|
zipTask.from(extension.getRepoDir());
|
||||||
|
SonatypePublishTask sonatypePublishTask = project.getTasks().register("publishToSonatype", SonatypePublishTask.class).get();
|
||||||
|
sonatypePublishTask.setGroup("publishing");
|
||||||
|
sonatypePublishTask.dependsOn(zipTask);
|
||||||
|
sonatypePublishTask.setUploadFile(zipTask.getArchiveFile());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
package org.xbib.gradle.plugin.sonatype.publish;
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.GradleException;
|
||||||
|
import org.gradle.api.InvalidUserDataException;
|
||||||
|
import org.gradle.api.file.RegularFile;
|
||||||
|
import org.gradle.api.file.RegularFileProperty;
|
||||||
|
import org.gradle.api.provider.Provider;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.xbib.gradle.plugin.sonatype.publish.DeploymentStatus.FAILED;
|
||||||
|
import static org.xbib.gradle.plugin.sonatype.publish.DeploymentStatus.PUBLISHED;
|
||||||
|
import static org.xbib.gradle.plugin.sonatype.publish.DeploymentStatus.PUBLISHING;
|
||||||
|
import static org.xbib.gradle.plugin.sonatype.publish.DeploymentStatus.VALIDATED;
|
||||||
|
import static org.xbib.gradle.plugin.sonatype.publish.PublishingType.USER_MANAGED;
|
||||||
|
import static org.xbib.gradle.plugin.sonatype.publish.SonatypePublishHelper.CHECKING_URL;
|
||||||
|
|
||||||
|
public abstract class SonatypePublishTask extends DefaultTask {
|
||||||
|
|
||||||
|
private final SonatypePublishExtension extension;
|
||||||
|
|
||||||
|
private final SonatypePublishHelper sonatypePublishHelper;
|
||||||
|
|
||||||
|
@SuppressWarnings("this-escape")
|
||||||
|
public SonatypePublishTask() {
|
||||||
|
this.sonatypePublishHelper = new SonatypePublishHelper();
|
||||||
|
SonatypePublishExtension extension = getProject().getExtensions().findByType(SonatypePublishExtension.class);
|
||||||
|
if (extension == null) {
|
||||||
|
extension = getProject().getExtensions().create(SonatypePublishExtension.class, "sonatypePublish",
|
||||||
|
DefaultSonatypePublishExtension.class, getProject().getObjects());
|
||||||
|
}
|
||||||
|
this.extension = Objects.requireNonNull(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
public void executeTask() throws InterruptedException, IOException {
|
||||||
|
if (!extension.getAuthToken().isPresent()) {
|
||||||
|
throw new InvalidUserDataException("auth token is not provided for Sonatype publishing");
|
||||||
|
}
|
||||||
|
RegularFileProperty regularFileProperty = getProject().getObjects().fileProperty();
|
||||||
|
if (!regularFileProperty.isPresent()) {
|
||||||
|
throw new InvalidUserDataException("no upload file");
|
||||||
|
}
|
||||||
|
PublishingType type = PublishingType.valueOf(extension.getPublishingType().get().toUpperCase(Locale.ROOT));
|
||||||
|
Path deployment = regularFileProperty.get().getAsFile().toPath();
|
||||||
|
getLogger().lifecycle("Sonatype publishing deployment = {}", deployment);
|
||||||
|
String deploymentId = sonatypePublishHelper.uploadBundle(extension.getUploadUrl().get(),
|
||||||
|
extension.getPublishingType().get(), extension.getAuthToken().get(), deployment);
|
||||||
|
getLogger().lifecycle("Sonatype publishing deployment ID = {}", deploymentId);
|
||||||
|
int seconds = 10;
|
||||||
|
int count = 0;
|
||||||
|
int checkCount = extension.getMaxWait().get() / seconds;
|
||||||
|
checkCount = checkCount <= 0 ? 1 : checkCount;
|
||||||
|
while (count < checkCount) {
|
||||||
|
TimeUnit.SECONDS.sleep(seconds);
|
||||||
|
DeploymentStatus deploymentStatus = DeploymentStatus.valueOf(sonatypePublishHelper.getDeploymentStatus(extension.getStatusUrl().get(),
|
||||||
|
extension.getAuthToken().get(), deploymentId).toUpperCase(Locale.ROOT));
|
||||||
|
boolean success = (type.equals(USER_MANAGED) && VALIDATED.equals(deploymentStatus))
|
||||||
|
|| PUBLISHING.equals(deploymentStatus)
|
||||||
|
|| PUBLISHED.equals(deploymentStatus);
|
||||||
|
if (success) {
|
||||||
|
getLogger().lifecycle("Sonatype publishing successful. Status = {}", deploymentStatus);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (FAILED.equals(deploymentStatus)) {
|
||||||
|
throw new GradleException(String.format("Deployment failed: %s, please visit %s and check your deployment",
|
||||||
|
deploymentStatus.name(), CHECKING_URL));
|
||||||
|
} else {
|
||||||
|
++count;
|
||||||
|
}
|
||||||
|
if (count == checkCount) {
|
||||||
|
throw new GradleException(String.format("Deployment timed out, status is: %s, please visit %s check your deployment",
|
||||||
|
deploymentStatus.name(), CHECKING_URL));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUploadFile(Provider<RegularFile> regularFile) {
|
||||||
|
getProject().getObjects().fileProperty().value(regularFile);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package org.xbib.gradle.plugin.sonatype.publish.test;
|
||||||
|
|
||||||
|
import org.gradle.testkit.runner.BuildResult;
|
||||||
|
import org.gradle.testkit.runner.BuildTask;
|
||||||
|
import org.gradle.testkit.runner.GradleRunner;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.io.TempDir;
|
||||||
|
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
import static org.gradle.testkit.runner.TaskOutcome.FAILED;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
public class SonatypePublishPluginIntegrationTest {
|
||||||
|
|
||||||
|
@TempDir
|
||||||
|
Path testProjectDir;
|
||||||
|
|
||||||
|
private Path settingsFile;
|
||||||
|
|
||||||
|
private Path buildFile;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup() {
|
||||||
|
settingsFile = testProjectDir.resolve("settings.gradle");
|
||||||
|
buildFile = testProjectDir.resolve("build.gradle");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSonatypePublish() throws IOException {
|
||||||
|
writeFile(settingsFile, "rootProject.name = 'sonatype-publish-test'");
|
||||||
|
String buildFileContent = """
|
||||||
|
plugins {
|
||||||
|
id 'org.xbib.gradle.plugin.sonatype.publish'
|
||||||
|
}
|
||||||
|
|
||||||
|
import org.xbib.gradle.plugin.sonatype.publish.SonatypePublishTask
|
||||||
|
|
||||||
|
apply plugin: 'java-library'
|
||||||
|
apply plugin: 'maven-publish'
|
||||||
|
apply plugin: 'signing'
|
||||||
|
apply plugin: 'org.xbib.gradle.plugin.sonatype.publish'
|
||||||
|
|
||||||
|
sonatypePublish {
|
||||||
|
uploadUrl = 'http://localhost'
|
||||||
|
repoDir = layout.buildDirectory.dir('repos/bundles')
|
||||||
|
authToken = 'dummy'
|
||||||
|
publishingType = 'AUTOMATIC'
|
||||||
|
maxWait = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
""";
|
||||||
|
writeFile(buildFile, buildFileContent);
|
||||||
|
assertThrows(Exception.class, ()-> {
|
||||||
|
BuildResult buildResult = GradleRunner.create()
|
||||||
|
.withProjectDir(testProjectDir.toFile())
|
||||||
|
.withArguments(":publish", ":publishToSonatype")
|
||||||
|
.withPluginClasspath()
|
||||||
|
.forwardOutput()
|
||||||
|
.build();
|
||||||
|
BuildTask buildTask = buildResult.task(":publishToSonatype");
|
||||||
|
// "no upload file"
|
||||||
|
assertEquals(FAILED, buildTask.getOutcome());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeFile(Path destination, String content) throws IOException {
|
||||||
|
try (BufferedWriter output = Files.newBufferedWriter(destination)) {
|
||||||
|
output.write(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,3 @@
|
||||||
group = org.xbib.gradle.plugin
|
group = org.xbib.gradle.plugin
|
||||||
name = gradle-plugins
|
name = gradle-plugins
|
||||||
|
|
||||||
# version reflects gradle version plus a patch level version
|
|
||||||
version = 8.7.0
|
version = 8.7.0
|
||||||
|
|
|
@ -13,6 +13,7 @@ test {
|
||||||
failFast = true
|
failFast = true
|
||||||
testLogging {
|
testLogging {
|
||||||
events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED'
|
events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED'
|
||||||
|
showStandardStreams = true
|
||||||
}
|
}
|
||||||
afterSuite { desc, result ->
|
afterSuite { desc, result ->
|
||||||
if (!desc.parent) {
|
if (!desc.parent) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ dependencyResolutionManagement {
|
||||||
// Attention: it is impossible to develop a gradle plugin with groovy 4!
|
// Attention: it is impossible to develop a gradle plugin with groovy 4!
|
||||||
// The gradle plugin publish plugin enforces java-gradle-plugin,
|
// The gradle plugin publish plugin enforces java-gradle-plugin,
|
||||||
// and java-gradle-plugin enforces the embedded groovy of gradle on the compile classpath.
|
// and java-gradle-plugin enforces the embedded groovy of gradle on the compile classpath.
|
||||||
// we keep this here as reference when Gradle switsches to Groovy 4+
|
// we keep this here as reference when Gradle switches to Groovy 4+
|
||||||
//library('groovy-bom', 'org.apache.groovy', 'groovy-bom').versionRef('groovy')
|
//library('groovy-bom', 'org.apache.groovy', 'groovy-bom').versionRef('groovy')
|
||||||
//library('groovy', 'org.apache.groovy', 'groovy').versionRef('groovy')
|
//library('groovy', 'org.apache.groovy', 'groovy').versionRef('groovy')
|
||||||
library('asm', 'org.ow2.asm', 'asm').versionRef('asm')
|
library('asm', 'org.ow2.asm', 'asm').versionRef('asm')
|
||||||
|
@ -57,3 +57,4 @@ include 'gradle-plugin-jlink'
|
||||||
include 'gradle-plugin-jpackage'
|
include 'gradle-plugin-jpackage'
|
||||||
include 'gradle-plugin-rpm'
|
include 'gradle-plugin-rpm'
|
||||||
include 'gradle-plugin-shadow'
|
include 'gradle-plugin-shadow'
|
||||||
|
include 'gradle-plugin-sonatype-publish'
|
||||||
|
|
Loading…
Reference in a new issue