├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradle ├── licenseHeader.txt └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── integTest ├── README.md ├── groovy │ └── io │ │ └── spring │ │ └── gradle │ │ └── bintray │ │ └── SpringBintrayPluginIntegSpec.groovy └── resources │ └── .gitignore ├── main ├── kotlin │ └── io │ │ └── spring │ │ └── gradle │ │ └── bintray │ │ ├── BintrayClient.kt │ │ ├── BintrayPackage.kt │ │ ├── SpringBintrayExtension.kt │ │ ├── SpringBintrayPlugin.kt │ │ └── task │ │ ├── AbstractBintrayTask.kt │ │ ├── CreatePackageTask.kt │ │ ├── CreateVersionTask.kt │ │ ├── MavenCentralSyncTask.kt │ │ ├── PublishTask.kt │ │ ├── SignTask.kt │ │ └── UploadTask.kt └── resources │ └── META-INF │ └── gradle-plugins │ └── io.spring.bintray.properties └── test ├── kotlin └── io │ └── spring │ └── gradle │ └── bintray │ ├── BintrayApiMatchers.kt │ └── task │ ├── AbstractBintrayTaskSetup.kt │ ├── AbstractBintrayTaskTest.kt │ ├── CreatePackageTaskTest.kt │ ├── CreateVersionTaskTest.kt │ └── MavenCentralSyncTaskTest.kt └── resources └── bintray.properties /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .gradle/ 3 | gradle.properties -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # spring-bintray-plugin is no longer actively maintained by VMware, Inc. 2 | 3 | # Spring Bintray Plugin 4 | 5 | ## Installing 6 | 7 | Follow the instructions on the Gradle [Plugin Portal](https://plugins.gradle.org/plugin/io.spring.bintray). 8 | 9 | ## Purpose 10 | 11 | This plugin is a modernization of [gradle-bintray-plugin](https://github.com/bintray/gradle-bintray-plugin) which provides more control over the individual stages of execution from creating a package all the way through Maven Central sync. Bintray's plugin places all of this logic in a single task `bintrayUpload` which is executed once on the root project for all subprojects. In the event of partial success, this can leave you high and dry manually exercising REST calls against the Bintray API to finish a release. 12 | 13 | Furthermore, the single-task per project model makes it difficult to configure publication on some projects and not others. Also, it does not allow for project-level decisions like NOT syncing an experimental module to Maven Central. 14 | 15 | ## A task for every stage 16 | 17 | These tasks are executed on a per-project basis rather than at the root project. Each task in this list `dependsOn` the prior task, so it is sufficient to call `mavenCentralSync` to perform the entire sequence. Or if you just want to get through the upload phase and publish it from the Bintray UI, call `bintrayUpload`. 18 | 19 | 1. `bintrayCreatePackage` - Creates a new package only if it doesn't already exist 20 | 2. `bintrayCreateVersion` - Creates a new package version only if it doesn't already exist 21 | 3. `bintrayUpload` - Uploads artifacts in parallel (only those that don't already exist unless `bintray.overrideOnUpload` is `true`) 22 | 4. `bintraySign` - Sign all artifacts in a version. This task is not generally necessary, as the plugin attempts to sign artifacts on upload. If signing fails for some reason on upload, you can invoke this later manually (such as after updating `bintray.gpgPassphrase` that you had wrong initially). 23 | 5. `bintrayPublish` - "Publishes" the artifacts in Bintray, effectively making them visible to more than just the original account that uploaded them (generally the public at large). 24 | 6. `mavenCentralSync` - Syncs artifacts to Maven Central and closes the corresponding OSSRH repo. 25 | 26 | In the event of partial failure in Bintray, you can simply rerun for a single project to kickstart the process again, e.g. `./gradlew :mysubproject:bintrayPublish`. Since each stage is smart enough to check whether it has already been done, you can comfortably start anywhere in the process and know that it will pick up right after the last successful stage. 27 | 28 | ## Configuration 29 | 30 | Configuration is simpler than `gradle-bintray-plugin`. 31 | 32 | Here are the required properties: 33 | 34 | ```groovy 35 | bintray { 36 | // The following properties are REQUIRED: 37 | bintrayUser = //... 38 | bintrayKey = //... 39 | repo = 'jars' 40 | publication = 'nebula' // the named Gradle MavenPublication identifying the artifacts to publish 41 | } 42 | ``` 43 | 44 | Everything else is optional, with sensible defaults: 45 | 46 | ```groovy 47 | bintray { 48 | org = 'spring' // uses bintrayUser if you aren't publishing to an organization repository 49 | labels = ['label1'] 50 | licenses = ['Apache-2.0'] 51 | ossrhUser = // only if syncing to Maven Central 52 | ossrhPassword = //... 53 | gpgPassphrase = // if your repository requires signing with a other-than-Bintray key 54 | overrideOnUpload = false // should the upload task override existing artifacts? 55 | 56 | // The following are derived from the `origin` github remote if not explicitly provided: 57 | websiteUrl = 'https://github.com/spring-gradle-plugins/spring-bintray-plugin' 58 | issueTrackerUrl = 'https://github.com/spring-gradle-plugins/spring-bintray-plugin/issues' 59 | vcsUrl = 'https://github.com/spring-gradle-plugins/spring-bintray-plugin.git' 60 | } 61 | ``` 62 | 63 | ## Gating your release 64 | 65 | You may wish to gate publishing of _any subproject_ with some other gradle task on _all projects_. For example, ensuring that all projects in multi-module project test successfully before attempting to publish _any_ project: 66 | 67 | ```groovy 68 | // in each subproject that applies the bintray plugin 69 | project.rootProject.subprojects.each { p -> 70 | def check = p.tasks.findByName('check') 71 | if(check) { 72 | tasks.bintrayUpload.dependsOn(check) 73 | } 74 | } 75 | ``` 76 | 77 | ## Benefits over `gradle-bintray-plugin` 78 | 79 | * Splits Bintray interactions into separate tasks so you can more easily control which projects do what and target particular tasks in the event of Bintray partial failure. 80 | * Logs warnings contained in the response body of uploads (`gradle-bintray-plugin` suppresses these warnings). 81 | * Uses the Gradle Worker API to parallelize uploads. 82 | * Having `mavenCentralSync` as a separate task allows you to perform validation of your release (if you choose) in a public repository (JCenter) that still allows you to delete artifacts. Maven Central does not allow this generally. 83 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | } 5 | 6 | dependencies { 7 | classpath 'gradle.plugin.nl.javadude.gradle.plugins:license-gradle-plugin:0.13.1' 8 | classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0' 9 | } 10 | } 11 | 12 | plugins { 13 | id 'nebula.kotlin' version '1.2.41' 14 | id 'nebula.plugin-plugin' version '7.1.6' 15 | } 16 | 17 | apply plugin: 'com.github.hierynomus.license' 18 | apply plugin: 'org.junit.platform.gradle.plugin' 19 | 20 | repositories { 21 | jcenter() 22 | } 23 | 24 | group = 'io.spring.gradle' 25 | description = 'Publish artifacts to bintray' 26 | 27 | contacts { 28 | 'jkschneider@gmail.com' { 29 | moniker 'Jon Schneider' 30 | github 'jkschneider' 31 | } 32 | } 33 | 34 | dependencies { 35 | compile "org.jetbrains.kotlin:kotlin-reflect" 36 | compile 'org.eclipse.jgit:org.eclipse.jgit:latest.release' 37 | 38 | // shade these 39 | compile 'com.squareup.okhttp3:okhttp:3.8.1' 40 | compile 'com.fasterxml.jackson.module:jackson-module-kotlin:2.+' 41 | 42 | testCompile 'com.netflix.nebula:nebula-test:latest.release' 43 | 44 | // JUnit 5 45 | testCompile 'org.junit.jupiter:junit-jupiter-api:5.0.0' 46 | testCompile 'org.junit.jupiter:junit-jupiter-params:5.0.0' 47 | testRuntime 'org.junit.jupiter:junit-jupiter-engine:5.0.0' 48 | 49 | testCompile 'org.assertj:assertj-core:3.+' 50 | testCompile 'com.nhaarman:mockito-kotlin:latest.release' 51 | } 52 | 53 | license { 54 | header = file('gradle/licenseHeader.txt') 55 | exclude '**/*.tokens' 56 | mapping { 57 | kt = 'JAVADOC_STYLE' 58 | } 59 | sourceSets = project.sourceSets 60 | strictCheck = true 61 | } 62 | 63 | pluginBundle { 64 | website = 'https://github.com/spring-gradle-plugins/spring-bintray-plugin' 65 | vcsUrl = 'https://github.com/spring-gradle-plugins/spring-bintray-plugin.git' 66 | description = project.description 67 | 68 | plugins { 69 | springBintrayPlugin { 70 | id = 'io.spring.bintray' 71 | displayName = 'Spring bintray plugin' 72 | description = project.description 73 | tags = ['spring', 'bintray'] 74 | } 75 | } 76 | 77 | mavenCoordinates { 78 | groupId = 'io.spring.gradle' 79 | artifactId = 'spring-bintray-plugin' 80 | } 81 | } 82 | 83 | bintray.pkg { 84 | repo = 'jars' 85 | userOrg = 'spring' 86 | websiteUrl = 'https://github.com/spring-gradle-plugins/spring-bintray-plugin' 87 | vcsUrl = 'https://github.com/spring-gradle-plugins/spring-bintray-plugin.git' 88 | issueTrackerUrl = 'https://github.com/spring-gradle-plugins/spring-bintray-plugin/issues' 89 | labels = ['gradle', 'spring', 'bintray'] 90 | gpgPassphrase = project.findProperty('gpgPassphrase') 91 | } -------------------------------------------------------------------------------- /gradle/licenseHeader.txt: -------------------------------------------------------------------------------- 1 | Copyright 2017-2018 Pivotal Software, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spring-attic/spring-bintray-plugin/2f9900f2f957707d0c4b6cbbabbf40b9261bc84b/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'spring-bintray-plugin' -------------------------------------------------------------------------------- /src/integTest/README.md: -------------------------------------------------------------------------------- 1 | You must provide a `resources/bintray.properties` file with: 2 | 3 | ``` 4 | bintrayUser=USER 5 | bintrayKey=KEY 6 | ``` -------------------------------------------------------------------------------- /src/integTest/groovy/io/spring/gradle/bintray/SpringBintrayPluginIntegSpec.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray 17 | 18 | import nebula.test.IntegrationSpec 19 | 20 | class SpringBintrayPluginIntegSpec extends IntegrationSpec { 21 | def 'publish a multi-module project to JCenter'() { 22 | when: 23 | def propsInput = getClass().getResourceAsStream('/bintray.properties') 24 | 25 | def props = new Properties() 26 | if(propsInput) 27 | props.load(propsInput) 28 | 29 | buildFile << """\ 30 | allprojects { 31 | group = 'io.spring.gradle.bintray.test' 32 | version = '${new Date().format('yyyyMMdd.HH.mm.ss')}' 33 | } 34 | 35 | subprojects { 36 | apply plugin: 'java' 37 | apply plugin: 'maven-publish' 38 | ${applyPlugin(SpringBintrayPlugin)} 39 | 40 | bintray { 41 | repo = 'jars' 42 | org = 'spring' 43 | 44 | bintrayUser = '${props.getProperty('bintrayUser')}' 45 | bintrayKey = '${props.getProperty('bintrayKey')}' 46 | 47 | gpgPassphrase = '${props.getProperty('gpgPassphrase')}' 48 | 49 | publication = 'mavenJava' 50 | 51 | websiteUrl = "https://github.com/spring-gradle-plugins/spring-bintray-plugin" 52 | vcsUrl = "https://github.com/spring-gradle-plugins/spring-bintray-plugin.git" 53 | issueTrackerUrl = "https://github.com/spring-gradle-plugins/spring-bintray-plugin/issues" 54 | 55 | licenses = ['Apache-2.0'] 56 | } 57 | 58 | publishing { 59 | publications { 60 | mavenJava(MavenPublication) { 61 | from components.java 62 | } 63 | } 64 | } 65 | } 66 | """.stripMargin() 67 | 68 | def core = addSubproject('spring-bintray-plugin-integtest-core') 69 | def a = new File(core, 'src/main/java/io/spring/bintray/test/A.java') 70 | a.getParentFile().mkdirs() 71 | a << '''\ 72 | package io.spring.bintray.test; 73 | public class A {} 74 | '''.stripMargin() 75 | 76 | addSubproject('spring-bintray-plugin-integtest-test') 77 | 78 | def atest = new File(core, 'src/main/java/io/spring/bintray/test/ATest.java') 79 | atest.getParentFile().mkdirs() 80 | atest << '''\ 81 | package io.spring.bintray.test; 82 | public class ATest {} 83 | '''.stripMargin() 84 | 85 | then: 86 | 87 | if(propsInput) { 88 | def result = runTasksSuccessfully('bintrayPublish') 89 | println(result.standardOutput) 90 | } 91 | else { 92 | println("Skipping integration test. Provide a bintray.properties in integTest/resources that includes bintrayUser, bintrayKey, and gpgPassphrase to run.") 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/integTest/resources/.gitignore: -------------------------------------------------------------------------------- 1 | bintray.properties -------------------------------------------------------------------------------- /src/main/kotlin/io/spring/gradle/bintray/BintrayClient.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray 17 | 18 | import com.fasterxml.jackson.databind.ObjectMapper 19 | import com.fasterxml.jackson.module.kotlin.KotlinModule 20 | import okhttp3.Credentials 21 | import okhttp3.Interceptor 22 | import okhttp3.MediaType 23 | import okhttp3.OkHttpClient 24 | import okhttp3.Request 25 | import okhttp3.RequestBody 26 | import okhttp3.Response 27 | import java.io.File 28 | import java.util.concurrent.TimeUnit 29 | 30 | class BintrayClient(val bintrayUser: String?, val bintrayKey: String?) { 31 | companion object { 32 | const val BINTRAY_API_URL = "https://api.bintray.com" 33 | } 34 | 35 | private val mapper: ObjectMapper = ObjectMapper().registerModule(KotlinModule()) 36 | 37 | /** 38 | * Useful for testing 39 | */ 40 | var interceptors = emptyList() 41 | 42 | private fun httpClient(): OkHttpClient { 43 | var builder = OkHttpClient.Builder() 44 | .connectTimeout(30, TimeUnit.SECONDS) 45 | .readTimeout(3, TimeUnit.MINUTES) 46 | .writeTimeout(6, TimeUnit.MINUTES) 47 | 48 | interceptors.forEach { builder = builder.addInterceptor(it) } 49 | 50 | return builder 51 | .authenticator({ _, response -> 52 | if (bintrayUser != null && bintrayKey != null) { 53 | val credential = Credentials.basic(bintrayUser, bintrayKey) 54 | response.request().newBuilder() 55 | .header("Authorization", credential) 56 | .build() 57 | } else response.request().newBuilder().build() 58 | }) 59 | .build() 60 | } 61 | 62 | fun head(path: String): Response = httpClient() 63 | .newCall(Request.Builder().head().url("$BINTRAY_API_URL/$path").build()) 64 | .execute() 65 | 66 | fun get(path: String): Response = httpClient() 67 | .newCall(Request.Builder().get().url("$BINTRAY_API_URL/$path").build()) 68 | .execute() 69 | 70 | fun headIsSuccessful(path: String): Boolean = head(path).use { response -> response.isSuccessful } 71 | 72 | fun post(path: String, body: Any): Response { 73 | val bodyStr = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), 74 | mapper.writeValueAsString(body)) 75 | 76 | val request = Request.Builder() 77 | .url("$BINTRAY_API_URL/$path") 78 | .post(bodyStr) 79 | .build() 80 | 81 | return httpClient().newCall(request).execute() 82 | } 83 | 84 | fun upload(path: String, artifact: File, gpgPassphrase: String?): Response { 85 | var requestBuilder = Request.Builder() 86 | .header("Content-Type", "*/*") 87 | 88 | if (!gpgPassphrase.isNullOrBlank()) { 89 | requestBuilder = requestBuilder.header("X-GPG-PASSPHRASE", gpgPassphrase!!) 90 | } 91 | 92 | val request = requestBuilder 93 | .put(RequestBody.create(MediaType.parse("application/octet-stream"), artifact)) 94 | .url("$BINTRAY_API_URL/$path") 95 | .build() 96 | 97 | return httpClient().newCall(request).execute() 98 | } 99 | } -------------------------------------------------------------------------------- /src/main/kotlin/io/spring/gradle/bintray/BintrayPackage.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray 17 | 18 | import java.io.Serializable 19 | 20 | /** 21 | * Answers the "where in bintray are these artifacts going" question 22 | * 23 | * In this context "subject" could be an organization name or a Bintray user. 24 | * 25 | * @author Jon Schneider 26 | */ 27 | data class BintrayPackage(val subject: String, val repo: String, val name: String): Serializable -------------------------------------------------------------------------------- /src/main/kotlin/io/spring/gradle/bintray/SpringBintrayExtension.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray 17 | 18 | import org.gradle.api.Project 19 | 20 | open class SpringBintrayExtension { 21 | // package info 22 | var org: String? = null 23 | var repo: String? = null 24 | var packageName: String? = null 25 | var packageDescription: String? = null 26 | var labels: Collection = emptyList() 27 | var licenses: Collection? = null 28 | 29 | // optional since: derived from the "origin" github remote or the first github remote, if any 30 | var websiteUrl: String? = null 31 | var issueTrackerUrl: String? = null 32 | var vcsUrl: String? = null 33 | 34 | // every put/post request to bintray must be authenticated 35 | var bintrayUser: String? = null 36 | var bintrayKey: String? = null 37 | 38 | // required for syncing to Maven Central 39 | var ossrhUser: String? = null 40 | var ossrhPassword: String? = null 41 | 42 | var publication: String? = null 43 | 44 | var gpgPassphrase: String? = null 45 | 46 | var overrideOnUpload: Boolean = false 47 | 48 | fun bintrayPackage(p: Project): BintrayPackage = 49 | BintrayPackage(org!!, repo!!, packageName ?: p.name) 50 | 51 | fun bintrayUser(p: Project): String? = bintrayUser ?: p.findProperty("bintrayUser") as String? 52 | 53 | fun bintrayKey(p: Project): String? = bintrayKey ?: p.findProperty("bintrayKey") as String? 54 | 55 | override fun toString(): String { 56 | return "bintray(org=$org, repo=$repo, packageName=$packageName, packageDescription=$packageDescription, labels=$labels, licenses=$licenses, websiteUrl=$websiteUrl, issueTrackerUrl=$issueTrackerUrl, vcsUrl=$vcsUrl, bintrayUser=$bintrayUser, bintrayKey=$bintrayKey, ossrhUser=$ossrhUser, ossrhPassword=$ossrhPassword, publication=$publication, gpgPassphrase=$gpgPassphrase, overrideOnUpload=$overrideOnUpload)" 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/kotlin/io/spring/gradle/bintray/SpringBintrayPlugin.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray 17 | 18 | import io.spring.gradle.bintray.task.CreatePackageTask 19 | import io.spring.gradle.bintray.task.CreateVersionTask 20 | import io.spring.gradle.bintray.task.MavenCentralSyncTask 21 | import io.spring.gradle.bintray.task.PublishTask 22 | import io.spring.gradle.bintray.task.SignTask 23 | import io.spring.gradle.bintray.task.UploadTask 24 | import org.gradle.api.Plugin 25 | import org.gradle.api.Project 26 | import org.gradle.api.publish.PublishingExtension 27 | import org.gradle.api.publish.maven.MavenPublication 28 | import org.slf4j.LoggerFactory 29 | 30 | /** 31 | * @author Jon Schneider 32 | */ 33 | class SpringBintrayPlugin : Plugin { 34 | lateinit var ext: SpringBintrayExtension 35 | private val logger = LoggerFactory.getLogger(SpringBintrayPlugin::class.java) 36 | 37 | override fun apply(project: Project) { 38 | ext = project.extensions.create("bintray", SpringBintrayExtension::class.java) 39 | 40 | val createPackageTask = project.tasks.create("bintrayCreatePackage", CreatePackageTask::class.java) 41 | 42 | val createVersionTask = project.tasks.create("bintrayCreateVersion", CreateVersionTask::class.java) 43 | createVersionTask.dependsOn(createPackageTask) 44 | 45 | val uploadTask = project.tasks.create("bintrayUpload", UploadTask::class.java) 46 | uploadTask.dependsOn(createVersionTask) 47 | 48 | // We try to sign on upload, so this task won't be part of the default chain of events. 49 | // It's here in case you need to sign manually after uploading for whatever reason. 50 | val signTask = project.tasks.create("bintraySign", SignTask::class.java) 51 | signTask.dependsOn(uploadTask) 52 | 53 | val publishTask = project.tasks.create("bintrayPublish", PublishTask::class.java) 54 | publishTask.dependsOn(uploadTask) 55 | 56 | val mavenCentralSyncTask = project.tasks.create("mavenCentralSync", MavenCentralSyncTask::class.java) 57 | mavenCentralSyncTask.dependsOn(publishTask) 58 | 59 | project.afterEvaluate { 60 | project.tasks.withType(CreateVersionTask::class.java) { t -> 61 | println() 62 | if(ext.publication != null) { 63 | val publication = project.extensions.getByType(PublishingExtension::class.java).publications.findByName(ext.publication) 64 | if (publication is MavenPublication) { 65 | publication.artifacts.forEach { artifact -> 66 | t.dependsOn(artifact.buildDependencies) 67 | } 68 | } 69 | } 70 | } 71 | 72 | project.tasks.withType(UploadTask::class.java) { t -> 73 | if(ext.publication != null) { 74 | val publication = project.extensions.getByType(PublishingExtension::class.java).publications.findByName(ext.publication) 75 | if (publication is MavenPublication) { 76 | t.dependsOn("generatePomFileFor${publication.name.capitalize()}Publication") 77 | } 78 | } 79 | } 80 | 81 | if (ext.bintrayUser(project) == null || ext.bintrayKey(project) == null || ext.repo == null || ext.publication == null || ext.licenses == null) { 82 | listOf(createPackageTask, createVersionTask, uploadTask, signTask, publishTask, mavenCentralSyncTask).forEach { 83 | it.onlyIf { 84 | project.logger.warn("bintray.[bintrayUser, bintrayKey, repo, publication, licenses] are all required for Bintray publishing") 85 | false 86 | } 87 | } 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/main/kotlin/io/spring/gradle/bintray/task/AbstractBintrayTask.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray.task 17 | 18 | import io.spring.gradle.bintray.BintrayClient 19 | import io.spring.gradle.bintray.BintrayPackage 20 | import io.spring.gradle.bintray.SpringBintrayExtension 21 | import org.gradle.api.DefaultTask 22 | import org.gradle.api.publish.Publication 23 | import org.gradle.api.publish.PublishingExtension 24 | import org.gradle.api.publish.maven.MavenPublication 25 | 26 | abstract class AbstractBintrayTask : DefaultTask() { 27 | init { 28 | onlyIf { 29 | if(bintrayUser() == null) 30 | logger.warn("No bintray.bintrayUser defined. Skipping.") 31 | if(bintrayKey() == null) 32 | logger.warn("No bintray.bintrayKey defined. Skipping.") 33 | bintrayUser() != null && bintrayKey() != null 34 | } 35 | } 36 | 37 | protected val ext: SpringBintrayExtension by lazy { project.extensions.getByType(SpringBintrayExtension::class.java) } 38 | protected val pkg: BintrayPackage by lazy { ext.bintrayPackage(project) } 39 | 40 | val bintrayClient: BintrayClient by lazy { BintrayClient(bintrayUser(), bintrayKey()) } 41 | 42 | val publication: Publication? by lazy { 43 | val pubName = ext.publication 44 | if(pubName is String) { 45 | project.extensions 46 | .findByType(PublishingExtension::class.java) 47 | ?.publications 48 | ?.findByName(pubName) 49 | } else null 50 | } 51 | 52 | val version: String by lazy { 53 | val pub = publication 54 | if (pub is MavenPublication && pub.version is String) { 55 | pub.version 56 | } else project.version.toString() 57 | } 58 | 59 | val packagePath: String by lazy { pkg.run { "packages/$subject/$repo/$name" } } 60 | val versionPath: String by lazy { pkg.run { "packages/$subject/$repo/$name/versions/$version" } } 61 | 62 | fun bintrayUser() = ext.bintrayUser(project) 63 | fun bintrayKey() = ext.bintrayKey(project) 64 | 65 | override fun getGroup(): String { 66 | return "bintray" 67 | } 68 | } -------------------------------------------------------------------------------- /src/main/kotlin/io/spring/gradle/bintray/task/CreatePackageTask.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray.task 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude 19 | import com.fasterxml.jackson.databind.PropertyNamingStrategy 20 | import com.fasterxml.jackson.databind.annotation.JsonNaming 21 | import org.eclipse.jgit.api.Git 22 | import org.gradle.api.GradleException 23 | import org.gradle.api.tasks.TaskAction 24 | import java.io.IOException 25 | 26 | /** 27 | * Creates a bintray package. Up-to-date when the package already exists. 28 | * 29 | * @author Jon Schneider 30 | */ 31 | open class CreatePackageTask : AbstractBintrayTask() { 32 | 33 | init { 34 | onlyIf { !bintrayClient.headIsSuccessful(packagePath) } 35 | } 36 | 37 | @TaskAction 38 | fun createPackage() { 39 | val githubRemote = findGithubRemote() 40 | 41 | val createPackage = CreatePackage( 42 | pkg.name, 43 | ext.packageDescription, 44 | ext.licenses ?: emptyList(), 45 | ext.labels, 46 | ext.websiteUrl ?: githubRemote, 47 | ext.issueTrackerUrl ?: githubRemote?.plus("/issues") ?: "", 48 | ext.vcsUrl ?: githubRemote?.plus(".git") ?: "", 49 | true) 50 | 51 | bintrayClient.post("packages/${pkg.subject}/${pkg.repo}", createPackage).use { response -> 52 | if (response.isSuccessful) { 53 | logger.info("Created Bintray package /$packagePath") 54 | } else if (response.code() == 409) { 55 | logger.info("Bintray package already exists /$packagePath") 56 | } else { 57 | throw GradleException("Could not create package /$packagePath: HTTP ${response.code()} / ${response.body()?.string()}") 58 | } 59 | } 60 | } 61 | 62 | private fun findGithubRemote(): String? { 63 | try { 64 | Git.open(project.projectDir).use { git -> 65 | val config = git.repository.config 66 | 67 | // Remote URLs will be formatted like one of these: 68 | // https://github.com/spring-gradle-plugins/spring-project-plugin.git 69 | // git@github.com:spring-gradle-plugins/spring-release-plugin.git 70 | val repoParts = config.getSubsections("remote") 71 | .map { remoteName -> Remote(remoteName, config.getString("remote", remoteName, "url")) } 72 | .sortedWith(Comparator { r1, r2 -> 73 | if (r1.name == "origin") -1 74 | else if (r2.name == "origin") 1 75 | else r1.name.compareTo(r2.name) 76 | }) 77 | .map { """github\.com[/:]([^/]+)/(.+)\.git""".toRegex().find(it.url) } 78 | .filterNotNull() 79 | .firstOrNull() 80 | ?: return null // no remote configured yet, do nothing 81 | 82 | val groups = repoParts.groupValues 83 | return "https://github.com/${groups[1]}/${groups[2]}" 84 | } 85 | } catch (ignored: IOException) { 86 | // do nothing 87 | return null 88 | } 89 | } 90 | } 91 | 92 | data class Remote(val name: String, val url: String) 93 | 94 | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy::class) 95 | @JsonInclude(JsonInclude.Include.NON_NULL) 96 | data class CreatePackage(val name: String, 97 | val desc: String?, 98 | val licenses: Collection, 99 | val labels: Collection, 100 | val websiteUrl: String?, 101 | val issueTrackerUrl: String?, 102 | val vcsUrl: String, 103 | val publicDownloadNumbers: Boolean) -------------------------------------------------------------------------------- /src/main/kotlin/io/spring/gradle/bintray/task/CreateVersionTask.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray.task 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude 19 | import com.fasterxml.jackson.databind.PropertyNamingStrategy 20 | import com.fasterxml.jackson.databind.annotation.JsonNaming 21 | import org.gradle.api.GradleException 22 | import org.gradle.api.tasks.TaskAction 23 | 24 | /** 25 | * Create a package version. Up-to-date when the version already exists. 26 | * 27 | * @author Jon Schneider 28 | */ 29 | open class CreateVersionTask : AbstractBintrayTask() { 30 | init { 31 | onlyIf { !bintrayClient.headIsSuccessful(versionPath) } 32 | } 33 | 34 | @TaskAction 35 | fun createVersion() { 36 | val createVersion = CreateVersion(version, "v$version") 37 | 38 | bintrayClient.post("packages/${pkg.subject}/${pkg.repo}/${pkg.name}/versions", createVersion).use { response -> 39 | when { 40 | response.isSuccessful -> logger.info("Created Bintray version $versionPath") 41 | response.code() == 409 -> logger.info("Bintray version already exists $versionPath") 42 | else -> throw GradleException("Could not create version $versionPath: HTTP ${response.code()} / ${response.body()?.string()}") 43 | } 44 | } 45 | } 46 | } 47 | 48 | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy::class) 49 | @JsonInclude(JsonInclude.Include.NON_NULL) 50 | data class CreateVersion(val name: String, val vcsTag: String) -------------------------------------------------------------------------------- /src/main/kotlin/io/spring/gradle/bintray/task/MavenCentralSyncTask.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray.task 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude 19 | import com.fasterxml.jackson.databind.PropertyNamingStrategy 20 | import com.fasterxml.jackson.databind.annotation.JsonNaming 21 | import okhttp3.OkHttpClient 22 | import okhttp3.Request 23 | import org.gradle.api.GradleException 24 | import org.gradle.api.publish.maven.MavenPublication 25 | import org.gradle.api.tasks.TaskAction 26 | 27 | /** 28 | * Sync a published package version to Maven Central 29 | * 30 | * @author Jon Schneider 31 | */ 32 | open class MavenCentralSyncTask : AbstractBintrayTask() { 33 | init { 34 | onlyIf { 35 | // version must exist in Bintray prior to syncing 36 | bintrayClient.headIsSuccessful(versionPath) 37 | } 38 | 39 | onlyIf { 40 | when (publication) { 41 | is MavenPublication -> !MavenCentral.exists(publication as MavenPublication) 42 | else -> { 43 | // can't make a determination, but we don't want to proceed with a sync anyway 44 | logger.warn("Not attempting to sync ${project.name} to Maven Central, because no maven publication could be found on this project") 45 | false 46 | } 47 | } 48 | } 49 | 50 | onlyIf { 51 | if (ext.ossrhUser == null || ext.ossrhPassword == null) { 52 | project.logger.warn("bintray.[ossrhUser, ossrhPassword] are required to sync to Maven Central") 53 | false 54 | } else true 55 | } 56 | } 57 | 58 | @TaskAction 59 | fun mavenCentralSync() { 60 | val sync = MavenCentralSync(ext.ossrhUser!!, ext.ossrhPassword!!) 61 | val packageVersionPath = "${pkg.subject}/${pkg.repo}/${pkg.name}/versions/$version" 62 | bintrayClient.post("maven_central_sync/$packageVersionPath", sync).use { response -> 63 | if (response.isSuccessful) { 64 | logger.info("Synced /$packageVersionPath to Maven Central") 65 | } else { 66 | throw GradleException("Could not sync /$packageVersionPath to Maven Central: HTTP ${response.code()} / ${response.body()?.string()}") 67 | } 68 | } 69 | } 70 | 71 | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy::class) 72 | @JsonInclude(JsonInclude.Include.NON_NULL) 73 | private data class MavenCentralSync( 74 | val username: String, 75 | val password: String, 76 | val close: Int = 1) 77 | } 78 | 79 | object MavenCentral { 80 | private const val MAVEN_CENTRAL_URI = "https://repo1.maven.org/maven2" 81 | 82 | fun exists(pub: MavenPublication): Boolean = OkHttpClient.Builder().build() 83 | .newCall(Request.Builder().head() 84 | .url("$MAVEN_CENTRAL_URI/${pub.groupId.replace('.', '/')}/${pub.artifactId}/${pub.version}") 85 | .build()) 86 | .execute() 87 | .use { response -> response.isSuccessful } 88 | } -------------------------------------------------------------------------------- /src/main/kotlin/io/spring/gradle/bintray/task/PublishTask.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray.task 17 | 18 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties 19 | import com.fasterxml.jackson.annotation.JsonInclude 20 | import com.fasterxml.jackson.databind.ObjectMapper 21 | import com.fasterxml.jackson.databind.PropertyNamingStrategy 22 | import com.fasterxml.jackson.databind.annotation.JsonNaming 23 | import com.fasterxml.jackson.module.kotlin.KotlinModule 24 | import org.gradle.api.GradleException 25 | import org.gradle.api.tasks.TaskAction 26 | 27 | /** 28 | * Publishing basically means that other users can see and download the files you have uploaded. 29 | * Only uploaded files (not repos, packages, versions or user profiles) can ever have the status of unpublished. 30 | * This gives the uploading user time to change his or her mind about the upload or to verify or test it. 31 | * After 7 days, unpublished files are deleted from Bintray. Note that since unpublished is the default status 32 | * of an uploaded file, every file manually uploaded must be separately published. Unpublished files are only 33 | * visible and accessible on Bintray to the user who uploaded them; once these files are uploaded the right and 34 | * ability to publish them belongs to this user. 35 | * 36 | * Publishing has the secondary effect of getting files into JCenter if the package has been pre-approved for 37 | * JCenter syncing. 38 | * 39 | * @author Jon Schneider 40 | */ 41 | open class PublishTask : AbstractBintrayTask() { 42 | companion object { 43 | val mapper: ObjectMapper = ObjectMapper().registerModule(KotlinModule()) 44 | } 45 | 46 | init { 47 | onlyIf { 48 | // version must exist in Bintray prior to publishing 49 | bintrayClient.get(versionPath).use { response -> 50 | // if the version is already published, do nothing 51 | val body = response.body()?.string() 52 | response.isSuccessful && (mapper.readValue(body, GetVersion::class.java)?.published?.let { !it } 53 | ?: false) 54 | } 55 | } 56 | } 57 | 58 | @TaskAction 59 | fun publish() { 60 | val packageVersionPath = "${pkg.subject}/${pkg.repo}/${pkg.name}/$version" 61 | bintrayClient.post("content/$packageVersionPath/publish", Publish()).use { response -> 62 | if (response.isSuccessful) { 63 | logger.info("Created Bintray package version /$packageVersionPath") 64 | } else { 65 | throw GradleException("Could not publish package version /$packageVersionPath: HTTP ${response.code()} / ${response.body()?.string()}") 66 | } 67 | } 68 | } 69 | 70 | @JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy::class) 71 | @JsonInclude(JsonInclude.Include.NON_NULL) 72 | private data class Publish( 73 | // causes this request to block waiting for publishing to complete, blocking for the maximum timeout allowed by Bintray 74 | val publishWaitForSecs: Int = -1) 75 | 76 | @JsonIgnoreProperties(ignoreUnknown = true) 77 | private data class GetVersion(val published: Boolean) 78 | } -------------------------------------------------------------------------------- /src/main/kotlin/io/spring/gradle/bintray/task/SignTask.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray.task 17 | 18 | import com.fasterxml.jackson.annotation.JsonInclude 19 | import org.gradle.api.GradleException 20 | import org.gradle.api.tasks.TaskAction 21 | 22 | open class SignTask : AbstractBintrayTask() { 23 | init { 24 | onlyIf { bintrayClient.headIsSuccessful(versionPath) } 25 | } 26 | 27 | @TaskAction 28 | fun sign() { 29 | logger.info("Signing $path") 30 | 31 | val sign = Sign(ext.gpgPassphrase) 32 | bintrayClient.post("gpg/${pkg.subject}/${pkg.repo}/${pkg.name}/versions/$version", sign).use { response -> 33 | if (!response.isSuccessful) { 34 | throw GradleException("failed to sign $path: HTTP ${response.code()} / ${response.body()?.string()}") 35 | } 36 | } 37 | } 38 | } 39 | 40 | @JsonInclude(JsonInclude.Include.NON_NULL) 41 | private data class Sign(val passphrase: String? = null) -------------------------------------------------------------------------------- /src/main/kotlin/io/spring/gradle/bintray/task/UploadTask.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray.task 17 | 18 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties 19 | import com.fasterxml.jackson.databind.ObjectMapper 20 | import com.fasterxml.jackson.module.kotlin.KotlinModule 21 | import io.spring.gradle.bintray.BintrayClient 22 | import io.spring.gradle.bintray.BintrayPackage 23 | import okhttp3.OkHttpClient 24 | import okhttp3.Request 25 | import org.gradle.api.GradleException 26 | import org.gradle.api.publish.maven.internal.publication.DefaultMavenPublication 27 | import org.gradle.api.tasks.TaskAction 28 | import org.gradle.workers.IsolationMode 29 | import org.gradle.workers.WorkerConfiguration 30 | import org.gradle.workers.WorkerExecutor 31 | import org.slf4j.LoggerFactory 32 | import java.io.File 33 | import javax.inject.Inject 34 | 35 | /** 36 | * Uploads all files related to a package version. Employs the Gradle Worker API to accomplish parallel uploading. 37 | * 38 | * @author Jon Schneider 39 | */ 40 | open class UploadTask @Inject constructor(private val workerExecutor: WorkerExecutor) : AbstractBintrayTask() { 41 | init { 42 | onlyIf { 43 | if (publication == null) { 44 | logger.warn("'${ext.publication}' does not refer to a maven publication, skipping") 45 | false 46 | } else true 47 | } 48 | } 49 | 50 | @TaskAction 51 | fun upload() { 52 | if (publication is DefaultMavenPublication) { 53 | val mavenPub = publication as DefaultMavenPublication 54 | 55 | // it's not clear from the Gradle implementation if it's possible for pomArtifact to be null, so we're defensive 56 | val pomArtifact = mavenPub.asNormalisedPublication().pomArtifact ?: 57 | throw GradleException("POM file does not exist for publication '${mavenPub.name}'") 58 | 59 | val artifacts = setOf(pomArtifact) + mavenPub.artifacts 60 | 61 | artifacts.forEach { artifact -> 62 | workerExecutor.submit(UploadWorker::class.java) { config: WorkerConfiguration -> 63 | val path = 64 | (mavenPub.groupId?.replace('.', '/') ?: "") + 65 | "/${mavenPub.artifactId}/${mavenPub.version}/${mavenPub.artifactId}-${mavenPub.version}" + 66 | (artifact.classifier?.let { "-$it" } ?: "") + 67 | ".${artifact.extension}" 68 | 69 | config.isolationMode = IsolationMode.NONE 70 | config.params(bintrayUser(), bintrayKey(), pkg, mavenPub.version, path, artifact.file, ext.overrideOnUpload, 71 | ext.gpgPassphrase ?: "") 72 | } 73 | } 74 | } else { 75 | logger.info("'${ext.publication}' does not refer to a maven publication, skipping") 76 | } 77 | } 78 | } 79 | 80 | /** 81 | * Allows artifacts to be uploaded in parallel, speeding the completion of this task 82 | */ 83 | private class UploadWorker @Inject constructor(val bintrayUser: String, 84 | val bintrayKey: String, 85 | val pkg: BintrayPackage, 86 | val version: String, 87 | val path: String, 88 | val artifact: File, 89 | val overrideOnUpload: Boolean, 90 | val gpgPassphrase: String?) : Runnable { 91 | 92 | @Transient 93 | private val mapper = ObjectMapper().registerModule(KotlinModule()) 94 | 95 | @Transient 96 | private val logger = LoggerFactory.getLogger(UploadWorker::class.java) 97 | 98 | override fun run() { 99 | val bintrayClient = BintrayClient(bintrayUser, bintrayKey) 100 | 101 | if (overrideOnUpload || !artifactExists()) { 102 | logger.info("Uploading $path") 103 | 104 | try { 105 | bintrayClient.upload("content/${pkg.subject}/${pkg.repo}/${pkg.name}/$version/$path", artifact, gpgPassphrase).use { response -> 106 | if (!response.isSuccessful) { 107 | throw GradleException("failed to upload $path: HTTP ${response.code()} / ${response.body()?.string()}") 108 | } 109 | 110 | response.body()?.let { body -> 111 | mapper.readValue(body.string(), UploadResponse::class.java).warn?.let { warning -> 112 | logger.warn("Upload response for $path contained warning message: '{}'", warning) 113 | } 114 | } 115 | } 116 | } catch (t: Throwable) { 117 | throw GradleException("failed to upload $path", t) 118 | } 119 | } 120 | } 121 | 122 | private fun artifactExists(): Boolean { 123 | val (subject, repo) = pkg 124 | 125 | val request = Request.Builder() 126 | .head() 127 | .url("https://dl.bintray.com/$subject/$repo/$path") 128 | .build() 129 | 130 | val response = OkHttpClient.Builder().build().newCall(request).execute() 131 | 132 | return if (response.isSuccessful) { 133 | logger.info("/$subject/$repo/$path already exists, skipping upload") 134 | true 135 | } else false 136 | } 137 | } 138 | 139 | @JsonIgnoreProperties(ignoreUnknown = true) 140 | private data class UploadResponse(val warn: String? = null) -------------------------------------------------------------------------------- /src/main/resources/META-INF/gradle-plugins/io.spring.bintray.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017-2018 Pivotal Software, Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | implementation-class=io.spring.gradle.bintray.SpringBintrayPlugin -------------------------------------------------------------------------------- /src/test/kotlin/io/spring/gradle/bintray/BintrayApiMatchers.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray 17 | 18 | import com.fasterxml.jackson.databind.ObjectMapper 19 | import com.fasterxml.jackson.module.kotlin.KotlinModule 20 | import okhttp3.Interceptor 21 | import okhttp3.MediaType 22 | import okhttp3.Protocol 23 | import okhttp3.Response 24 | import okhttp3.ResponseBody 25 | import okio.Buffer 26 | import org.assertj.core.api.Assertions.assertThat 27 | 28 | object BintrayApiMatchers { 29 | fun pathEq(path: String, responseCode: Int = 200) = PathEqualsInterceptor(path, responseCode) 30 | fun bodyEq(body: T) = BodyEqualsInterceptor(body) 31 | } 32 | 33 | class PathEqualsInterceptor(private val path: String, private val responseCode: Int) : Interceptor { 34 | override fun intercept(chain: Interceptor.Chain): Response { 35 | val request = chain.request() 36 | 37 | assertThat(request.url().encodedPath()).isEqualTo(path) 38 | 39 | return Response.Builder() 40 | .request(request) 41 | .protocol(Protocol.HTTP_1_1) 42 | .code(responseCode) 43 | .message("path matcher") 44 | .body(ResponseBody.create(MediaType.parse("text/plain"), "")) 45 | .build() 46 | } 47 | } 48 | 49 | class BodyEqualsInterceptor(private val body: T) : Interceptor { 50 | override fun intercept(chain: Interceptor.Chain): Response { 51 | val request = chain.request() 52 | 53 | val copy = request.newBuilder().build() 54 | val buffer = Buffer() 55 | copy.body()?.writeTo(buffer) 56 | val body = ObjectMapper().registerModule(KotlinModule()) 57 | .readValue(buffer.readByteArray(), body.javaClass) 58 | 59 | assertThat(body).isEqualTo(body) 60 | 61 | return Response.Builder() 62 | .request(request) 63 | .protocol(Protocol.HTTP_1_1) 64 | .code(200) 65 | .build() 66 | } 67 | } -------------------------------------------------------------------------------- /src/test/kotlin/io/spring/gradle/bintray/task/AbstractBintrayTaskSetup.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray.task; 17 | 18 | import io.spring.gradle.bintray.SpringBintrayExtension 19 | import org.eclipse.jgit.api.Git 20 | import org.gradle.api.Project 21 | import org.gradle.testfixtures.ProjectBuilder 22 | import org.junit.jupiter.api.BeforeEach 23 | 24 | /** 25 | * Base class for all bintray task tests 26 | */ 27 | abstract class AbstractBintrayTaskSetup { 28 | protected val project: Project = ProjectBuilder.builder().withName("mock-project").build() 29 | private val ext = project.extensions.create("bintray", SpringBintrayExtension::class.java) 30 | 31 | @BeforeEach 32 | fun gitAndExtensionProperties() { 33 | Git.init().setDirectory(project.projectDir).call().use { git -> 34 | val config = git.repository.config 35 | config.setString("remote", "origin", "url", "git@github.com:mock/mock-project.git") 36 | config.save() 37 | } 38 | 39 | ext.bintrayUser = "doesnt.matter" 40 | ext.bintrayKey = "doesnt.matter" 41 | ext.org = "spring" 42 | ext.repo = "jars" 43 | ext.packageDescription = "some description" 44 | ext.licenses = listOf("apache2") 45 | ext.labels = listOf("label") 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/test/kotlin/io/spring/gradle/bintray/task/AbstractBintrayTaskTest.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray.task 17 | 18 | import io.spring.gradle.bintray.SpringBintrayExtension 19 | import org.assertj.core.api.Assertions.assertThat 20 | import org.assertj.core.util.Files 21 | import org.gradle.api.Project 22 | import org.gradle.api.plugins.ExtraPropertiesExtension 23 | import org.gradle.testfixtures.ProjectBuilder 24 | import org.junit.After 25 | import org.junit.jupiter.api.Test 26 | 27 | open class AbstractBintrayTaskTest { 28 | private val project = ProjectBuilder.builder().withName("mock-project").build() 29 | private val task = project.tasks.create("bintrayTask", NoopBintrayTask::class.java) 30 | 31 | init { 32 | project.extensions.getByType(ExtraPropertiesExtension::class.java).run { 33 | set("bintrayUser", "me") 34 | set("bintrayKey", "key") 35 | } 36 | 37 | project.extensions.create("bintray", SpringBintrayExtension::class.java) 38 | } 39 | 40 | @Test 41 | fun `load bintray user and key from props`() { 42 | assertThat(task.bintrayUser()).isEqualTo("me") 43 | assertThat(task.bintrayKey()).isEqualTo("key") 44 | } 45 | 46 | open class NoopBintrayTask : AbstractBintrayTask() 47 | } -------------------------------------------------------------------------------- /src/test/kotlin/io/spring/gradle/bintray/task/CreatePackageTaskTest.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray.task 17 | 18 | import io.spring.gradle.bintray.BintrayApiMatchers.bodyEq 19 | import io.spring.gradle.bintray.BintrayApiMatchers.pathEq 20 | import org.assertj.core.api.Assertions.assertThat 21 | import org.junit.jupiter.api.Test 22 | 23 | 24 | class CreatePackageTaskTest: AbstractBintrayTaskSetup() { 25 | private val task = project.tasks.create("bintrayCreatePackage", CreatePackageTask::class.java) 26 | 27 | @Test 28 | fun `check if package exists`() { 29 | task.bintrayClient.interceptors = listOf(pathEq("/packages/spring/jars/mock-project", 404)) 30 | assertThat(task.onlyIf.isSatisfiedBy(task)).isTrue() 31 | } 32 | 33 | @Test 34 | fun `vcsUrl and githubRepo can be inferred from the project`() { 35 | task.bintrayClient.interceptors = listOf( 36 | pathEq("/packages/spring/jars"), 37 | bodyEq(CreatePackage(project.name, 38 | "some description", 39 | listOf("apache2"), 40 | listOf("label"), 41 | "https://github.com/mock/mock-project", 42 | "https://github.com/mock/mock-project/issues", 43 | "https://github.com/mock/mock-project.git", 44 | true)) 45 | ) 46 | 47 | task.createPackage() 48 | } 49 | } -------------------------------------------------------------------------------- /src/test/kotlin/io/spring/gradle/bintray/task/CreateVersionTaskTest.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray.task 17 | 18 | import io.spring.gradle.bintray.BintrayApiMatchers 19 | import org.assertj.core.api.Assertions.assertThat 20 | import org.junit.jupiter.api.Test 21 | 22 | class CreateVersionTaskTest: AbstractBintrayTaskSetup() { 23 | private val task = project.tasks.create("bintrayCreateVersion", CreateVersionTask::class.java) 24 | 25 | @Test 26 | fun `check if version exists`() { 27 | project.version = "1.0" 28 | task.bintrayClient.interceptors = listOf(BintrayApiMatchers.pathEq("/packages/spring/jars/mock-project/versions/1.0", 404)) 29 | assertThat(task.onlyIf.isSatisfiedBy(task)).isTrue() 30 | } 31 | 32 | @Test 33 | fun `vcsUrl and githubRepo can be inferred from the project`() { 34 | task.bintrayClient.interceptors = listOf( 35 | BintrayApiMatchers.pathEq("/packages/spring/jars/mock-project/versions"), 36 | BintrayApiMatchers.bodyEq(CreateVersion(project.name, "v1.0")) 37 | ) 38 | task.createVersion() 39 | } 40 | } -------------------------------------------------------------------------------- /src/test/kotlin/io/spring/gradle/bintray/task/MavenCentralSyncTaskTest.kt: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2017-2018 Pivotal Software, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package io.spring.gradle.bintray.task 17 | 18 | import com.nhaarman.mockito_kotlin.doReturn 19 | import com.nhaarman.mockito_kotlin.mock 20 | import org.assertj.core.api.Assertions.assertThat 21 | import org.gradle.api.publish.maven.MavenPublication 22 | import org.junit.jupiter.api.Test 23 | 24 | class MavenCentralSyncTaskTest { 25 | @Test 26 | fun existsInMavenCentral() { 27 | val pub = mock { 28 | on { groupId } doReturn "org.springframework.boot" 29 | on { artifactId } doReturn "spring-boot-starter-actuator" 30 | on { version } doReturn "2.0.0.RELEASE" 31 | } 32 | 33 | assertThat(MavenCentral.exists(pub)).isTrue() 34 | } 35 | 36 | @Test 37 | fun doesNotExistInMavenCentral() { 38 | val pub = mock { 39 | on { groupId } doReturn "org.springframework.boot" 40 | on { artifactId } doReturn "spring-boot-starter-actuator" 41 | on { version } doReturn "DOES.NOT.EXIST" 42 | } 43 | 44 | assertThat(MavenCentral.exists(pub)).isFalse() 45 | } 46 | } -------------------------------------------------------------------------------- /src/test/resources/bintray.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2017-2018 Pivotal Software, Inc. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | bintrayUser=spring-operator 18 | bintrayKey=d958a5bfa633e4da5ccfa034727c67d4be96ac9c --------------------------------------------------------------------------------