diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index d8e23a9e..feb785d6 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -13,8 +13,6 @@ jobs: strategy: matrix: java: ['17', '21'] - env: - WORKSPACE: ${{ github.workspace }} steps: - name: "📥 Checkout repository" uses: actions/checkout@v4 @@ -86,7 +84,7 @@ jobs: env: DEVELOCITY_BUILD_CACHE_NODE_USER: ${{ secrets.GRADLE_ENTERPRISE_BUILD_CACHE_NODE_USER }} DEVELOCITY_BUILD_CACHE_NODE_KEY: ${{ secrets.GRADLE_ENTERPRISE_BUILD_CACHE_NODE_KEY }} - run: ./gradle groovydoc + run: ./gradlew groovydoc - name: "🚀 Publish to Github Pages" id: docs if: success() diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1199852e..506035dc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -71,7 +71,7 @@ jobs: SECRING_FILE: ${{ secrets.SECRING_FILE }} DEVELOCITY_BUILD_CACHE_NODE_USER: ${{ secrets.GRADLE_ENTERPRISE_BUILD_CACHE_NODE_USER }} DEVELOCITY_BUILD_CACHE_NODE_KEY: ${{ secrets.GRADLE_ENTERPRISE_BUILD_CACHE_NODE_KEY }} - run: | + run: > ./gradlew -Psigning.secretKeyRingFile=${{ github.workspace }}/secring.gpg publishToSonatype @@ -105,7 +105,7 @@ jobs: SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} SONATYPE_STAGING_PROFILE_ID: ${{ secrets.SONATYPE_STAGING_PROFILE_ID }} - run: | + run: > ./gradlew findSonatypeStagingRepository releaseSonatypeStagingRepository @@ -135,6 +135,10 @@ jobs: with: distribution: liberica java-version: 17 + - name: "🐘 Setup Gradle" + uses: gradle/actions/setup-gradle@v4 + with: + develocity-access-key: ${{ secrets.GRADLE_ENTERPRISE_ACCESS_KEY }} - name: "📜 Generate Groovydoc" id: groovydoc env: diff --git a/README.md b/README.md index dd77ee15..e36b0aee 100644 --- a/README.md +++ b/README.md @@ -43,10 +43,7 @@ _Todo_: Add the docs grails-publish --------- -A Gradle plugin to simplify publishing: - -1. snapshots with either the Maven Publish gradle plugin or Nexus Publish gradle plugin. -2. releases with the Nexus Publish gradle plugin. +A Gradle plugin to ease publishing with the maven publish plugin or the nexus publish plugin. Example Usage: @@ -74,23 +71,23 @@ or developers = [johndoe: 'John Doe'] } -By default this plugin will publish to the specified `MAVEN_PUBLISH` instance for snapshots, and `NEXUS_PUBLISH` for releases. To change the snapshot publish behavior, you can set the `snapshotRepoType` to `RepositoryTarget.NEXUS_PUBLISH`. +By default this plugin will publish to the specified `MAVEN_PUBLISH` instance for snapshots, and `NEXUS_PUBLISH` for releases. To change the snapshot publish behavior, set `snapshotRepoType` to `PublishType.NEXUS_PUBLISH`. To change the release publish behavior, set `releaseRepoType` to `PublishType.NEXUS_PUBLISH`. The credentials and connection url must be specified as a project property or an environment variable. -The `MAVEN_PUBLISH` Environment Variables are: +`MAVEN_PUBLISH` Environment Variables are: - ARTIFACTORY_USERNAME - ARTIFACTORY_PASSWORD - ARTIFACTORY_URL + MAVEN_PUBLISH_USERNAME + MAVEN_PUBLISH_PASSWORD + MAVEN_PUBLISH_URL -The `NEXUS_PUBLISH` Environment Variables are: +`NEXUS_PUBLISH` Environment Variables are: - SONATYPE_NEXUS_URL - SONATYPE_SNAPSHOT_URL - SONATYPE_USERNAME - SONATYPE_PASSWORD - SONATYPE_STAGING_PROFILE_ID + NEXUS_PUBLISH_URL + NEXUS_PUBLISH_SNAPSHOT_URL + NEXUS_PUBLISH_USERNAME + NEXUS_PUBLISH_PASSWORD + NEXUS_PUBLISH_STAGING_PROFILE_ID grails-web --------- diff --git a/settings.gradle b/settings.gradle index 8a07d8a1..db4ebcf9 100644 --- a/settings.gradle +++ b/settings.gradle @@ -31,4 +31,4 @@ buildCache { } -rootProject.name = "grails-gradle-plugin" \ No newline at end of file +rootProject.name = 'grails-gradle-plugin' \ No newline at end of file diff --git a/src/main/groovy/org/grails/gradle/plugin/profiles/GrailsProfilePublishGradlePlugin.groovy b/src/main/groovy/org/grails/gradle/plugin/profiles/GrailsProfilePublishGradlePlugin.groovy index 04d55f15..63ef4729 100644 --- a/src/main/groovy/org/grails/gradle/plugin/profiles/GrailsProfilePublishGradlePlugin.groovy +++ b/src/main/groovy/org/grails/gradle/plugin/profiles/GrailsProfilePublishGradlePlugin.groovy @@ -23,6 +23,7 @@ import org.gradle.api.XmlProvider import org.gradle.api.artifacts.Dependency import org.gradle.api.artifacts.DependencySet import org.gradle.api.artifacts.SelfResolvingDependency +import org.gradle.api.publish.maven.MavenPom import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.tasks.bundling.Jar import org.grails.gradle.plugin.publishing.GrailsPublishGradlePlugin @@ -43,13 +44,13 @@ class GrailsProfilePublishGradlePlugin extends GrailsPublishGradlePlugin { @Override void apply(Project project) { super.apply(project) - final File tempReadmeForJavadoc = Files.createTempFile("README", "txt").toFile() - tempReadmeForJavadoc << "https://central.sonatype.org/publish/requirements/#supply-javadoc-and-sources" - project.tasks.create("javadocJar", Jar, { Jar jar -> + final File tempReadmeForJavadoc = Files.createTempFile('README', 'txt').toFile() + tempReadmeForJavadoc << 'https://central.sonatype.org/publish/requirements/#supply-javadoc-and-sources' + project.tasks.create('javadocJar', Jar, { Jar jar -> jar.from(tempReadmeForJavadoc) - jar.archiveClassifier.set("javadoc") - jar.destinationDirectory.set(new File(project.layout.buildDirectory.getAsFile().get(), "libs")) - jar.setDescription("Assembles a jar archive containing the profile javadoc.") + jar.archiveClassifier.set('javadoc') + jar.destinationDirectory.set(new File(project.layout.buildDirectory.getAsFile().get(), 'libs')) + jar.setDescription('Assembles a jar archive containing the profile javadoc.') jar.setGroup(BUILD_GROUP) }) } @@ -68,10 +69,10 @@ class GrailsProfilePublishGradlePlugin extends GrailsPublishGradlePlugin { @Override protected void doAddArtefact(Project project, MavenPublication publication) { - publication.artifact(project.tasks.findByName("jar")) - publication.pom(new Action() { + publication.artifact(project.tasks.findByName('jar')) + publication.pom(new Action() { @Override - void execute(org.gradle.api.publish.maven.MavenPom mavenPom) { + void execute(MavenPom mavenPom) { mavenPom.withXml(new Action() { @Override void execute(XmlProvider xml) { diff --git a/src/main/groovy/org/grails/gradle/plugin/publishing/GrailsPublishExtension.groovy b/src/main/groovy/org/grails/gradle/plugin/publishing/GrailsPublishExtension.groovy index 2fa7934b..9342ba99 100644 --- a/src/main/groovy/org/grails/gradle/plugin/publishing/GrailsPublishExtension.groovy +++ b/src/main/groovy/org/grails/gradle/plugin/publishing/GrailsPublishExtension.groovy @@ -21,14 +21,20 @@ import org.gradle.util.ConfigureUtil /** * @author Puneet Behl + * @author James Daugherty * @since 4.0.11 */ @CompileStatic class GrailsPublishExtension { /** - * Determines the snapshot repository to publish to + * Determines which plugin is used to publish snapshots */ - RepositoryTarget snapshotRepoType = RepositoryTarget.MAVEN_PUBLISH + PublishType snapshotPublishType = PublishType.MAVEN_PUBLISH + + /** + * Determines which plugin is used to publish releases + */ + PublishType releasePublishType = PublishType.NEXUS_PUBLISH /** * The slug from github diff --git a/src/main/groovy/org/grails/gradle/plugin/publishing/GrailsPublishGradlePlugin.groovy b/src/main/groovy/org/grails/gradle/plugin/publishing/GrailsPublishGradlePlugin.groovy index 8bca82f5..11356f90 100644 --- a/src/main/groovy/org/grails/gradle/plugin/publishing/GrailsPublishGradlePlugin.groovy +++ b/src/main/groovy/org/grails/gradle/plugin/publishing/GrailsPublishGradlePlugin.groovy @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -//file:noinspection DuplicatedCode package org.grails.gradle.plugin.publishing import grails.util.GrailsNameUtils @@ -40,6 +39,7 @@ import static com.bmuschko.gradle.nexus.NexusPlugin.getSIGNING_KEYRING * A plugin to ease publishing Grails related artifacts * * @author Graeme Rocher + * @author James Daugherty * @since 3.1 */ class GrailsPublishGradlePlugin implements Plugin { @@ -48,7 +48,7 @@ class GrailsPublishGradlePlugin implements Plugin { return """No '$missingSetting' was specified. Please provide a valid publishing configuration. Example: grailsPublish { - websiteUrl = 'http://foo.com/myplugin' + websiteUrl = 'https://example.com/myplugin' license { name = 'Apache-2.0' } @@ -71,20 +71,21 @@ grailsPublish { developers = [johndoe: 'John Doe'] } +By default snapshotPublishType is set to MAVEN_PUBLISH and releasePublishType is set to NEXUS_PUBLISH. + The credentials and connection url must be specified as a project property or an environment variable: `MAVEN_PUBLISH` Environment Variables are: - ARTIFACTORY_USERNAME - ARTIFACTORY_PASSWORD - ARTIFACTORY_URL + MAVEN_PUBLISH_USERNAME + MAVEN_PUBLISH_PASSWORD + MAVEN_PUBLISH_URL `NEXUS_PUBLISH` Environment Variables are: - SONATYPE_NEXUS_URL - SONATYPE_SNAPSHOT_URL - SONATYPE_USERNAME - SONATYPE_PASSWORD - SONATYPE_STAGING_PROFILE_ID - + NEXUS_PUBLISH_URL + NEXUS_PUBLISH_SNAPSHOT_URL + NEXUS_PUBLISH_USERNAME + NEXUS_PUBLISH_PASSWORD + NEXUS_PUBLISH_STAGING_PROFILE_ID """ } @@ -94,43 +95,50 @@ The credentials and connection url must be specified as a project property or an final TaskContainer taskContainer = project.tasks final GrailsPublishExtension gpe = extensionContainer.create('grailsPublish', GrailsPublishExtension) - final String artifactoryUsername = project.findProperty('artifactoryPublishUsername') ?: System.getenv('ARTIFACTORY_USERNAME') ?: '' - final String artifactoryPassword = project.findProperty('artifactoryPublishPassword') ?: System.getenv('ARTIFACTORY_PASSWORD') ?: '' - final String artifactoryPublishUrl = project.findProperty('artifactoryPublishUrl') ?: System.getenv('ARTIFACTORY_URL') ?: '' - final String sonatypeNexusUrl = project.findProperty('sonatypeNexusUrl') ?: System.getenv('SONATYPE_NEXUS_URL') ?: '' - final String sonatypeSnapshotUrl = project.findProperty('sonatypeSnapshotUrl') ?: System.getenv('SONATYPE_SNAPSHOT_URL') ?: '' - final String sonatypeUsername = project.findProperty('sonatypeUsername') ?: System.getenv('SONATYPE_USERNAME') ?: '' - final String sonatypePassword = project.findProperty('sonatypePassword') ?: System.getenv('SONATYPE_PASSWORD') ?: '' - final String sonatypeStagingProfileId = project.findProperty('sonatypeStagingProfileId') ?: System.getenv('SONATYPE_STAGING_PROFILE_ID') ?: '' + final String mavenPublishUsername = project.findProperty('mavenPublishUsername') ?: System.getenv('MAVEN_PUBLISH_USERNAME') ?: '' + final String mavenPublishPassword = project.findProperty('mavenPublishPassword') ?: System.getenv('MAVEN_PUBLISH_PASSWORD') ?: '' + final String mavenPublishUrl = project.findProperty('mavenPublishUrl') ?: System.getenv('MAVEN_PUBLISH_URL') ?: '' + + final String nexusPublishUrl = project.findProperty('nexusPublishUrl') ?: System.getenv('NEXUS_PUBLISH_URL') ?: '' + final String nexusPublishSnapshotUrl = project.findProperty('nexusPublishSnapshotUrl') ?: System.getenv('NEXUS_PUBLISH_SNAPSHOT_URL') ?: '' + final String nexusPublishUsername = project.findProperty('nexusPublishUsername') ?: System.getenv('NEXUS_PUBLISH_USERNAME') ?: '' + final String nexusPublishPassword = project.findProperty('nexusPublishPassword') ?: System.getenv('NEXUS_PUBLISH_PASSWORD') ?: '' + final String nexusPublishStagingProfileId = project.findProperty('nexusPublishStagingProfileId') ?: System.getenv('NEXUS_PUBLISH_STAGING_PROFILE_ID') ?: '' final ExtraPropertiesExtension extraPropertiesExtension = extensionContainer.findByType(ExtraPropertiesExtension) - extraPropertiesExtension.setProperty(SIGNING_KEY_ID, project.hasProperty(SIGNING_KEY_ID) ? project[SIGNING_KEY_ID] : System.getenv('SIGNING_KEY') ?: null) - extraPropertiesExtension.setProperty(SIGNING_PASSWORD, project.hasProperty(SIGNING_PASSWORD) ? project[SIGNING_PASSWORD] : System.getenv('SIGNING_PASSPHRASE') ?: null) - extraPropertiesExtension.setProperty(SIGNING_KEYRING, project.hasProperty(SIGNING_KEYRING) ? project[SIGNING_KEYRING] : System.getenv('SIGNING_KEYRING') ?: null) + extraPropertiesExtension.setProperty(SIGNING_KEY_ID, project.findProperty(SIGNING_KEY_ID) ?: System.getenv('SIGNING_KEY')) + extraPropertiesExtension.setProperty(SIGNING_PASSWORD, project.findProperty(SIGNING_PASSWORD) ?: System.getenv('SIGNING_PASSPHRASE')) + extraPropertiesExtension.setProperty(SIGNING_KEYRING, project.findProperty(SIGNING_KEYRING) ?: System.getenv('SIGNING_KEYRING')) project.afterEvaluate { - RepositoryTarget snapshotType = gpe.snapshotRepoType + PublishType snapshotPublishType = gpe.snapshotPublishType + PublishType releasePublishType = gpe.releasePublishType + boolean isSnapshot = project.version.endsWith('SNAPSHOT') boolean isRelease = !isSnapshot + + boolean mavenPublish = (isSnapshot && snapshotPublishType == PublishType.MAVEN_PUBLISH) || (isRelease && releasePublishType == PublishType.MAVEN_PUBLISH) + boolean sonatypePublish = (isSnapshot && snapshotPublishType == PublishType.NEXUS_PUBLISH) || (isRelease && releasePublishType == PublishType.NEXUS_PUBLISH) + final PluginManager projectPluginManager = project.getPluginManager() final PluginManager rootProjectPluginManager = project.rootProject.getPluginManager() projectPluginManager.apply(MavenPublishPlugin) project.publishing { - if (isSnapshot && snapshotType == RepositoryTarget.MAVEN_PUBLISH) { + if (mavenPublish) { System.setProperty('org.gradle.internal.publish.checksums.insecure', true as String) repositories { maven { credentials { - username = artifactoryUsername - password = artifactoryPassword + username = mavenPublishUsername + password = mavenPublishPassword } - if (!artifactoryPublishUrl) { - throw new RuntimeException('Could not locate a project property of `artifactoryPublishUrl` or an environment variable of `ARTIFACTORY_URL` for the snapshot url') + if (!mavenPublishUrl) { + throw new RuntimeException('Could not locate a project property of `mavenPublishUrl` or an environment variable of `MAVEN_PUBLISH_URL`') } - url = artifactoryPublishUrl + url = mavenPublishUrl } } } @@ -164,36 +172,32 @@ The credentials and connection url must be specified as a project property or an if (gpe != null) { pomNode.children().last() + { def title = gpe.title ?: project.name - delegate.name title - delegate.description gpe.desc ?: title + delegate.name = title + delegate.description = gpe.desc ?: title def websiteUrl = gpe.websiteUrl ?: gpe.githubSlug ? "https://github.com/$gpe.githubSlug" : '' if (!websiteUrl) { throw new RuntimeException(getErrorMessage('websiteUrl')) } - - delegate.url websiteUrl - + delegate.url = websiteUrl def license = gpe.license if (license != null) { - def concreteLicense = GrailsPublishExtension.License.LICENSES.get(license.name) if (concreteLicense != null) { - delegate.licenses { delegate.license { - delegate.name concreteLicense.name - delegate.url concreteLicense.url - delegate.distribution concreteLicense.distribution + delegate.name = concreteLicense.name + delegate.url = concreteLicense.url + delegate.distribution = concreteLicense.distribution } } } else if (license.name && license.url) { delegate.licenses { delegate.license { - delegate.name license.name - delegate.url license.url - delegate.distribution license.distribution + delegate.name = license.name + delegate.url = license.url + delegate.distribution = license.distribution } } } @@ -203,20 +207,20 @@ The credentials and connection url must be specified as a project property or an if (gpe.githubSlug) { delegate.scm { - delegate.url "https://github.com/$gpe.githubSlug" - delegate.connection "scm:git@github.com:${gpe.githubSlug}.git" - delegate.developerConnection "scm:git@github.com:${gpe.githubSlug}.git" + delegate.url = "https://github.com/$gpe.githubSlug" + delegate.connection = "scm:git@github.com:${gpe.githubSlug}.git" + delegate.developerConnection = "scm:git@github.com:${gpe.githubSlug}.git" } delegate.issueManagement { - delegate.system "Github Issues" - delegate.url "https://github.com/$gpe.githubSlug/issues" + delegate.system = 'Github Issues' + delegate.url = "https://github.com/$gpe.githubSlug/issues" } } else { if (gpe.vcsUrl) { delegate.scm { - delegate.url gpe.vcsUrl - delegate.connection "scm:$gpe.vcsUrl" - delegate.developerConnection "scm:$gpe.vcsUrl" + delegate.url = gpe.vcsUrl + delegate.connection = "scm:$gpe.vcsUrl" + delegate.developerConnection = "scm:$gpe.vcsUrl" } } else { throw new RuntimeException(getErrorMessage('vcsUrl')) @@ -224,21 +228,20 @@ The credentials and connection url must be specified as a project property or an if (gpe.issueTrackerUrl) { delegate.issueManagement { - delegate.system "Issue Tracker" - delegate.url gpe.issueTrackerUrl + delegate.system = 'Issue Tracker' + delegate.url = gpe.issueTrackerUrl } } else { throw new RuntimeException(getErrorMessage('issueTrackerUrl')) } - } if (gpe.developers) { delegate.developers { for (entry in gpe.developers.entrySet()) { delegate.developer { - delegate.id entry.key - delegate.name entry.value + delegate.id = entry.key + delegate.name = entry.value } } } @@ -263,7 +266,7 @@ The credentials and connection url must be specified as a project property or an } } - if (isRelease || (isSnapshot && snapshotType == RepositoryTarget.NEXUS_PUBLISH)) { + if (sonatypePublish) { rootProjectPluginManager.apply(NexusPublishPlugin) projectPluginManager.apply(SigningPlugin) @@ -283,34 +286,34 @@ The credentials and connection url must be specified as a project property or an project.rootProject.nexusPublishing { repositories { sonatype { - if (sonatypeNexusUrl) { - nexusUrl = project.uri(sonatypeNexusUrl) + if (nexusPublishUrl) { + nexusUrl = project.uri(nexusPublishUrl) } - if (sonatypeSnapshotUrl) { - snapshotRepositoryUrl = project.uri(sonatypeSnapshotUrl) + if (nexusPublishSnapshotUrl) { + snapshotRepositoryUrl = project.uri(nexusPublishSnapshotUrl) } - username = sonatypeUsername - password = sonatypePassword - stagingProfileId = sonatypeStagingProfileId + username = nexusPublishUsername + password = nexusPublishPassword + stagingProfileId = nexusPublishStagingProfileId } } } } - def installTask = taskContainer.findByName("install") + def installTask = taskContainer.findByName('install') def publishToSonatypeTask = taskContainer.findByName('publishToSonatype') def closeAndReleaseSonatypeStagingRepositoryTask = taskContainer.findByName('closeAndReleaseSonatypeStagingRepository') - def publishToMavenLocal = taskContainer.findByName("publishToMavenLocal") + def publishToMavenLocal = taskContainer.findByName('publishToMavenLocal') if (publishToSonatypeTask != null && taskContainer.findByName("publish${GrailsNameUtils.getClassName(defaultClassifier)}") == null) { taskContainer.register("publish${GrailsNameUtils.getClassName(defaultClassifier)}", { Task task -> task.dependsOn([publishToSonatypeTask, closeAndReleaseSonatypeStagingRepositoryTask]) - task.setGroup("publishing") + task.setGroup('publishing') }) } if (installTask == null) { - taskContainer.register("install", { Task task -> + taskContainer.register('install', { Task task -> task.dependsOn(publishToMavenLocal) - task.setGroup("publishing") + task.setGroup('publishing') }) } } @@ -330,7 +333,7 @@ The credentials and connection url must be specified as a project property or an } protected String getDefaultClassifier() { - "plugin" + 'plugin' } } diff --git a/src/main/groovy/org/grails/gradle/plugin/publishing/RepositoryTarget.groovy b/src/main/groovy/org/grails/gradle/plugin/publishing/PublishType.groovy similarity index 77% rename from src/main/groovy/org/grails/gradle/plugin/publishing/RepositoryTarget.groovy rename to src/main/groovy/org/grails/gradle/plugin/publishing/PublishType.groovy index 0dd468f1..bda1491e 100644 --- a/src/main/groovy/org/grails/gradle/plugin/publishing/RepositoryTarget.groovy +++ b/src/main/groovy/org/grails/gradle/plugin/publishing/PublishType.groovy @@ -1,6 +1,6 @@ package org.grails.gradle.plugin.publishing -enum RepositoryTarget { +enum PublishType { MAVEN_PUBLISH, NEXUS_PUBLISH }