From 8fc0bc9d66532cb9447b207477a9b0c4c7a1bec4 Mon Sep 17 00:00:00 2001 From: Alexei Vainshtein Date: Sun, 10 Jun 2018 13:21:36 +0300 Subject: [PATCH] Adjustment to make tests public, create final task for publishing, don't skip if missing username or password --- README.md | 24 + .../bintray/gradle/BintrayExtension.groovy | 1 + .../jfrog/bintray/gradle/BintrayPlugin.groovy | 156 +--- .../bintray/gradle/BintrayUploadTask.groovy | 816 ------------------ .../ProjectsEvaluatedBuildListener.groovy | 131 +++ .../gradle/tasks/BintrayPublishTask.groovy | 102 +++ .../gradle/tasks/BintrayUploadTask.groovy | 596 +++++++++++++ .../{ => tasks}/RecordingCopyTask.groovy | 3 +- .../{ => tasks/entities}/Artifact.groovy | 2 +- .../gradle/tasks/entities/Package.groovy | 43 + .../gradle/tasks/entities/Repository.groovy | 26 + .../gradle/tasks/entities/Version.groovy | 65 ++ .../gradle/GradleBintrayPluginSpec.groovy | 127 ++- .../bintray/gradle/PluginSpecUtils.groovy | 2 - .../jfrog/bintray/gradle/TestsConfig.groovy | 14 +- ...n_package_and_version_with_fileSpec.gradle | 12 +- ...kage_and_version_with_configuration.gradle | 12 +- ...with_configuration_without_username.gradle | 27 + ...e_package_and_version_with_fileSpec.gradle | 12 +- ...ackage_and_version_with_publication.gradle | 12 +- .../buildFiles/maven_central_sync.gradle | 20 - .../gradle/buildFiles/override.gradle | 10 +- .../api/build.gradle | 49 ++ .../main/java/org/gradle/api/PersonList.java | 37 + .../src/main/java/org/gradle/api/package.html | 19 + .../main/java/org/gradle/apiImpl/Impl.java | 25 + .../configurationWithSubModules/build.gradle | 34 + .../configurationWithSubModules/gradlew | 164 ++++ .../configurationWithSubModules/gradlew.bat | 90 ++ .../settings.gradle | 1 + 30 files changed, 1618 insertions(+), 1014 deletions(-) delete mode 100644 src/main/groovy/com/jfrog/bintray/gradle/BintrayUploadTask.groovy create mode 100644 src/main/groovy/com/jfrog/bintray/gradle/ProjectsEvaluatedBuildListener.groovy create mode 100644 src/main/groovy/com/jfrog/bintray/gradle/tasks/BintrayPublishTask.groovy create mode 100644 src/main/groovy/com/jfrog/bintray/gradle/tasks/BintrayUploadTask.groovy rename src/main/groovy/com/jfrog/bintray/gradle/{ => tasks}/RecordingCopyTask.groovy (93%) rename src/main/groovy/com/jfrog/bintray/gradle/{ => tasks/entities}/Artifact.groovy (97%) create mode 100644 src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Package.groovy create mode 100644 src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Repository.groovy create mode 100644 src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Version.groovy create mode 100644 src/test/resources/gradle/buildFiles/create_package_and_version_with_configuration_without_username.gradle delete mode 100644 src/test/resources/gradle/buildFiles/maven_central_sync.gradle create mode 100644 src/test/resources/gradle/projects/configurationWithSubModules/api/build.gradle create mode 100644 src/test/resources/gradle/projects/configurationWithSubModules/api/src/main/java/org/gradle/api/PersonList.java create mode 100644 src/test/resources/gradle/projects/configurationWithSubModules/api/src/main/java/org/gradle/api/package.html create mode 100644 src/test/resources/gradle/projects/configurationWithSubModules/api/src/main/java/org/gradle/apiImpl/Impl.java create mode 100644 src/test/resources/gradle/projects/configurationWithSubModules/build.gradle create mode 100644 src/test/resources/gradle/projects/configurationWithSubModules/gradlew create mode 100644 src/test/resources/gradle/projects/configurationWithSubModules/gradlew.bat create mode 100644 src/test/resources/gradle/projects/configurationWithSubModules/settings.gradle diff --git a/README.md b/README.md index b2add14..716968b 100644 --- a/README.md +++ b/README.md @@ -425,6 +425,30 @@ bintray { } ``` +# Tests + +#### Pre condition +The profile that performs the tests (user or organization) must have the following two repositories: +1. maven - For performing the java tests +2. debian - For performing the debian tests + +#### Running the tests +To run the tests, we need to provide a few variables. Those variables can be created as environment variables: + +| Environment variable | Description +| --- | --- | +| `BINTRAY_USER` | [Mandatory] Bintray user name. | +| `BINTRAY_KEY` | [Mandatory] Bintray API key. | +| `BINTRAY_ORG` | [Optional] Bintray organization. | + +To run the tests, please perform the following: + +```` +1. Clone the project +2. Configure the environment variables or configure within the build.gradle file. +3. Run the following: gradle test +```` + # Release Notes The release notes are available on [Bintray](https://bintray.com/jfrog/jfrog-jars/gradle-bintray-plugin#release). diff --git a/src/main/groovy/com/jfrog/bintray/gradle/BintrayExtension.groovy b/src/main/groovy/com/jfrog/bintray/gradle/BintrayExtension.groovy index eacbb6a..7faad4b 100644 --- a/src/main/groovy/com/jfrog/bintray/gradle/BintrayExtension.groovy +++ b/src/main/groovy/com/jfrog/bintray/gradle/BintrayExtension.groovy @@ -1,5 +1,6 @@ package com.jfrog.bintray.gradle +import com.jfrog.bintray.gradle.tasks.RecordingCopyTask import org.gradle.api.Project import org.gradle.util.ConfigureUtil diff --git a/src/main/groovy/com/jfrog/bintray/gradle/BintrayPlugin.groovy b/src/main/groovy/com/jfrog/bintray/gradle/BintrayPlugin.groovy index 8ae774f..cfa2847 100644 --- a/src/main/groovy/com/jfrog/bintray/gradle/BintrayPlugin.groovy +++ b/src/main/groovy/com/jfrog/bintray/gradle/BintrayPlugin.groovy @@ -1,125 +1,63 @@ package com.jfrog.bintray.gradle +import com.jfrog.bintray.gradle.tasks.BintrayPublishTask +import com.jfrog.bintray.gradle.tasks.BintrayUploadTask import org.gradle.api.* -import org.gradle.api.publish.Publication -import org.gradle.api.publish.PublishingExtension -import org.gradle.api.publish.maven.MavenPublication -import org.gradle.api.tasks.Upload class BintrayPlugin implements Plugin { - private Project project - public void apply(Project project) { - this.project = project; + if (project.getTasks().findByName(BintrayUploadTask.TASK_NAME) == null) { + //Create and configure the task + BintrayUploadTask bintrayUpload = project.task(type: BintrayUploadTask, BintrayUploadTask.TASK_NAME) + project.gradle.addListener(new ProjectsEvaluatedBuildListener(project, bintrayUpload)) + } - //Create and configure the task - BintrayUploadTask bintrayUpload = project.task(type: BintrayUploadTask, BintrayUploadTask.NAME) + addBintrayUploadTask(project) + if (isRootProject(project)) { + addBintrayPublishTask(project) + } else { + if (!project.getRootProject().getPluginManager().hasPlugin("com.jfrog.bintray")) { + // Reached this state means that the plugin is not enabled on the root project + BintrayUploadTask bintrayUploadRoot = project.getRootProject().task(type: BintrayUploadTask, BintrayUploadTask.TASK_NAME) + bintrayUploadRoot.setEnabled(false) + project.getRootProject().gradle.addListener(new ProjectsEvaluatedBuildListener(project.getRootProject(), bintrayUploadRoot)) + project.getRootProject().getPluginManager().apply(BintrayPlugin.class) + } + } + } - def extension = project.extensions.create("bintray", BintrayExtension, project) - extension.with { - apiUrl = BintrayUploadTask.API_URL_DEFAULT + private BintrayUploadTask addBintrayUploadTask(Project project) { + BintrayUploadTask bintrayUploadTask = project.tasks.findByName(BintrayUploadTask.TASK_NAME) + if (bintrayUploadTask == null) { + bintrayUploadTask = createBintrayUploadTask(project) + bintrayUploadTask.setGroup(BintrayUploadTask.GROUP) } + return bintrayUploadTask + } - project.gradle.addListener(new ProjectEvaluationListener() { - @Override - void beforeEvaluate(Project proj) { + BintrayUploadTask createBintrayUploadTask(Project project) { + def result = project.getTasks().create(BintrayUploadTask.TASK_NAME, BintrayUploadTask.class) + result.setDescription('''AddS bintray closure''') + return result + } - } + private static boolean isRootProject(Project project) { + project.equals(project.getRootProject()) + } - @Override - void afterEvaluate(Project proj, ProjectState state) { - bintrayUpload.with { - apiUrl = extension.apiUrl - user = extension.user - apiKey = extension.key - configurations = extension.configurations - publications = extension.publications - filesSpec = extension.filesSpec - publish = extension.publish - override = extension.override - dryRun = extension.dryRun - userOrg = extension.pkg.userOrg ?: extension.user - repoName = extension.pkg.repo - packageName = extension.pkg.name - packageDesc = extension.pkg.desc - packageWebsiteUrl = extension.pkg.websiteUrl - packageIssueTrackerUrl = extension.pkg.issueTrackerUrl - packageVcsUrl = extension.pkg.vcsUrl - packageGithubRepo = extension.pkg.githubRepo - packageGithubReleaseNotesFile = extension.pkg.githubReleaseNotesFile - packageLicenses = extension.pkg.licenses - packageLabels = extension.pkg.labels - packageAttributes = extension.pkg.attributes - packagePublicDownloadNumbers = extension.pkg.publicDownloadNumbers - debianDistribution = extension.pkg.debian.distribution - debianComponent = extension.pkg.debian.component - debianArchitecture = extension.pkg.debian.architecture - versionName = extension.pkg.version.name ?: project.version - versionDesc = extension.pkg.version.desc - versionReleased = extension.pkg.version.released - versionVcsTag = extension.pkg.version.vcsTag ?: project.version - versionAttributes = extension.pkg.version.attributes - signVersion = extension.pkg.version.gpg.sign - gpgPassphrase = extension.pkg.version.gpg.passphrase - syncToMavenCentral = extension.pkg.version.mavenCentralSync.sync == null ? - true : extension.pkg.version.mavenCentralSync.sync - ossUser = extension.pkg.version.mavenCentralSync.user - ossPassword = extension.pkg.version.mavenCentralSync.password - ossCloseRepo = extension.pkg.version.mavenCentralSync.close - } - if (extension.configurations?.length) { - extension.configurations.each { - def configuration = project.configurations.findByName(it) - if (!configuration) { - project.logger.warn "Configuration ${it} specified but does not exist in project {}.", - project.path - } else { - bintrayUpload.dependsOn(configuration.allArtifacts) - } - } - Upload installTask = project.tasks.withType(Upload)?.findByName('install') - if (installTask) { - bintrayUpload.dependsOn(installTask) - } else { - project.logger.warn "Configuration(s) specified but the install task does not exist in project {}.", - project.path - } - } - if (extension.publications?.length) { - def publicationExt = project.extensions.findByType(PublishingExtension) - if (!publicationExt) { - project.logger.warn "Publications(s) specified but no publications exist in project {}.", - project.path - } else { - extension.publications.each { - Publication publication = publicationExt?.publications?.findByName(it) - if (!publication) { - project.logger.warn 'Publication {} not found in project {}.', it, project.path - } else if (publication instanceof MavenPublication) { - def taskName = - "publish${it[0].toUpperCase()}${it.substring(1)}PublicationToMavenLocal" - bintrayUpload.dependsOn(taskName) - /*bintrayUpload.dependsOn(publication.publishableFiles)*/ - } else { - project.logger.warn "{} can only use maven publications - skipping {}.", - bintrayUpload.path, publication.name - } - } - } - } - // Depend on tasks in sub-projects - project.subprojects.each { - Task subTask = it.tasks.findByName(BintrayUploadTask.NAME) - if (subTask) { - bintrayUpload.dependsOn(subTask) - } - } - if (extension.filesSpec) { - bintrayUpload.dependsOn(extension.filesSpec) - } - } - }) + private BintrayPublishTask addBintrayPublishTask(Project project) { + Task signAndPublish = project.tasks.findByName(BintrayPublishTask.TASK_NAME) + if (signAndPublish == null) { + project.getLogger().info("Configuring signAndPublish task for project ${project.path}") + signAndPublish = createBintraySignAndPublishTask(project) + signAndPublish.setGroup(BintrayUploadTask.GROUP) + } + } + protected BintrayPublishTask createBintraySignAndPublishTask(Project project) { + def result = project.getTasks().create(BintrayPublishTask.TASK_NAME, BintrayPublishTask.class) + result.setDescription('''Bintray Sign, publish and Maven central sync task''') + return result } } diff --git a/src/main/groovy/com/jfrog/bintray/gradle/BintrayUploadTask.groovy b/src/main/groovy/com/jfrog/bintray/gradle/BintrayUploadTask.groovy deleted file mode 100644 index f8b462a..0000000 --- a/src/main/groovy/com/jfrog/bintray/gradle/BintrayUploadTask.groovy +++ /dev/null @@ -1,816 +0,0 @@ -package com.jfrog.bintray.gradle - -import groovy.json.JsonBuilder -import groovyx.net.http.HTTPBuilder -import org.gradle.api.DefaultTask -import org.gradle.api.GradleException -import org.gradle.api.Task -import org.gradle.api.artifacts.Configuration -import org.gradle.api.file.CopySpec -import org.gradle.api.publish.Publication -import org.gradle.api.publish.PublishingExtension -import org.gradle.api.publish.maven.MavenPublication -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.Optional -import org.gradle.api.tasks.TaskAction -import org.gradle.api.tasks.Upload -import java.util.concurrent.ConcurrentHashMap - -import static groovyx.net.http.ContentType.BINARY -import static groovyx.net.http.ContentType.JSON -import static groovyx.net.http.Method.* - -class BintrayUploadTask extends DefaultTask { - - static final String NAME = 'bintrayUpload' - static final String GROUP = 'publishing' - static final String DESCRIPTION = 'Publishes artifacts to bintray.com.' - static final String API_URL_DEFAULT = 'https://api.bintray.com' - - List bintrayUploadTasks = null - private ConcurrentHashMap repositories = new ConcurrentHashMap<>() - - @Input - @Optional - String apiUrl - - @Input - @Optional - String user - - @Input - @Optional - String apiKey - - @Input - @Optional - Object[] configurations - - @Input - @Optional - Object[] publications - - @Input - @Optional - CopySpec filesSpec - - @Input - boolean publish - - @Input - boolean override - - @Input - boolean dryRun - - @Input - @Optional - String userOrg - - @Input - @Optional - String repoName - - @Input - @Optional - String packageName - - @Input - @Optional - String packageDesc - - @Input - @Optional - String packageWebsiteUrl - - @Input - @Optional - String packageIssueTrackerUrl - - @Input - @Optional - String packageVcsUrl - - @Input - @Optional - String packageGithubRepo - - @Input - @Optional - String packageGithubReleaseNotesFile - - @Input - @Optional - String[] packageLicenses - - @Input - @Optional - String[] packageLabels - - @Input - @Optional - Map packageAttributes - - @Input - @Optional - boolean packagePublicDownloadNumbers - - @Input - @Optional - String debianDistribution - - @Input - @Optional - String debianComponent - - @Input - @Optional - String debianArchitecture - - @Input - @Optional - String versionName - - @Input - @Optional - String versionDesc - - @Input - @Optional - String versionReleased - - @Input - @Optional - boolean signVersion - - @Input - @Optional - String gpgPassphrase - - @Input - @Optional - String versionVcsTag - - @Input - @Optional - Map versionAttributes - - @Input - @Optional - boolean syncToMavenCentral - - @Input - @Optional - String ossUser - - @Input - @Optional - String ossPassword - - @Input - @Optional - String ossCloseRepo - - Artifact[] configurationUploads - Artifact[] publicationUploads - Artifact[] fileUploads - - { - group = GROUP - description = DESCRIPTION - } - - @TaskAction - void bintrayUpload() { - logger.info("Gradle Bintray Plugin version: ${new Utils().pluginVersion}"); - if (shouldSkip()) { - logger.info("Skipping task '{}:bintrayUpload' because user or apiKey is null.", this.project.name); - return - } - validateDebianDefinition() - - //TODO: [by yl] replace with findResults for Gradle 2.x - configurationUploads = configurations.collect { - if (it instanceof CharSequence) { - Configuration configuration = project.configurations.findByName(it) - if (configuration != null) { - return collectArtifacts(configuration) - } else { - logger.error("{}: Could not find configuration: {}.", path, it) - } - } else if (conf instanceof Configuration) { - return collectArtifacts((Configuration) it) - } else { - logger.error("{}: Unsupported configuration type: {}.", path, it.class) - } - [] - }.flatten() as Artifact[] - - publicationUploads = publications.collect { - if (it instanceof CharSequence) { - Publication publication = project.extensions.getByType(PublishingExtension).publications.findByName(it) - if (publication != null) { - return collectArtifacts(publication) - } else { - logger.error("{}: Could not find publication: {}.", path, it); - } - } else if (conf instanceof MavenPublication) { - return collectArtifacts((Configuration) it) - } else { - logger.error("{}: Unsupported publication type: {}.", path, it.class) - } - [] - }.flatten() as Artifact[] - - RecordingCopyTask recordingCopyTask = getDependsOn().find { it instanceof RecordingCopyTask } - fileUploads = (recordingCopyTask ? recordingCopyTask.fileUploads : []) as Artifact[] - - // Upload the files - HTTPBuilder http = BintrayHttpClientFactory.create(apiUrl, user, apiKey) - def subject = "${userOrg ?: user}" - def packagePath = "$subject/$repoName/$packageName" - - def setAttributes = { attributesPath, attributes, entity, entityName -> - http.request(POST, JSON) { - Utils.addHeaders(headers) - uri.path = attributesPath - def builder = new JsonBuilder() - builder.content = attributes.collect { - //Support both arrays and singular values - coerce to an array of values - ['name': it.key, 'values': [it.value].flatten()] - } - body = builder.toString() - response.success = { resp -> - logger.info("Attributes set on $entity '$entityName'.") - } - response.failure = { resp, reader -> - throw new GradleException( - "Could not set attributes on $entity '$entityName': $resp.statusLine $reader") - } - } - } - - def checkAndCreatePackage = { - // Check if the package has already been created by another BintrayUploadTask. - Package pkg = checkPackageAlreadyCreated() - if (pkg && pkg.isCreated()) { - return; - } - def create - http.request(HEAD) { - Utils.addHeaders(headers) - uri.path = "/packages/$packagePath" - response.success = { resp -> - logger.debug("Package '$packageName' exists.") - } - response.'404' = { resp -> - logger.info("Package '$packageName' does not exist. Attempting to create it...") - create = true - } - } - if (create) { - if (dryRun) { - logger.info("(Dry run) Created package '$packagePath'.") - } else { - http.request(POST, JSON) { - Utils.addHeaders(headers) - uri.path = "/packages/$subject/$repoName" - body = [name: packageName, desc: packageDesc, - licenses: packageLicenses, - labels: packageLabels, - website_url: packageWebsiteUrl, - issue_tracker_url: packageIssueTrackerUrl, - vcs_url: packageVcsUrl, - public_download_numbers: packagePublicDownloadNumbers, - github_repo: packageGithubRepo, - github_release_notes_file: packageGithubReleaseNotesFile] - - response.success = { resp -> - logger.info("Created package '$packagePath'.") - } - response.failure = { resp, reader -> - throw new GradleException("Could not create package '$packagePath': $resp.statusLine $reader") - } - } - if (packageAttributes) { - setAttributes "/packages/$packagePath/attributes", packageAttributes, 'package', packageName - } - } - } - setPackageAsCreated(pkg) - } - - def checkAndCreateVersion = { - // Check if the version has already been created by another BintrayUploadTask. - Version version = checkVersionAlreadyCreated() - if (version && version.isCreated()) { - return; - } - def create - http.request(HEAD) { - Utils.addHeaders(headers) - uri.path = "/packages/$packagePath/versions/$versionName" - response.success = { resp -> - logger.debug("Version '$packagePath/$versionName' exists.") - } - response.'404' = { resp -> - logger.info("Version '$packagePath/$versionName' does not exist. Attempting to create it...") - create = true - } - } - if (create) { - if (dryRun) { - logger.info("(Dry run) Created version '$packagePath/$versionName'.") - } else { - http.request(POST, JSON) { - Utils.addHeaders(headers) - uri.path = "/packages/$packagePath/versions" - versionReleased = Utils.toIsoDateFormat(versionReleased) - body = [name: versionName, desc: versionDesc, released: versionReleased, vcs_tag: versionVcsTag] - response.success = { resp -> - logger.info("Created version '$versionName'.") - } - response.failure = { resp, reader -> - throw new GradleException("Could not create version '$versionName': $resp.statusLine $reader") - } - } - if (versionAttributes) { - setAttributes "/packages/$packagePath/versions/$versionName/attributes", versionAttributes, - 'version', versionName - } - } - } - setVersionAsCreated(version) - } - - def gpgSignVersion = { repo, pkg, version -> - def pkgPath = "$subject/$repo.name/$pkg.name" - def versionName = version.name - if (dryRun) { - logger.info("(Dry run) Signed version '$pkgPath/$versionName'.") - return - } - http.request(POST, JSON) { - Utils.addHeaders(headers) - uri.path = "/gpg/$pkgPath/versions/$versionName" - if (version.gpgPassphrase) { - body = [passphrase: gpgPassphrase] - } - response.success = { resp -> - logger.info("Signed version '$versionName'.") - } - response.failure = { resp, reader -> - throw new GradleException("Could not sign version '$versionName': $resp.statusLine $reader") - } - } - } - - def uploadArtifact = { artifact -> - def versionPath = packagePath + '/' + versionName ?: artifact.version - def uploadUri = "/content/$versionPath/${artifact.path}" - - if (!artifact.file.exists()) { - logger.error("Skipping upload for missing file '$artifact.file'.") - return - } - artifact.file.withInputStream { is -> - is.metaClass.totalBytes = { - artifact.file.length() - } - logger.info("Uploading to $apiUrl$uploadUri...") - if (dryRun) { - logger.info("(Dry run) Uploaded to '$apiUrl$uploadUri'.") - return - } - http.request(PUT) { - if (override) { - uri.query = [override: "1"] - } - addUploadHeaders(headers) - // Set the requestContentType to BINARY, so that HTTPBuilder can encode the uploaded file: - requestContentType = BINARY - // Set the Content-Type to '*/*' to enable Bintray to set it on its own: - headers["Content-Type"] = '*/*' - uri.path = uploadUri - body = is - response.success = { resp -> - logger.info("Uploaded to '$apiUrl$uri.path'.") - } - response.failure = { resp, reader -> - throw new GradleException("Could not upload to '$apiUrl$uri.path': $resp.statusLine $reader") - } - } - } - } - - def publishVersion = { repo, pkg, version -> - def pkgPath = "$subject/$repo.name/$pkg.name" - def versionName = version.name - def publishUri = "/content/$pkgPath/$versionName/publish" - if (dryRun) { - logger.info("(Dry run) Published version '$pkgPath/$versionName'.") - return - } - http.request(POST, JSON) { - Utils.addHeaders(headers) - uri.path = publishUri - response.success = { resp -> - logger.info("Published '$pkgPath/$versionName'.") - } - response.failure = { resp, reader -> - throw new GradleException("Could not publish '$pkgPath/$versionName': $resp.statusLine $reader") - } - } - } - - def mavenCentralSync = { repo, pkg, version -> - def pkgPath = "$subject/$repo.name/$pkg.name" - def versionName = version.name - if (dryRun) { - logger.info("(Dry run) Sync to Maven Central performed for '$pkgPath/$versionName'.") - return - } - http.request(POST, JSON) { - Utils.addHeaders(headers) - uri.path = "/maven_central_sync/$pkgPath/versions/$versionName" - body = [username: ossUser, password: ossPassword] - if (ossCloseRepo != null) { - body << [close: ossCloseRepo] - } - response.success = { resp -> - logger.info("Sync to Maven Central performed for '$pkgPath/$versionName'.") - } - response.failure = { resp, reader -> - throw new GradleException("Could not sync '$pkgPath/$versionName' to Maven Central: $resp.statusLine $reader") - } - } - } - - def signPublishAndSync = { - Collection repositories = getCachedRepositories().values() - for (Repository r : repositories) { - Collection packages = r.packages.values() - for (Package p : packages) { - Collection versions = p.versions.values() - for (Version v : versions) { - if (v.gpgSign) { - gpgSignVersion(r, p, v) - } - if (v.publish) { - publishVersion(r, p, v) - } - if (v.mavenCentralSync) { - mavenCentralSync(r, p, v) - } - } - } - } - } - - checkAndCreatePackage() - checkAndCreateVersion() - - configurationUploads.each { - uploadArtifact it - } - publicationUploads.each { - uploadArtifact it - } - fileUploads.each { - uploadArtifact it - } - if (lastTask) { - signPublishAndSync() - } - } - - void validateDebianDefinition() { - if ((debianDistribution && !debianArchitecture) || - (!debianDistribution && debianArchitecture)) { - throw new GradleException("Both 'distribution' and 'architecture' are mandatory in the gradle.debian closure.") - } - } - - boolean shouldSkip() { - return (user == null || apiKey == null) - } - - void addUploadHeaders(Map headers) { - Utils.addHeaders(headers) - if (debianDistribution) { - String component = debianComponent ? debianComponent : "main" - headers.put("X-Bintray-Debian-Distribution", debianDistribution) - headers.put("X-Bintray-Debian-Component", component) - headers.put("X-Bintray-Debian-Architecture", debianArchitecture) - } - } - - Package checkPackageAlreadyCreated() { - Package pkg = new Package(packageName) - Package p = getRepository().packages.putIfAbsent(packageName, pkg) - if (p && !p.created) { - synchronized (p) { - if (!p.created) { - p.wait() - } - } - } - return p ? p : pkg - } - - Version checkVersionAlreadyCreated() { - Package pkg = getRepository().packages.get(packageName) - if (!pkg) { - throw new IllegalStateException( - "Attempted checking and creating version, before checking and creating the package.") - } - Version v = new Version( - versionName, signVersion, gpgPassphrase, publish, shouldSyncToMavenCentral()) - Version version = pkg.addVersionIfAbsent(v) - if (version && !version.created) { - synchronized (version) { - if (!version.created) { - version.wait() - } - } - } - return version ? version : v - } - - void setPackageAsCreated(Package pkg) { - pkg.setAsCreated() - synchronized (pkg) { - pkg.notifyAll() - } - } - - void setVersionAsCreated(Version version) { - version.setAsCreated() - synchronized (version) { - version.notifyAll() - } - } - - /** - * Indicates whether this BintrayUploadTask is the last task to be executed. - * @return true if this is the last BintrayUploadTask task. - */ - boolean isLastTask() { - currentTaskIndex == allBintrayUploadTasks.size() - 1 - } - - /** - * Return the index of this BintrayUploadTask in the list of all tasks of type BintrayUploadTask. - * @return The task index. - */ - int getCurrentTaskIndex() { - List tasks = allBintrayUploadTasks - int currentTaskIndex = tasks.indexOf(this); - if (currentTaskIndex == -1) { - throw new Exception("Could not find the current task {} in the task graph", getPath()); - } - currentTaskIndex - } - - List getAllBintrayUploadTasks() { - if (!bintrayUploadTasks) { - List tasks = new ArrayList() - for (Task task : getProject().getGradle().getTaskGraph().getAllTasks()) { - if (task instanceof BintrayUploadTask) { - if (!task.shouldSkip()) { - tasks.add(task); - } - } - } - bintrayUploadTasks = tasks - } - bintrayUploadTasks - } - - boolean shouldSyncToMavenCentral() { - syncToMavenCentral && ossUser != null && ossPassword != null - } - - Artifact[] collectArtifacts(Configuration config) { - boolean pomArtifact - def artifacts = config.allArtifacts.findResults { - if (!it.file.exists()) { - logger.error("{}: file {} could not be found.", path, it.file.getAbsolutePath()) - return null - } - pomArtifact = !pomArtifact && it.type == 'pom' - boolean signedArtifact = (it instanceof org.gradle.plugins.signing.Signature) - def signedExtension = signedArtifact ? it.toSignArtifact.getExtension() : null - new Artifact( - name: it.name, groupId: project.group, version: project.version, extension: it.extension, - type: it.type, classifier: it.classifier, file: it.file, signedExtension: signedExtension - ) - }.unique(); - - // Add pom file per config - Upload installTask = project.tasks.withType(Upload).findByName('install'); - if (!installTask) { - logger.info "maven plugin was not applied, no pom will be uploaded." - } else if (!pomArtifact) { - File pom = new File(getProject().convention.plugins['maven'].mavenPomDir, "pom-default.xml") - String artifactId = Utils.readArtifactIdFromPom(pom) - artifacts << new Artifact( - name: artifactId, - groupId: project.group, - version: project.version, - extension: 'pom', - type: 'pom', - file: pom - ) - } - artifacts - } - - Artifact[] collectArtifacts(Publication publication) { - if (!publication instanceof MavenPublication) { - logger.info "{} can only use maven publications - skipping {}.", path, publication.name - return [] - } - def identity = publication.mavenProjectIdentity - def artifacts = publication.artifacts.findResults { - boolean signedArtifact = (it instanceof org.gradle.plugins.signing.Signature) - def signedExtension = signedArtifact ? it.toSignArtifact.getExtension() : null - new Artifact( - name: identity.artifactId, - groupId: identity.groupId, - version: identity.version, - extension: it.extension, - type: it.extension, - classifier: it.classifier, - file: it.file, - signedExtension: signedExtension - ) - } - - // Add the pom file - artifacts << new Artifact( - name: identity.artifactId, - groupId: identity.groupId, - version: identity.version, - extension: 'pom', - type: 'pom', - file: publication.asNormalisedPublication().pomFile - ) - artifacts - } - - public ConcurrentHashMap getCachedRepositories() { - BintrayUploadTask t = ((BintrayUploadTask)project.rootProject.tasks.findByName(NAME)) - if (t == null) { - project.rootProject.getPluginManager().apply(BintrayPlugin.class) - t = ((BintrayUploadTask)project.rootProject.tasks.findByName(NAME)) - } - if (t == null) { - throw new RuntimeException("Could not find $NAME task in root project") - } - t.getRepositories() - } - - public ConcurrentHashMap getRepositories() { - if (this.project != this.project.rootProject) { - throw new IllegalStateException("The getRepositories method can be invoked on the root project$NAME task only") - } - return repositories - } - - private Repository getRepository() { - Repository repository = new Repository(repoName) - Repository r = getCachedRepositories().putIfAbsent(repoName, repository) - if (!r) { - return repository - } - return r - } - - class Repository { - private String name - private ConcurrentHashMap packages = new ConcurrentHashMap() - - Repository(String name) { - this.name = name - } - - boolean equals(o) { - if (this.is(o)) { - return true - } - if (getClass() != o.class || name != ((Repository)o).name) { - return false - } - return true - } - - int hashCode() { - name != null ? name.hashCode() : 0 - } - } - - class Package { - private String name - private boolean created - private ConcurrentHashMap versions = new ConcurrentHashMap() - - Package(String name) { - this.name = name - } - - boolean isCreated() { - return created - } - - void setAsCreated() { - this.created = true - } - - public Version addVersionIfAbsent(Version version) { - Version v = versions.putIfAbsent(version.name, version) - if (v) { - v.merge(version) - } - return v - } - - boolean equals(o) { - if (this.is(o)) { - return true - } - if (getClass() != o.class || name != ((Package)o).name) { - return false - } - return true - } - - int hashCode() { - name != null ? name.hashCode() : 0 - } - } - - class Version { - private String name - private boolean created - private boolean gpgSign - private String gpgPassphrase - private boolean publish - private boolean mavenCentralSync - - Version(String name, boolean gpgSign, String gpgPassphrase, boolean publish, boolean mavenCentralSync) { - this.name = name - this.gpgSign = gpgSign - this.gpgPassphrase = gpgPassphrase - this.publish = publish - this.mavenCentralSync = mavenCentralSync - } - - boolean isCreated() { - return created - } - - void setAsCreated() { - this.created = true - } - - boolean isGpgSign() { - return gpgSign - } - - String getGpgPassphrase() { - return gpgPassphrase - } - - boolean isPublish() { - return publish - } - - boolean isMavenCentralSync() { - return mavenCentralSync - } - - void merge(Version version) { - if (version) { - this.gpgSign = this.gpgSign || version.gpgSign - this.publish = this.publish || version.publish - this.mavenCentralSync = this.mavenCentralSync || version.mavenCentralSync - this.gpgPassphrase = gpgPassphrase ?: this.gpgPassphrase - } - } - - boolean equals(o) { - if (this.is(o)) { - return true - } - if (getClass() != o.class || name != ((Version)o).name) { - return false - } - return true - } - - int hashCode() { - name != null ? name.hashCode() : 0 - } - } -} diff --git a/src/main/groovy/com/jfrog/bintray/gradle/ProjectsEvaluatedBuildListener.groovy b/src/main/groovy/com/jfrog/bintray/gradle/ProjectsEvaluatedBuildListener.groovy new file mode 100644 index 0000000..7dd0d4f --- /dev/null +++ b/src/main/groovy/com/jfrog/bintray/gradle/ProjectsEvaluatedBuildListener.groovy @@ -0,0 +1,131 @@ +package com.jfrog.bintray.gradle + +import com.jfrog.bintray.gradle.tasks.BintrayPublishTask +import com.jfrog.bintray.gradle.tasks.BintrayUploadTask +import org.gradle.api.Project +import org.gradle.api.ProjectEvaluationListener +import org.gradle.api.ProjectState +import org.gradle.api.Task +import org.gradle.api.publish.Publication +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.api.tasks.Upload + +class ProjectsEvaluatedBuildListener implements ProjectEvaluationListener { + private Project project + private BintrayUploadTask bintrayUpload + private BintrayExtension extension + + ProjectsEvaluatedBuildListener(Project project, BintrayUploadTask bintrayUpload) { + this.project = project + this.bintrayUpload = bintrayUpload + extension = project.extensions.create("bintray", BintrayExtension, project) + extension.with { + apiUrl = BintrayUploadTask.API_URL_DEFAULT + } + } + + @Override + void beforeEvaluate(Project project) { + } + + @Override + void afterEvaluate(Project proj, ProjectState state) { + + bintrayUpload.with { + apiUrl = extension.apiUrl + user = extension.user + apiKey = extension.key + configurations = extension.configurations + publications = extension.publications + filesSpec = extension.filesSpec + publish = extension.publish + override = extension.override + dryRun = extension.dryRun + userOrg = extension.pkg.userOrg ?: extension.user + repoName = extension.pkg.repo + packageName = extension.pkg.name + packageDesc = extension.pkg.desc + packageWebsiteUrl = extension.pkg.websiteUrl + packageIssueTrackerUrl = extension.pkg.issueTrackerUrl + packageVcsUrl = extension.pkg.vcsUrl + packageGithubRepo = extension.pkg.githubRepo + packageGithubReleaseNotesFile = extension.pkg.githubReleaseNotesFile + packageLicenses = extension.pkg.licenses + packageLabels = extension.pkg.labels + packageAttributes = extension.pkg.attributes + packagePublicDownloadNumbers = extension.pkg.publicDownloadNumbers + debianDistribution = extension.pkg.debian.distribution + debianComponent = extension.pkg.debian.component + debianArchitecture = extension.pkg.debian.architecture + versionName = extension.pkg.version.name ?: project.version + versionDesc = extension.pkg.version.desc + versionReleased = extension.pkg.version.released + versionVcsTag = extension.pkg.version.vcsTag ?: project.version + versionAttributes = extension.pkg.version.attributes + signVersion = extension.pkg.version.gpg.sign + gpgPassphrase = extension.pkg.version.gpg.passphrase + syncToMavenCentral = extension.pkg.version.mavenCentralSync.sync == null ? + true : extension.pkg.version.mavenCentralSync.sync + ossUser = extension.pkg.version.mavenCentralSync.user + ossPassword = extension.pkg.version.mavenCentralSync.password + ossCloseRepo = extension.pkg.version.mavenCentralSync.close + } + + if (extension.configurations?.length) { + extension.configurations.each { + def configuration = project.configurations.findByName(it) + if (!configuration) { + project.logger.warn "Configuration ${it} specified but does not exist in project {}.", + project.path + } else { + bintrayUpload.dependsOn(configuration.allArtifacts) + } + } + Upload installTask = project.tasks.withType(Upload)?.findByName('install') + if (installTask) { + bintrayUpload.dependsOn(installTask) + } else { + project.logger.warn "Configuration(s) specified but the install task does not exist in project {}.", + project.path + } + } + if (extension.publications?.length) { + def publicationExt = project.extensions.findByType(PublishingExtension) + if (!publicationExt) { + project.logger.warn "Publications(s) specified but no publications exist in project {}.", + project.path + } else { + extension.publications.each { + Publication publication = publicationExt?.publications?.findByName(it) + if (!publication) { + project.logger.warn 'Publication {} not found in project {}.', it, project.path + } else if (publication instanceof MavenPublication) { + def taskName = + "publish${it[0].toUpperCase()}${it.substring(1)}PublicationToMavenLocal" + bintrayUpload.dependsOn(taskName) + } else { + project.logger.warn "{} can only use maven publications - skipping {}.", + bintrayUpload.path, publication.name + } + } + } + } + + Task deployTask = project.getRootProject().getTasks().findByName(BintrayPublishTask.TASK_NAME) + if (deployTask == null) { + throw new IllegalStateException(String.format("Could not find %s in the root project", BintrayPublishTask.TASK_NAME)) + } + bintrayUpload.finalizedBy(deployTask) + // Depend on tasks in sub-projects + project.subprojects.each { + Task subTask = it.tasks.findByName(BintrayUploadTask.TASK_NAME) + if (subTask) { + bintrayUpload.dependsOn(subTask) + } + } + if (extension.filesSpec) { + bintrayUpload.dependsOn(extension.filesSpec) + } + } +} diff --git a/src/main/groovy/com/jfrog/bintray/gradle/tasks/BintrayPublishTask.groovy b/src/main/groovy/com/jfrog/bintray/gradle/tasks/BintrayPublishTask.groovy new file mode 100644 index 0000000..3d5d78b --- /dev/null +++ b/src/main/groovy/com/jfrog/bintray/gradle/tasks/BintrayPublishTask.groovy @@ -0,0 +1,102 @@ +package com.jfrog.bintray.gradle.tasks + +import com.jfrog.bintray.gradle.Utils +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +import org.gradle.api.tasks.TaskAction + +import static groovyx.net.http.ContentType.JSON +import static groovyx.net.http.Method.POST + +/** + * @author Alexei Vainshtein + * This task runs as final task after all other bintrayUpload tasks were executed. + * This task performs the signing, publishing and maven central sync + */ +class BintrayPublishTask extends DefaultTask { + static final String TASK_NAME = "bintrayPublish" + + @TaskAction + void taskAction() throws IOException { + signPublishAndSync() + } + + private void signPublishAndSync() { + HashSet tasks = project.getTasksByName(BintrayUploadTask.TASK_NAME, true) + for (BintrayUploadTask task : tasks) { + if (task.getEnabled()) { + if (task.getSignVersion()) { + gpgSignVersion(task.repoName, task.packageName, task.versionName, task) + } + if (task.publish) { + publishVersion(task.repoName, task.packageName, task.versionName, task) + } + if (task.shouldSyncToMavenCentral()) { + mavenCentralSync(task.repoName, task.packageName, task.versionName, task) + } + } + } + } + + private void gpgSignVersion(String repoName, String pkgName, String versionName, BintrayUploadTask task) { + def pkgPath = "$task.subject/$repoName/$pkgName" + if (task.dryRun) { + logger.info("(Dry run) Signed version '$pkgPath/$versionName'.") + return + } + task.getHttpBuilder().request(POST, JSON) { + Utils.addHeaders(headers) + uri.path = "/gpg/$pkgPath/versions/$versionName" + if (task.gpgPassphrase) { + body = [passphrase: task.gpgPassphrase] + } + response.success = { resp -> + logger.info("Signed version '$versionName'.") + } + response.failure = { resp, reader -> + throw new GradleException("Could not sign version '$versionName': $resp.statusLine $reader") + } + } + } + + private void publishVersion(String repoName, String pkgName, String versionName, BintrayUploadTask task) { + def pkgPath = "$task.subject/$repoName/$pkgName" + def publishUri = "/content/$pkgPath/$versionName/publish" + if (task.dryRun) { + logger.info("(Dry run) Published version '$pkgPath/$versionName'.") + return + } + task.getHttpBuilder().request(POST, JSON) { + Utils.addHeaders(headers) + uri.path = publishUri + response.success = { resp -> + logger.info("Published '$pkgPath/$versionName'.") + } + response.failure = { resp, reader -> + throw new GradleException("Could not publish '$pkgPath/$versionName': $resp.statusLine $reader") + } + } + } + + private void mavenCentralSync(String repoName, String pkgName, String versionName, BintrayUploadTask task) { + def pkgPath = "$task.subject/$repoName/$pkgName" + if (task.dryRun) { + logger.info("(Dry run) Sync to Maven Central performed for '$pkgPath/$versionName'.") + return + } + task.getHttpBuilder().request(POST, JSON) { + Utils.addHeaders(headers) + uri.path = "/maven_central_sync/$pkgPath/versions/$versionName" + body = [username: task.ossUser, password: task.ossPassword] + if (task.ossCloseRepo != null) { + body << [close: task.ossCloseRepo] + } + response.success = { resp -> + logger.info("Sync to Maven Central performed for '$pkgPath/$versionName'.") + } + response.failure = { resp, reader -> + throw new GradleException("Could not sync '$pkgPath/$versionName' to Maven Central: $resp.statusLine $reader") + } + } + } +} diff --git a/src/main/groovy/com/jfrog/bintray/gradle/tasks/BintrayUploadTask.groovy b/src/main/groovy/com/jfrog/bintray/gradle/tasks/BintrayUploadTask.groovy new file mode 100644 index 0000000..0856bb0 --- /dev/null +++ b/src/main/groovy/com/jfrog/bintray/gradle/tasks/BintrayUploadTask.groovy @@ -0,0 +1,596 @@ +package com.jfrog.bintray.gradle.tasks + +import com.jfrog.bintray.gradle.BintrayHttpClientFactory +import com.jfrog.bintray.gradle.BintrayPlugin +import com.jfrog.bintray.gradle.Utils +import com.jfrog.bintray.gradle.tasks.entities.Artifact +import com.jfrog.bintray.gradle.tasks.entities.Package +import com.jfrog.bintray.gradle.tasks.entities.Repository +import com.jfrog.bintray.gradle.tasks.entities.Version +import groovy.json.JsonBuilder +import groovyx.net.http.HTTPBuilder +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +import org.gradle.api.artifacts.Configuration +import org.gradle.api.file.CopySpec +import org.gradle.api.publish.Publication +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPublication +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.Upload +import java.util.concurrent.ConcurrentHashMap + +import static groovyx.net.http.ContentType.BINARY +import static groovyx.net.http.ContentType.JSON +import static groovyx.net.http.Method.* + +class BintrayUploadTask extends DefaultTask { + static final String TASK_NAME = 'bintrayUpload' + static final String GROUP = 'publishing' + static final String DESCRIPTION = 'Publishes artifacts to bintray.com.' + static final String API_URL_DEFAULT = 'https://api.bintray.com' + + private ConcurrentHashMap repositories = new ConcurrentHashMap<>() + private HTTPBuilder httpBuilder + + @Input + @Optional + String apiUrl + + @Input + @Optional + String user + + @Input + @Optional + String apiKey + + @Input + @Optional + Object[] configurations + + @Input + @Optional + Object[] publications + + @Input + @Optional + CopySpec filesSpec + + @Input + boolean publish + + @Input + boolean override + + @Input + boolean dryRun + + @Input + @Optional + String userOrg + + @Input + @Optional + String repoName + + @Input + @Optional + String packageName + + @Input + @Optional + String packageDesc + + @Input + @Optional + String packageWebsiteUrl + + @Input + @Optional + String packageIssueTrackerUrl + + @Input + @Optional + String packageVcsUrl + + @Input + @Optional + String packageGithubRepo + + @Input + @Optional + String packageGithubReleaseNotesFile + + @Input + @Optional + String[] packageLicenses + + @Input + @Optional + String[] packageLabels + + @Input + @Optional + Map packageAttributes + + @Input + @Optional + boolean packagePublicDownloadNumbers + + @Input + @Optional + String debianDistribution + + @Input + @Optional + String debianComponent + + @Input + @Optional + String debianArchitecture + + @Input + @Optional + String versionName + + @Input + @Optional + String versionDesc + + @Input + @Optional + String versionReleased + + @Input + @Optional + boolean signVersion + + @Input + @Optional + String gpgPassphrase + + @Input + @Optional + String versionVcsTag + + @Input + @Optional + Map versionAttributes + + @Input + @Optional + boolean syncToMavenCentral + + @Input + @Optional + String ossUser + + @Input + @Optional + String ossPassword + + @Input + @Optional + String ossCloseRepo + + Artifact[] configurationUploads + Artifact[] publicationUploads + Artifact[] fileUploads + { + group = GROUP + description = DESCRIPTION + } + + @TaskAction + void bintrayUpload() { + logger.info("Gradle Bintray Plugin version: ${new Utils().pluginVersion}"); + if (getEnabled()) { + validateDebianDefinition() + //TODO: [by yl] replace with findResults for Gradle 2.x + configurationUploads = configurations.collect { + if (it instanceof CharSequence) { + Configuration configuration = project.configurations.findByName(it) + if (configuration != null) { + return collectArtifacts(configuration) + } else { + logger.error("{}: Could not find configuration: {}.", path, it) + } + } else if (conf instanceof Configuration) { + return collectArtifacts((Configuration) it) + } else { + logger.error("{}: Unsupported configuration type: {}.", path, it.class) + } + [] + }.flatten() as Artifact[] + + publicationUploads = publications.collect { + if (it instanceof CharSequence) { + Publication publication = project.extensions.getByType(PublishingExtension).publications.findByName(it) + if (publication != null) { + return collectArtifacts(publication) + } else { + logger.error("{}: Could not find publication: {}.", path, it); + } + } else if (conf instanceof MavenPublication) { + return collectArtifacts((Configuration) it) + } else { + logger.error("{}: Unsupported publication type: {}.", path, it.class) + } + [] + }.flatten() as Artifact[] + + RecordingCopyTask recordingCopyTask = getDependsOn().find { it instanceof RecordingCopyTask } + fileUploads = (recordingCopyTask ? recordingCopyTask.fileUploads : []) as Artifact[] + + if (repoName == null || versionName == null || packageName == null) { + logger.warn("Repository name, package name or version name are null for project: " + project.getDisplayName()) + return + } + checkAndCreatePackage() + checkAndCreateVersion() + configurationUploads.each { + uploadArtifact(it) + } + publicationUploads.each { + uploadArtifact(it) + } + fileUploads.each { + uploadArtifact(it) + } + } else { + logger.debug("Gradle Bintray plugin is disabled for task: " + project.getName()) + } + } + + void checkAndCreatePackage() { + // Check if the package has already been created by another BintrayUploadTask. + Package pkg = checkPackageAlreadyCreated() + if (pkg && pkg.isCreated()) { + return + } + def create + getHttpBuilder().request(HEAD) { + Utils.addHeaders(headers) + uri.path = "/packages/$packagePath" + response.success = { resp -> + logger.debug("Package '$packageName' exists.") + } + response.'404' = { resp -> + logger.info("Package '$packageName' does not exist. Attempting to create it...") + create = true + } + } + if (create) { + if (dryRun) { + logger.info("(Dry run) Created package '$packagePath'.") + } else { + getHttpBuilder().request(POST, JSON) { + Utils.addHeaders(headers) + uri.path = "/packages/$subject/$repoName" + body = [name : packageName, desc: packageDesc, + licenses : packageLicenses, + labels : packageLabels, + website_url : packageWebsiteUrl, + issue_tracker_url : packageIssueTrackerUrl, + vcs_url : packageVcsUrl, + public_download_numbers : packagePublicDownloadNumbers, + github_repo : packageGithubRepo, + github_release_notes_file: packageGithubReleaseNotesFile] + + response.success = { resp -> + logger.info("Created package '$packagePath'.") + } + response.failure = { resp, reader -> + throw new GradleException("Could not create package '$packagePath': $resp.statusLine $reader") + } + } + if (packageAttributes) { + setAttributes "/packages/$packagePath/attributes", packageAttributes, 'package', packageName + } + } + } + setPackageAsCreated(pkg) + } + + void checkAndCreateVersion() { + // Check if the version has already been created by another BintrayUploadTask. + if (versionName == null) { + return + } + Version version = checkVersionAlreadyCreated() + if (version && version.isCreated()) { + return + } + def create + getHttpBuilder().request(HEAD) { + Utils.addHeaders(headers) + uri.path = "/packages/$packagePath/versions/$versionName" + response.success = { resp -> + logger.debug("Version '$packagePath/$versionName' exists.") + } + response.'404' = { resp -> + logger.info("Version '$packagePath/$versionName' does not exist. Attempting to create it...") + create = true + } + } + if (create) { + if (dryRun) { + logger.info("(Dry run) Created version '$packagePath/$versionName'.") + } else { + getHttpBuilder().request(POST, JSON) { + Utils.addHeaders(headers) + uri.path = "/packages/$packagePath/versions" + versionReleased = Utils.toIsoDateFormat(versionReleased) + body = [name: versionName, desc: versionDesc, released: versionReleased, vcs_tag: versionVcsTag] + response.success = { resp -> + logger.info("Created version '$versionName'.") + } + response.failure = { resp, reader -> + throw new GradleException("Could not create version '$versionName': $resp.statusLine $reader") + } + } + if (versionAttributes) { + setAttributes "/packages/$packagePath/versions/$versionName/attributes", versionAttributes, + 'version', versionName + } + } + } + setVersionAsCreated(version) + } + + void validateDebianDefinition() { + if ((debianDistribution && !debianArchitecture) || + (!debianDistribution && debianArchitecture)) { + throw new GradleException("Both 'distribution' and 'architecture' are mandatory in the gradle.debian closure.") + } + } + + void setAttributes(String attributesPath, Map attributes, String entity, String entityName) { + getHttpBuilder().request(POST, JSON) { + Utils.addHeaders(headers) + uri.path = attributesPath + def builder = new JsonBuilder() + builder.content = attributes.collect { + //Support both arrays and singular values - coerce to an array of values + ['name': it.key, 'values': [it.value].flatten()] + } + body = builder.toString() + response.success = { resp -> + logger.info("Attributes set on $entity '$entityName'.") + } + response.failure = { resp, reader -> + throw new GradleException( + "Could not set attributes on $entity '$entityName': $resp.statusLine $reader") + } + } + } + + void addUploadHeaders(Map headers) { + Utils.addHeaders(headers) + if (debianDistribution) { + String component = debianComponent ? debianComponent : "main" + headers.put("X-Bintray-Debian-Distribution", debianDistribution) + headers.put("X-Bintray-Debian-Component", component) + headers.put("X-Bintray-Debian-Architecture", debianArchitecture) + } + } + + Package checkPackageAlreadyCreated() { + Package pkg = new Package(packageName) + Package p = getRepository().packages.putIfAbsent(packageName, pkg) + if (p && !p.created) { + synchronized (p) { + if (!p.created) { + p.wait() + } + } + } + return p ? p : pkg + } + + Version checkVersionAlreadyCreated() { + Package pkg = getRepository().packages.get(packageName) + if (!pkg) { + throw new IllegalStateException( + "Attempted checking and creating version, before checking and creating the package.") + } + Version v = new Version( + versionName, signVersion, gpgPassphrase, publish, shouldSyncToMavenCentral()) + Version version = pkg.addVersionIfAbsent(v) + if (version && !version.created) { + synchronized (version) { + if (!version.created) { + version.wait() + } + } + } + return version ? version : v + } + + void setPackageAsCreated(Package pkg) { + pkg.setAsCreated() + synchronized (pkg) { + pkg.notifyAll() + } + } + + void setVersionAsCreated(Version version) { + version.setAsCreated() + synchronized (version) { + version.notifyAll() + } + } + + void uploadArtifact(Artifact artifact) { + def versionPath = packagePath + '/' + versionName ?: artifact.version + def uploadUri = "/content/$versionPath/${artifact.path}" + + if (!artifact.file.exists()) { + logger.error("Skipping upload for missing file '$artifact.file'.") + return + } + artifact.file.withInputStream { is -> + is.metaClass.totalBytes = { + artifact.file.length() + } + logger.warn("Uploading to $apiUrl$uploadUri...") + if (dryRun) { + logger.info("(Dry run) Uploaded to '$apiUrl$uploadUri'.") + return + } + getHttpBuilder().request(PUT) { + if (override) { + uri.query = [override: "1"] + } + addUploadHeaders(headers) + // Set the requestContentType to BINARY, so that HTTPBuilder can encode the uploaded file: + requestContentType = BINARY + // Set the Content-Type to '*/*' to enable Bintray to set it on its own: + headers["Content-Type"] = '*/*' + uri.path = uploadUri + body = is + response.success = { resp -> + logger.warn("Uploaded to '$apiUrl$uri.path'.") + } + response.failure = { resp, reader -> + throw new GradleException("Could not upload to '$apiUrl$uri.path': $resp.statusLine $reader") + } + } + } + } + + boolean shouldSyncToMavenCentral() { + syncToMavenCentral && ossUser != null && ossPassword != null + } + + Artifact[] collectArtifacts(Configuration config) { + // First lets check if there is a pom inside. + String artifactId + ArrayList artifacts = new ArrayList<>() + boolean pomArtifact = config.allArtifacts.findResults { + if (!it.file.exists()) { + logger.error("{}: file {} could not be found.", path, it.file.getAbsolutePath()) + return null + } + if (it.type == 'pom') { + return true + } + } + if (!pomArtifact) { + // Add pom file per config + Upload installTask = project.tasks.withType(Upload).findByName('install'); + if (!installTask) { + logger.info "maven plugin was not applied, no pom will be uploaded." + } else { + File pom = new File(getProject().convention.plugins['maven'].mavenPomDir, "pom-default.xml") + if (pom.exists()) { + artifactId = Utils.readArtifactIdFromPom(pom) + artifacts << new Artifact( + name: artifactId, + groupId: project.group, + version: project.version, + extension: 'pom', + type: 'pom', + file: pom + ) + } else { + logger.debug("Pom file " + pom.getAbsolutePath() + " doesn't exists.") + } + } + } + config.allArtifacts.findResults { + if (!it.file.exists()) { + logger.error("{}: file {} could not be found.", path, it.file.getAbsolutePath()) + return null + } + boolean signedArtifact = (it instanceof org.gradle.plugins.signing.Signature) + def signedExtension = signedArtifact ? it.toSignArtifact.getExtension() : null + String name = artifactId == null ? it.name : artifactId + artifacts << new Artifact( + name: name, groupId: project.group, version: project.version, extension: it.extension, + type: it.type, classifier: it.classifier, file: it.file, signedExtension: signedExtension + ) + }.unique() + + artifacts + } + + + HTTPBuilder getHttpBuilder() { + if (httpBuilder == null) { + httpBuilder = BintrayHttpClientFactory.create(apiUrl, user, apiKey) + } + return httpBuilder + } + + String getSubject() { + "${userOrg ?: user}" + } + + String getPackagePath() { + "$subject/$repoName/$packageName" + } + + Artifact[] collectArtifacts(Publication publication) { + if (!publication instanceof MavenPublication) { + logger.info "{} can only use maven publications - skipping {}.", path, publication.name + return [] + } + def artifacts = publication.artifacts.findResults { + boolean signedArtifact = (it instanceof org.gradle.plugins.signing.Signature) + def signedExtension = signedArtifact ? it.toSignArtifact.getExtension() : null + new Artifact( + name: publication.artifactId, + groupId: publication.groupId, + version: publication.version, + extension: it.extension, + type: it.extension, + classifier: it.classifier, + file: it.file, + signedExtension: signedExtension + ) + } + + // Add the pom file + artifacts << new Artifact( + name: publication.artifactId, + groupId: publication.groupId, + version: publication.version, + extension: 'pom', + type: 'pom', + file: publication.asNormalisedPublication().pomFile + ) + artifacts + } + + public ConcurrentHashMap getCachedRepositories() { + BintrayUploadTask t = ((BintrayUploadTask) project.rootProject.tasks.findByName(TASK_NAME)) + if (t == null) { + project.rootProject.getPluginManager().apply(BintrayPlugin.class) + t = ((BintrayUploadTask) project.rootProject.tasks.findByName(TASK_NAME)) + } + if (t == null) { + throw new RuntimeException("Could not find $TASK_NAME task in root project") + } + t.getRepositories() + } + + public ConcurrentHashMap getRepositories() { + if (this.project != this.project.rootProject) { + throw new IllegalStateException("The getRepositories method can be invoked on the root project$TASK_NAME task only") + } + return repositories + } + + private Repository getRepository() { + Repository repository = new Repository(repoName) + Repository r = getCachedRepositories().putIfAbsent(repoName, repository) + if (!r) { + return repository + } + return r + } +} diff --git a/src/main/groovy/com/jfrog/bintray/gradle/RecordingCopyTask.groovy b/src/main/groovy/com/jfrog/bintray/gradle/tasks/RecordingCopyTask.groovy similarity index 93% rename from src/main/groovy/com/jfrog/bintray/gradle/RecordingCopyTask.groovy rename to src/main/groovy/com/jfrog/bintray/gradle/tasks/RecordingCopyTask.groovy index ceba601..c3bf28a 100644 --- a/src/main/groovy/com/jfrog/bintray/gradle/RecordingCopyTask.groovy +++ b/src/main/groovy/com/jfrog/bintray/gradle/tasks/RecordingCopyTask.groovy @@ -1,5 +1,6 @@ -package com.jfrog.bintray.gradle +package com.jfrog.bintray.gradle.tasks +import com.jfrog.bintray.gradle.tasks.entities.Artifact import org.gradle.api.internal.file.copy.CopyAction import org.gradle.api.internal.file.copy.CopyActionProcessingStream import org.gradle.api.internal.file.copy.FileCopyDetailsInternal diff --git a/src/main/groovy/com/jfrog/bintray/gradle/Artifact.groovy b/src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Artifact.groovy similarity index 97% rename from src/main/groovy/com/jfrog/bintray/gradle/Artifact.groovy rename to src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Artifact.groovy index d00a1de..6c3c955 100644 --- a/src/main/groovy/com/jfrog/bintray/gradle/Artifact.groovy +++ b/src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Artifact.groovy @@ -1,4 +1,4 @@ -package com.jfrog.bintray.gradle +package com.jfrog.bintray.gradle.tasks.entities class Artifact { String name diff --git a/src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Package.groovy b/src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Package.groovy new file mode 100644 index 0000000..53ee725 --- /dev/null +++ b/src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Package.groovy @@ -0,0 +1,43 @@ +package com.jfrog.bintray.gradle.tasks.entities + +import java.util.concurrent.ConcurrentHashMap + +class Package { + private String name + private boolean created + private ConcurrentHashMap versions = new ConcurrentHashMap() + + Package(String name) { + this.name = name + } + + boolean isCreated() { + return created + } + + void setAsCreated() { + this.created = true + } + + public Version addVersionIfAbsent(Version version) { + Version v = versions.putIfAbsent(version.name, version) + if (v) { + v.merge(version) + } + return v + } + + boolean equals(o) { + if (this.is(o)) { + return true + } + if (getClass() != o.class || name != ((Package) o).name) { + return false + } + return true + } + + int hashCode() { + name != null ? name.hashCode() : 0 + } +} \ No newline at end of file diff --git a/src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Repository.groovy b/src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Repository.groovy new file mode 100644 index 0000000..3ad4959 --- /dev/null +++ b/src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Repository.groovy @@ -0,0 +1,26 @@ +package com.jfrog.bintray.gradle.tasks.entities + +import java.util.concurrent.ConcurrentHashMap + +class Repository { + private String name + private ConcurrentHashMap packages = new ConcurrentHashMap() + + Repository(String name) { + this.name = name + } + + boolean equals(o) { + if (this.is(o)) { + return true + } + if (getClass() != o.class || name != ((Repository) o).name) { + return false + } + return true + } + + int hashCode() { + name != null ? name.hashCode() : 0 + } +} diff --git a/src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Version.groovy b/src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Version.groovy new file mode 100644 index 0000000..ed5f063 --- /dev/null +++ b/src/main/groovy/com/jfrog/bintray/gradle/tasks/entities/Version.groovy @@ -0,0 +1,65 @@ +package com.jfrog.bintray.gradle.tasks.entities + +class Version { + private String name + private boolean created + private boolean gpgSign + private String gpgPassphrase + private boolean publish + private boolean mavenCentralSync + + Version(String name, boolean gpgSign, String gpgPassphrase, boolean publish, boolean mavenCentralSync) { + this.name = name + this.gpgSign = gpgSign + this.gpgPassphrase = gpgPassphrase + this.publish = publish + this.mavenCentralSync = mavenCentralSync + } + + boolean isCreated() { + return created + } + + void setAsCreated() { + this.created = true + } + + boolean isGpgSign() { + return gpgSign + } + + String getGpgPassphrase() { + return gpgPassphrase + } + + boolean isPublish() { + return publish + } + + boolean isMavenCentralSync() { + return mavenCentralSync + } + + void merge(Version version) { + if (version) { + this.gpgSign = this.gpgSign || version.gpgSign + this.publish = this.publish || version.publish + this.mavenCentralSync = this.mavenCentralSync || version.mavenCentralSync + this.gpgPassphrase = gpgPassphrase ?: this.gpgPassphrase + } + } + + boolean equals(o) { + if (this.is(o)) { + return true + } + if (getClass() != o.class || name != ((Version) o).name) { + return false + } + return true + } + + int hashCode() { + name != null ? name.hashCode() : 0 + } +} \ No newline at end of file diff --git a/src/test/groovy/com/jfrog/bintray/gradle/GradleBintrayPluginSpec.groovy b/src/test/groovy/com/jfrog/bintray/gradle/GradleBintrayPluginSpec.groovy index 67170b9..4cf6060 100644 --- a/src/test/groovy/com/jfrog/bintray/gradle/GradleBintrayPluginSpec.groovy +++ b/src/test/groovy/com/jfrog/bintray/gradle/GradleBintrayPluginSpec.groovy @@ -49,20 +49,21 @@ class GradleBintrayPluginSpec extends Specification { } def cleanupRepo(String repoName) { + String bintraySubject = getSubject() for (String v : versions) { - if (bintray.subject(config.bintrayOrg).repository(repoName) + if (bintray.subject(bintraySubject).repository(repoName) .pkg(config.pkgName).version(v).exists()) { - bintray.subject(config.bintrayOrg).repository(repoName) + bintray.subject(bintraySubject).repository(repoName) .pkg(config.pkgName).version(v).delete() } } - boolean pkgExists = bintray.subject(config.bintrayOrg).repository(repoName) + boolean pkgExists = bintray.subject(bintraySubject).repository(repoName) .pkg(config.pkgName).exists() if (pkgExists) { // Delete the package: - bintray.subject(config.bintrayOrg).repository(repoName) + bintray.subject(bintraySubject).repository(repoName) .pkg(config.pkgName).delete() } } @@ -78,17 +79,12 @@ class GradleBintrayPluginSpec extends Specification { // Gradle build finished successfully: exitCode == 0 - // Package was created: - bintray.subject(config.bintrayOrg).repository(config.debianRepo) - .pkg(config.pkgName).exists() - - // Version was created: - bintray.subject(config.bintrayOrg).repository(config.debianRepo) - .pkg(config.pkgName).version(version).exists() + String bintraySubject = getSubject() + checkExistence(bintraySubject, config.debianRepo as String, config.pkgName as String, version) when: // Get the created package: - Pkg pkg = bintray.subject(config.bintrayOrg).repository(config.debianRepo) + Pkg pkg = bintray.subject(bintraySubject).repository(config.debianRepo) .pkg(config.pkgName).get() then: @@ -108,17 +104,12 @@ class GradleBintrayPluginSpec extends Specification { // Gradle build finished successfully: exitCode == 0 - // Package was created: - bintray.subject(config.bintrayOrg).repository(config.mavenRepo) - .pkg(config.pkgName).exists() - - // Version was created: - bintray.subject(config.bintrayOrg).repository(config.mavenRepo) - .pkg(config.pkgName).version(version).exists() + String bintraySubject = getSubject() + checkExistence(bintraySubject, config.mavenRepo as String, config.pkgName as String, version) when: // Get the created package: - Pkg pkg = bintray.subject(config.bintrayOrg).repository(config.mavenRepo) + Pkg pkg = bintray.subject(bintraySubject).repository(config.mavenRepo) .pkg(config.pkgName).get() then: @@ -138,17 +129,62 @@ class GradleBintrayPluginSpec extends Specification { // Gradle build finished successfully: exitCode == 0 - // Package was created: - bintray.subject(config.bintrayOrg).repository(config.mavenRepo) - .pkg(config.pkgName).exists() + String bintraySubject = getSubject() + checkExistence(bintraySubject, config.mavenRepo as String, config.pkgName as String, version) - // Version was created: - bintray.subject(config.bintrayOrg).repository(config.mavenRepo) - .pkg(config.pkgName).version(version).exists() + when: + // Get the created package: + Pkg pkg = bintray.subject(bintraySubject).repository(config.mavenRepo) + .pkg(config.pkgName).get() + + then: + pkg.name() == config.pkgName + pkg.description() == config.pkgDesc + pkg.labels().sort() == config.pkgLabels.sort() + } + + def "[configurationWithSubModules]create package and version with configuration"() { + when: + String version = PluginSpecUtils.createVersion() + versions.add(version) + String[] tasks = ["clean", "install", "bintrayUpload"] + def exitCode = PluginSpecUtils.launchGradle(testName.methodName + " without username", tasks, version) + + then: + // Gradle build finished with error: + exitCode != 0 + when: + version = PluginSpecUtils.createVersion() + versions.add(version) + tasks = ["clean", "install", "bintrayUpload"] + exitCode = PluginSpecUtils.launchGradle(testName.methodName, tasks, version) + + then: + // Gradle build finished successfully: + exitCode == 0 + + String bintraySubject = getSubject() + checkExistence(bintraySubject, config.mavenRepo as String, config.pkgName as String, version) + + // Check that the jar file was uploaded with the right artifactId + HTTPBuilder httpBuilder = BintrayHttpClientFactory.create("https://dl.bintray.com/", config.bintrayUser, config.bintrayKey) + String path = "/$bintraySubject/${config.mavenRepo}/bintray/gradle/test/android-maven-example/0.1/android-maven-example-0.1.jar" + + def response = httpBuilder.request(HEAD) { + Utils.addHeaders(headers) + uri.path = path + response.success = { resp -> + return resp + } + response.failure = { resp -> + return resp + } + } + response.status == 200 when: // Get the created package: - Pkg pkg = bintray.subject(config.bintrayOrg).repository(config.mavenRepo) + Pkg pkg = bintray.subject(bintraySubject).repository(config.mavenRepo) .pkg(config.pkgName).get() then: @@ -169,17 +205,12 @@ class GradleBintrayPluginSpec extends Specification { // Gradle build finished successfully: exitCode == 0 - // Package was created: - bintray.subject(config.bintrayOrg).repository(config.mavenRepo) - .pkg(config.pkgName).exists() - - // Version was created: - bintray.subject(config.bintrayOrg).repository(config.mavenRepo) - .pkg(config.pkgName).version(version).exists() + String bintraySubject = getSubject() + checkExistence(bintraySubject, config.mavenRepo as String, config.pkgName as String, version) when: // Get the created package: - Pkg pkg = bintray.subject(config.bintrayOrg).repository(config.mavenRepo) + Pkg pkg = bintray.subject(bintraySubject).repository(config.mavenRepo) .pkg(config.pkgName).get() then: @@ -225,17 +256,18 @@ class GradleBintrayPluginSpec extends Specification { // therefore the following path should exist on Bintray. expect: - fileExistsOnBintray(config.bintrayOrg as String, config.debianRepo as String, + String bintraySubject = getSubject() + fileExistsOnBintray(bintraySubject, config.debianRepo as String, '/dists/squeeze/main/binary-amd64/Packages') } - private boolean fileExistsOnBintray(String org, String repo, String path) { + private boolean fileExistsOnBintray(String bintraySubject, String repo, String path) { HTTPBuilder http = BintrayHttpClientFactory.create('https://dl.bintray.com', config.bintrayUser, config.bintrayKey) boolean exists http.request(HEAD) { Utils.addHeaders(headers) - uri.path = "/$org/$repo/$path" + uri.path = "/$bintraySubject/$repo/$path" response.success = { resp -> exists = true } @@ -249,4 +281,23 @@ class GradleBintrayPluginSpec extends Specification { } return exists } + + private String getSubject() { + return config.bintrayOrg ?: config.bintrayUser + } + + private boolean checkExistence(String bintraySubject, String repo, String pkgName, String version) { + // Package was created: + if (!bintray.subject(bintraySubject).repository(repo) + .pkg(pkgName).exists()) { + return false + } + + // Version was created: + if (!bintray.subject(bintraySubject).repository(repo) + .pkg(pkgName).version(version).exists()) { + return false + } + return true + } } \ No newline at end of file diff --git a/src/test/groovy/com/jfrog/bintray/gradle/PluginSpecUtils.groovy b/src/test/groovy/com/jfrog/bintray/gradle/PluginSpecUtils.groovy index 7fe4cb5..01d3a9f 100644 --- a/src/test/groovy/com/jfrog/bintray/gradle/PluginSpecUtils.groovy +++ b/src/test/groovy/com/jfrog/bintray/gradle/PluginSpecUtils.groovy @@ -46,8 +46,6 @@ class PluginSpecUtils { .addEnvVar("debianRepoName", config.debianRepo) .addEnvVar("pkgName", config.pkgName) .addEnvVar("pkgDesc", config.pkgDesc) - .addEnvVar("mavenCentralUser", config.mavenCentralUser) - .addEnvVar("mavenCentralPassword", config.mavenCentralPassword) .addSwitch("info") .addSwitch("stacktrace") diff --git a/src/test/groovy/com/jfrog/bintray/gradle/TestsConfig.groovy b/src/test/groovy/com/jfrog/bintray/gradle/TestsConfig.groovy index f1efb0a..a7c0995 100644 --- a/src/test/groovy/com/jfrog/bintray/gradle/TestsConfig.groovy +++ b/src/test/groovy/com/jfrog/bintray/gradle/TestsConfig.groovy @@ -16,13 +16,9 @@ class TestsConfig { private TestsConfig() { config = new ConfigSlurper().parse(this.class.getResource('/gradle/config.groovy')).conf - config.bintrayUser = readValue('Bintray user name', 'BINTRAY_USER', 'bintrayUser') - config.bintrayKey = readValue('Bintray API key', 'BINTRAY_KEY', 'bintrayKey') - config.bintrayOrg = readValue('Bintray organization', 'BINTRAY_ORG', 'bintrayOrg') - config.bintrayAdminUser = readValue('Bintray admin user name (used for linking the package to JCenter)', 'BINTRAY_ADMIN_USER', 'bintrayAdminUser') - config.bintrayAdminKey = readValue('Bintray admin API key (used for linking the package to JCenter)', 'BINTRAY_ADMIN_KEY', 'bintrayAdminKey') - config.mavenCentralUser = readValue('Maven Central user', 'MAVEN_CENTRAL_USER', 'mavenCentralUser') - config.mavenCentralPassword = readValue('Maven Central password', 'MAVEN_CENTRAL_PASSWORD', 'mavenCentralPassword') + config.bintrayUser = readValue('Bintray user name', 'BINTRAY_USER', 'bintrayUser', true) + config.bintrayKey = readValue('Bintray API key', 'BINTRAY_KEY', 'bintrayKey', true) + config.bintrayOrg = readValue('Bintray organization', 'BINTRAY_ORG', 'bintrayOrg', false) def bintrayApiUrl = getenv('BINTRAY_API_URL') if (!bintrayApiUrl) { @@ -49,12 +45,12 @@ class TestsConfig { } } - private String readValue(String displayName, String envVarName, String sysPropName) { + private String readValue(String displayName, String envVarName, String sysPropName, boolean mandatory) { String value = getenv(envVarName) if (!value) { value = System.getProperty(sysPropName) } - if (!value) { + if (!value && mandatory) { throwMissingConfProp(displayName, envVarName, sysPropName) } value diff --git a/src/test/resources/gradle/buildFiles/create_debian_package_and_version_with_fileSpec.gradle b/src/test/resources/gradle/buildFiles/create_debian_package_and_version_with_fileSpec.gradle index 2ad2139..45fe60c 100644 --- a/src/test/resources/gradle/buildFiles/create_debian_package_and_version_with_fileSpec.gradle +++ b/src/test/resources/gradle/buildFiles/create_debian_package_and_version_with_fileSpec.gradle @@ -18,17 +18,21 @@ bintray { component = 'main' architecture = 'i386,noarch,amd64' } - userOrg = bintrayOrg - desc = pkgDesc + if (!isNull(bintrayOrg)) { + userOrg = bintrayOrg + } + desc = pkgDesc labels = pkgLabels licenses = ['Apache-2.0'] websiteUrl = 'https://github.com/bintray/gradle-bintray-plugin' issueTrackerUrl = 'https://github.com/bintray/gradle-bintray-plugin/issues' vcsUrl = 'https://github.com/bintray/gradle-bintray-plugin.git' - githubRepo = 'bintray/gradle-bintray-plugin' - githubReleaseNotesFile = 'README.md' version { name = versionName } } +} + +boolean isNull(String value) { + return value == null || value == "" || value == 'null' } \ No newline at end of file diff --git a/src/test/resources/gradle/buildFiles/create_package_and_version_with_configuration.gradle b/src/test/resources/gradle/buildFiles/create_package_and_version_with_configuration.gradle index 6ad3365..79aa32c 100644 --- a/src/test/resources/gradle/buildFiles/create_package_and_version_with_configuration.gradle +++ b/src/test/resources/gradle/buildFiles/create_package_and_version_with_configuration.gradle @@ -9,17 +9,21 @@ bintray { pkg { repo = mavenRepoName name = pkgName - userOrg = bintrayOrg - desc = pkgDesc + if (!isNull(bintrayOrg)) { + userOrg = bintrayOrg + } + desc = pkgDesc labels = pkgLabels licenses = ['Apache-2.0'] websiteUrl = 'https://github.com/bintray/gradle-bintray-plugin' issueTrackerUrl = 'https://github.com/bintray/gradle-bintray-plugin/issues' vcsUrl = 'https://github.com/bintray/gradle-bintray-plugin.git' - githubRepo = 'bintray/gradle-bintray-plugin' - githubReleaseNotesFile = 'README.md' version { name = versionName } } +} + +boolean isNull(String value) { + return value == null || value == "" || value == 'null' } \ No newline at end of file diff --git a/src/test/resources/gradle/buildFiles/create_package_and_version_with_configuration_without_username.gradle b/src/test/resources/gradle/buildFiles/create_package_and_version_with_configuration_without_username.gradle new file mode 100644 index 0000000..94a8eca --- /dev/null +++ b/src/test/resources/gradle/buildFiles/create_package_and_version_with_configuration_without_username.gradle @@ -0,0 +1,27 @@ +def pkgLabels = [label1, label2, label3] + +bintray { + apiUrl = bintrayApiUrl + configurations = ['archives'] + publish = true + pkg { + repo = mavenRepoName + name = pkgName + if (!isNull(bintrayOrg)) { + userOrg = bintrayOrg + } + desc = pkgDesc + labels = pkgLabels + licenses = ['Apache-2.0'] + websiteUrl = 'https://github.com/bintray/gradle-bintray-plugin' + issueTrackerUrl = 'https://github.com/bintray/gradle-bintray-plugin/issues' + vcsUrl = 'https://github.com/bintray/gradle-bintray-plugin.git' + version { + name = versionName + } + } +} + +boolean isNull(String value) { + return value == null || value == "" || value == 'null' +} \ No newline at end of file diff --git a/src/test/resources/gradle/buildFiles/create_package_and_version_with_fileSpec.gradle b/src/test/resources/gradle/buildFiles/create_package_and_version_with_fileSpec.gradle index 1a49fa5..7d29aeb 100644 --- a/src/test/resources/gradle/buildFiles/create_package_and_version_with_fileSpec.gradle +++ b/src/test/resources/gradle/buildFiles/create_package_and_version_with_fileSpec.gradle @@ -12,17 +12,21 @@ bintray { pkg { repo = mavenRepoName name = pkgName - userOrg = bintrayOrg - desc = pkgDesc + if (!isNull(bintrayOrg)) { + userOrg = bintrayOrg + } + desc = pkgDesc labels = pkgLabels licenses = ['Apache-2.0'] websiteUrl = 'https://github.com/bintray/gradle-bintray-plugin' issueTrackerUrl = 'https://github.com/bintray/gradle-bintray-plugin/issues' vcsUrl = 'https://github.com/bintray/gradle-bintray-plugin.git' - githubRepo = 'bintray/gradle-bintray-plugin' - githubReleaseNotesFile = 'README.md' version { name = versionName } } +} + +boolean isNull(String value) { + return value == null || value == "" || value == 'null' } \ No newline at end of file diff --git a/src/test/resources/gradle/buildFiles/create_package_and_version_with_publication.gradle b/src/test/resources/gradle/buildFiles/create_package_and_version_with_publication.gradle index cbe9d91..cc443a6 100644 --- a/src/test/resources/gradle/buildFiles/create_package_and_version_with_publication.gradle +++ b/src/test/resources/gradle/buildFiles/create_package_and_version_with_publication.gradle @@ -9,15 +9,15 @@ bintray { pkg { repo = mavenRepoName name = pkgName - userOrg = bintrayOrg - desc = pkgDesc + if (!isNull(bintrayOrg)) { + userOrg = bintrayOrg + } + desc = pkgDesc labels = pkgLabels licenses = ['Apache-2.0'] websiteUrl = 'https://github.com/bintray/gradle-bintray-plugin' issueTrackerUrl = 'https://github.com/bintray/gradle-bintray-plugin/issues' vcsUrl = 'https://github.com/bintray/gradle-bintray-plugin.git' - githubRepo = 'bintray/gradle-bintray-plugin' - githubReleaseNotesFile = 'README.md' version { name = versionName gpg { @@ -25,4 +25,8 @@ bintray { } } } +} + +boolean isNull(String value) { + return value == null || value == "" || value == 'null' } \ No newline at end of file diff --git a/src/test/resources/gradle/buildFiles/maven_central_sync.gradle b/src/test/resources/gradle/buildFiles/maven_central_sync.gradle deleted file mode 100644 index 3edb09c..0000000 --- a/src/test/resources/gradle/buildFiles/maven_central_sync.gradle +++ /dev/null @@ -1,20 +0,0 @@ -bintray { - apiUrl = bintrayApiUrl - user = bintrayUser - key = bintrayKey - pkg { - repo = mavenRepoName - name = pkgName - userOrg = bintrayOrg - vcsUrl = 'https://github.com/bintray/gradle-bintray-plugin.git' - version { - name = versionName - mavenCentralSync { - sync = true - user = mavenCentralUser - password = mavenCentralPassword - close = '1' - } - } - } -} \ No newline at end of file diff --git a/src/test/resources/gradle/buildFiles/override.gradle b/src/test/resources/gradle/buildFiles/override.gradle index 014180f..0ba9fd6 100644 --- a/src/test/resources/gradle/buildFiles/override.gradle +++ b/src/test/resources/gradle/buildFiles/override.gradle @@ -12,12 +12,18 @@ bintray { pkg { repo = mavenRepoName name = pkgName - userOrg = bintrayOrg - desc = pkgDesc + if (!isNull(bintrayOrg)) { + userOrg = bintrayOrg + } + desc = pkgDesc vcsUrl = 'https://github.com/bintray/gradle-bintray-plugin.git' licenses = ['Apache-2.0'] version { name = versionName } } +} + +boolean isNull(String value) { + return value == null || value == "" || value == 'null' } \ No newline at end of file diff --git a/src/test/resources/gradle/projects/configurationWithSubModules/api/build.gradle b/src/test/resources/gradle/projects/configurationWithSubModules/api/build.gradle new file mode 100644 index 0000000..cfad2a0 --- /dev/null +++ b/src/test/resources/gradle/projects/configurationWithSubModules/api/build.gradle @@ -0,0 +1,49 @@ +group = 'bintray.gradle.test' +version = '0.1' + +dependencies { + compile(group: 'commons-lang', name: 'commons-lang', version: '2.4') + compile group: 'org.apache.wicket', name: 'wicket', version: '1.3.7' +} + +install { + repositories.mavenInstaller { + pom.project { + name 'Bintray test' + description 'A test for the Bintray Gradle plugin' + url 'https://github.com/bintray/bintray-examples' + inceptionYear '2015' + + packaging 'aar' + groupId 'bintray.gradle.test' + artifactId 'android-maven-example' + version '0.1' + + licenses { + license { + name 'The Apache Software License, Version 2.0' + url 'http://www.apache.org/licenses/LICENSE-2.0.txt' + distribution 'repo' + } + } + scm { + connection 'https://github.com/bintray/bintray-examples.git' + url 'https://github.com/bintray/bintray-examples' + + } + } + } +} + +def rootProjectDir = projectDir +def testsDir = new File(rootProjectDir.getParentFile().getParentFile().getParentFile(), 'buildFiles') + +def getTestFile = { fileName -> + testsDir.toString() + '/' + fileName +} + +apply from: getTestFile("${testName}.gradle") + +task wrapper(type: Wrapper) { + gradleVersion = '2.4' +} \ No newline at end of file diff --git a/src/test/resources/gradle/projects/configurationWithSubModules/api/src/main/java/org/gradle/api/PersonList.java b/src/test/resources/gradle/projects/configurationWithSubModules/api/src/main/java/org/gradle/api/PersonList.java new file mode 100644 index 0000000..3d859a9 --- /dev/null +++ b/src/test/resources/gradle/projects/configurationWithSubModules/api/src/main/java/org/gradle/api/PersonList.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2011 JFrog Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api; + +import org.gradle.apiImpl.Impl; + +import java.util.ArrayList; + + +public class PersonList { + private ArrayList persons = new ArrayList(); + + public void doSomethingWithImpl() { + org.apache.commons.lang.builder.ToStringBuilder stringBuilder; + try { + Class.forName("org.apache.commons.io.FileUtils"); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + new Impl().implMethod(); + } + +} diff --git a/src/test/resources/gradle/projects/configurationWithSubModules/api/src/main/java/org/gradle/api/package.html b/src/test/resources/gradle/projects/configurationWithSubModules/api/src/main/java/org/gradle/api/package.html new file mode 100644 index 0000000..cea998a --- /dev/null +++ b/src/test/resources/gradle/projects/configurationWithSubModules/api/src/main/java/org/gradle/api/package.html @@ -0,0 +1,19 @@ + + + +

These are the API classes

+ diff --git a/src/test/resources/gradle/projects/configurationWithSubModules/api/src/main/java/org/gradle/apiImpl/Impl.java b/src/test/resources/gradle/projects/configurationWithSubModules/api/src/main/java/org/gradle/apiImpl/Impl.java new file mode 100644 index 0000000..a6e651d --- /dev/null +++ b/src/test/resources/gradle/projects/configurationWithSubModules/api/src/main/java/org/gradle/apiImpl/Impl.java @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2011 JFrog Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.apiImpl; + + +public class Impl { + + public void implMethod() { + double a = 4.0 * 4; + } +} diff --git a/src/test/resources/gradle/projects/configurationWithSubModules/build.gradle b/src/test/resources/gradle/projects/configurationWithSubModules/build.gradle new file mode 100644 index 0000000..9aa496f --- /dev/null +++ b/src/test/resources/gradle/projects/configurationWithSubModules/build.gradle @@ -0,0 +1,34 @@ +buildscript { + repositories { + mavenLocal() + jcenter() + } + dependencies { + classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.1-SNAPSHOT" + } +} + +def rootProjectDir = projectDir +def testsDir = new File(rootProjectDir.getParentFile().getParentFile(), 'buildFiles') + +def getTestFile = { fileName -> + testsDir.toString() + '/' + fileName +} + +group = pkgName +version = versionName + +allprojects { + repositories { + jcenter() + } + apply plugin: 'java' + apply plugin: 'maven' + apply plugin: 'com.jfrog.bintray' +} + +apply from: getTestFile("${testName}.gradle") + +task wrapper(type: Wrapper) { + gradleVersion = '1.10' +} diff --git a/src/test/resources/gradle/projects/configurationWithSubModules/gradlew b/src/test/resources/gradle/projects/configurationWithSubModules/gradlew new file mode 100644 index 0000000..91a7e26 --- /dev/null +++ b/src/test/resources/gradle/projects/configurationWithSubModules/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/src/test/resources/gradle/projects/configurationWithSubModules/gradlew.bat b/src/test/resources/gradle/projects/configurationWithSubModules/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/src/test/resources/gradle/projects/configurationWithSubModules/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/src/test/resources/gradle/projects/configurationWithSubModules/settings.gradle b/src/test/resources/gradle/projects/configurationWithSubModules/settings.gradle new file mode 100644 index 0000000..5f53697 --- /dev/null +++ b/src/test/resources/gradle/projects/configurationWithSubModules/settings.gradle @@ -0,0 +1 @@ +include ':api'