diff --git a/.github/workflows/gradle_build.yml b/.github/workflows/gradle_build.yml index 2d2c735..325f325 100644 --- a/.github/workflows/gradle_build.yml +++ b/.github/workflows/gradle_build.yml @@ -21,11 +21,11 @@ jobs: - name: Checkout Repository uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK uses: actions/setup-java@v3 with: - distribution: 'zulu' - java-version: '11' + distribution: 'temurin' + java-version: '17' - name: Add gradle.properties run: | diff --git a/.github/workflows/gradle_publish.yml b/.github/workflows/gradle_publish.yml index 8627cfb..3085aaf 100644 --- a/.github/workflows/gradle_publish.yml +++ b/.github/workflows/gradle_publish.yml @@ -18,11 +18,11 @@ jobs: - name: Checkout Repository uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK uses: actions/setup-java@v3 with: - distribution: 'zulu' - java-version: '11' + distribution: 'temurin' + java-version: '17' - name: Add gradle.properties run: | diff --git a/build.gradle b/build.gradle index cb8ecf8..5e48b90 100644 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,7 @@ * along with the Cyface Publish Plugin for Android. If not, see . */ buildscript { - ext.gradle_version = '7.4.2' // Major release available but breaks publish [RFR-412] + ext.gradle_version = '8.2.2' // Major release available but breaks publish [RFR-412] repositories { google() @@ -50,12 +50,6 @@ publishing { username = project.findProperty("githubUser").toString() password = project.findProperty("githubToken").toString() } - - /* - * Use this instead of the above to publish to a local folder under "build/repo". - * This is useful for debugging the publication code. - */ - //url = layout.buildDirectory.dir("repo") } } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cb..d64cd49 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e8be595..2ea3535 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68..1aa94a4 100755 --- a/gradlew +++ b/gradlew @@ -83,10 +83,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,10 +131,13 @@ 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. + if ! command -v java >/dev/null 2>&1 + then + 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 fi # Increase the maximum file descriptors if we can. @@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 6689b85..7101f8e 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -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. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -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. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/src/main/groovy/de.cyface.android-publish.gradle b/src/main/groovy/de.cyface.android-publish.gradle index 54eac87..50ad7f9 100644 --- a/src/main/groovy/de.cyface.android-publish.gradle +++ b/src/main/groovy/de.cyface.android-publish.gradle @@ -39,89 +39,90 @@ plugins { * reference. */ -// Setup Javadoc and source tasks for all build variants. +/** + * Identify variants which are not of interest in the publication process. + * + * @param variant The variant from `android.libraryVariants` + * @return `true` if this variant can be skipped in release + */ +static def isDebugOrMock(variant) { + def isDebug = variant.buildType.name == 'debug' + def isMock = variant.flavorName?.contains('Mock') + return isDebug || isMock +} + +/** + * Selects one variant per module to generate exactly one javadoc/sources.jar. + * + * For `cyface-de/android-backend` datacapturing and synchronization module the variant + * `movebisFullRelease` is selected and for the persistence module the variant `release`. + * + * @param variant + * @return + */ +static def isVariantForDocs(variant) { + return variant.name == 'movebisFullRelease' || variant.name == 'release' +} + +/** + * Only generate one sources and javadoc jar per module. + * + * Before switching to Gradle 8 we generates one per variant but with identical names, i.e. they + * did overwrite themselves. When switching to Gradle 8 this does not work anymore as we need to + * define each dependency explicitly and this way the javadocsJar of another flavor is used. We + * tried to generate a variant-specific Javadoc/SourcesJar but they contain the same bytes anyways. + * and with + * - `def kebabCaseName = variant.name.replaceAll("([a-z])([A-Z]+)", '$1-$2').toLowerCase()` and + * - `archiveClassifier.set(kebabCaseName + '-javadoc')` in this section and + * - `classifier kebabCaseName + '-javadoc'` in the publications section + * the jars are named like `datacapturing-cyface-full-release-javadoc.jar` which do not apply to the + * naming convention and no links are added to the POM by gradle. Thus, we only generate a variant- + * unspecific javadoc/sources jar. + * + * But we need to use `libraryVariants` for this as there is no possibility anymore to define the + * classpath without variant context. Our workaround is to select one specific variant. + */ project.android.libraryVariants.all { variant -> + if (!isVariantForDocs(variant)) { + return + } - def javaDocDestDir = file("${buildDir}/docs/${variant.name}Javadoc") - def javadocTaskName = "${variant.name}Javadoc" - def javadoc = tasks.create(javadocTaskName, Javadoc) { - description "Generates Javadoc for ${variant.name}." - source = variant.javaCompileProvider.get().source + // Setup Javadoc and source tasks for all build variants. + def javaDocDestDir = file("${buildDir}/docs/javadoc") + // Using `tasks.create` as with `task.register` the `destinationDir` is not found + def javadoc = tasks.create("javadoc", Javadoc) { + description "Generates Javadoc." + source = android.sourceSets.main.java.srcDirs destinationDir = javaDocDestDir classpath += files(android.getBootClasspath().join(File.pathSeparator)) def compileClassPath = variant.javaCompileProvider.get().classpath classpath += files(compileClassPath) - options.links("http://docs.oracle.com/javase/7/docs/api/") - options.links("http://d.android.com/reference/") exclude '**/BuildConfig.java' exclude '**/R.java' failOnError false } - tasks.register("${variant.name}JavadocJar", Jar) { - dependsOn "${javadocTaskName}" - description "Puts Javadoc for ${variant.name} in a jar." + tasks.register("javadocJar", Jar) { + dependsOn "javadoc" + description "Puts Javadoc in a jar" archiveClassifier.set('javadoc') from javadoc.destinationDir } - def sourceDirs = variant.sourceSets.collect { + def sourceDirs = android.sourceSets.collect { it.javaDirectories // includes Kotlin sources } - tasks.register("${variant.name}SourcesJar", Jar) { - description "Puts sources for ${variant.name} in a jar." + tasks.register("sourcesJar", Jar) { + description "Puts sources in jar" from sourceDirs archiveClassifier.set('sources') } - - // Attempt to define dependency (Gradle 8 requirement), but does not work [RFR-412] - /*def isDebug = variant.getBuildType().name == 'debug' - def isFlavored = !variant.flavorName.isEmpty() - def flavor = variant.flavorName.replace('_', '-') - def isMock = isFlavored && flavor.contains('Mock') - if (!isDebug && !isMock) { - tasks.named("publish${project.name.capitalize()}${variant.name.capitalize()}PublicationToMavenRepository") { - println "dependsOn publish${project.name.capitalize()}${variant.name.capitalize()}PublicationToMavenRepository on ${variant.name}JavadocJar" - dependsOn("${variant.name}JavadocJar") - dependsOn("${variant.name}SourcesJar") - } - tasks.named("publish${project.name.capitalize()}${variant.name.capitalize()}PublicationToMavenLocal") { - println "dependsOn publish${project.name.capitalize()}${variant.name.capitalize()}PublicationToMavenLocal on ${variant.name}JavadocJar" - dependsOn("${variant.name}JavadocJar") - dependsOn("${variant.name}SourcesJar") - } - }*/ } // This is probably required to run Javadoc and Source creation on each invocation of publish publish.dependsOn 'assemble' -// Attempt to define dependency for error occurring in Gradle 8 [RFR-412] -/*tasks.withType(PublishToMavenRepository) { task -> - println "task: ${task.name}" - def projectName = "${project.name.capitalize()}" - println "project: ${projectName}" - def match = task.name =~ /^publish($projectName)(.*)PublicationTo(.*)$/ - def variantName = "${match[0][2]}" // Release (persistence) or e.g. CyfaceFullRelease - // For some reasons, the publish task is also dependent on the other projectFlavor javadocJar - //def variant = variantName.uncapitalize() - def suffix = variantName.replace("Cyface", "").replace("Movebis", "") - // Persistence - if (suffix == "Release") { - def variant = suffix.uncapitalize() - println "dependsOn ${variant}SourcesJar/JavadocJar" - dependsOn(["${variant}JavadocJar", "${variant}SourcesJar"]) - } - // Datacapturing, Synchronization - else { - def variant = "movebis${suffix}" - def variant2 = "cyface${suffix}" - println "dependsOn ${variant}JavadocJar/SourcesJar ${variant2}JavadocJar/SourcesJar" - dependsOn(["${variant}JavadocJar", "${variant}SourcesJar", "${variant2}JavadocJar", "${variant2}SourcesJar"]) - } -}*/ - publishing { // Authenticate at the repository repositories { @@ -132,27 +133,39 @@ publishing { password = project.findProperty("githubToken").toString() } } + } + + // Ensure publication tasks depend on Javadoc and sources generation + afterEvaluate { + project.android.libraryVariants.all { variant -> + if (isDebugOrMock(variant)) { + return + } + + def variantNameCapitalized = variant.name.capitalize() + def bundleTaskName = "bundle${variantNameCapitalized}Aar" + + def projectName = "${project.name.capitalize()}" + + tasks.named("publish${projectName}${variantNameCapitalized}PublicationToMavenRepository").configure { + dependsOn tasks.named(bundleTaskName), + tasks.named("javadocJar"), + tasks.named("sourcesJar") + + } - /* - * Uncomment this to get all publications to a local folder under "build/repo". - * This is useful for debugging the publication code without uploading stuff to the - * server. - */ - /*maven { - name = 'myRepo' - url = layout.buildDirectory.dir("repo") - }*/ + tasks.named("publish${projectName}${variantNameCapitalized}PublicationToMavenLocal").configure { + dependsOn tasks.named(bundleTaskName), + tasks.named("javadocJar"), + tasks.named("sourcesJar") + } } + } + // Create publications for all release variants. publications { project.android.libraryVariants.all { variant -> - - // Only publish full release variants - def isDebug = variant.getBuildType().name == 'debug' - def isFlavored = !variant.flavorName.isEmpty() - def flavor = variant.flavorName.replace('_', '-') - def isMock = isFlavored && flavor.contains('Mock') - if (isDebug || isMock) { + if (isDebugOrMock(variant)) { return } @@ -160,15 +173,23 @@ publishing { "${project.name}${variant.name.capitalize()}"(MavenPublication) { groupId = 'de.cyface' // The artifactId must not contain upper case chars [STAD-234] - artifactId "${project.name}${flavor.contains('movebis') ? 'movebis' : ''}" + artifactId "${project.name}${variant.flavorName.contains('movebis') ? 'movebis' : ''}" project.logger.lifecycle('artifactId: ' + artifactId) version android.defaultConfig.versionName + + // Add main artifact artifact(variant.packageLibraryProvider.get().archivePath) + // Put javadoc and sources into jar - println "publish dependency: ${project.name}${variant.name.capitalize()} on ${variant.name}JavadocJar/SourcesJar" - println "" - artifact(tasks.named("${variant.name}JavadocJar")) - artifact(tasks.named("${variant.name}SourcesJar")) + artifact(tasks["javadocJar"].outputs.files.singleFile) { + classifier 'javadoc' + } + artifact(tasks["sourcesJar"].outputs.files.singleFile) { + classifier 'sources' + } + + // Logging for diagnostic purposes + project.logger.lifecycle("Configuring publication for variant: $variant.name with ArtifactId: $artifactId") } } }