├── .appveyor.yml ├── .github ├── dependabot.yml └── workflows │ └── CI.yml ├── .gitignore ├── .yo-rc.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src ├── main └── groovy │ └── ru │ └── vyarus │ └── gradle │ └── plugin │ └── lib │ ├── JavaLibExtension.groovy │ └── JavaLibPlugin.groovy └── test ├── groovy └── ru │ └── vyarus │ └── gradle │ └── plugin │ └── lib │ ├── AbstractKitTest.groovy │ ├── AbstractTest.groovy │ ├── ConfigurationCacheSupportKitTest.groovy │ ├── EncodingConfigurationTest.groovy │ ├── GradleMetadataDisableKitTest.groovy │ ├── GradlePluginCompatibilityKitTest.groovy │ ├── GradlePluginCompatibilityTest.groovy │ ├── JarModificationKitTest.groovy │ ├── JavaLibPluginKitTest.groovy │ ├── JavaLibPluginTest.groovy │ ├── JavaPlatformKitTest.groovy │ ├── LegacyModeKitTest.groovy │ ├── OpenDepsReportTasksTest.groovy │ ├── PomConfigurationTest.groovy │ ├── PomCorrectnessKitTest.groovy │ ├── PublicationOverrideKitTest.groovy │ ├── ReportsAggregationKitTest.groovy │ ├── ReportsAggregationTest.groovy │ ├── SigningKitTest.groovy │ └── UpstreamKitTest.groovy └── resources ├── cert └── test.gpg └── sample ├── Sample.java ├── Sample2.java ├── SampleTest.groovy ├── SampleTest2.groovy └── TestPlugin.java /.appveyor.yml: -------------------------------------------------------------------------------- 1 | version: '{build}' 2 | 3 | environment: 4 | matrix: 5 | - job_name: Java 8 6 | JAVA_HOME: C:\Program Files\Java\jdk1.8.0 7 | - job_name: Java 11 8 | JAVA_HOME: C:\Program Files\Java\jdk11 9 | - job_name: Java 17 10 | appveyor_build_worker_image: Visual Studio 2019 11 | JAVA_HOME: C:\Program Files\Java\jdk17 12 | 13 | build_script: 14 | - ./gradlew assemble --no-daemon 15 | test_script: 16 | - ./gradlew check --no-daemon 17 | 18 | on_success: 19 | - ./gradlew jacocoTestReport --no-daemon 20 | - ps: | 21 | $ProgressPreference = 'SilentlyContinue' 22 | Invoke-WebRequest -Uri https://uploader.codecov.io/latest/windows/codecov.exe -Outfile codecov.exe 23 | .\codecov.exe -f build\reports\jacoco\test\jacocoTestReport.xml -F windows 24 | 25 | cache: 26 | - C:\Users\appveyor\.gradle\caches 27 | - C:\Users\appveyor\.gradle\wrapper -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gradle 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "23:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | pull_request: 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | name: Java ${{ matrix.java }} 11 | strategy: 12 | matrix: 13 | java: [8, 11, 17] 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - name: Set up JDK ${{ matrix.java }} 19 | uses: actions/setup-java@v4 20 | with: 21 | distribution: 'zulu' 22 | java-version: ${{ matrix.java }} 23 | 24 | - name: Setup Gradle 25 | uses: gradle/actions/setup-gradle@v3 26 | 27 | - name: Build 28 | run: | 29 | chmod +x gradlew 30 | ./gradlew assemble --no-daemon 31 | 32 | - name: Test 33 | env: 34 | GH_ACTIONS: true 35 | run: ./gradlew check --no-daemon 36 | 37 | - name: Build coverage report 38 | if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' 39 | run: ./gradlew jacocoTestReport --no-daemon 40 | 41 | - uses: codecov/codecov-action@v4 42 | if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' 43 | with: 44 | files: build/reports/jacoco/test/jacocoTestReport.xml 45 | flags: LINUX 46 | fail_ci_if_error: true 47 | token: ${{ secrets.CODECOV_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created with https://www.gitignore.io 2 | 3 | ### Gradle ### 4 | .gradle/ 5 | build/ 6 | 7 | # Ignore Gradle GUI config 8 | gradle-app.setting 9 | 10 | ### JetBrains ### 11 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 12 | 13 | /*.iml 14 | 15 | ## Directory-based project format: 16 | .idea/ 17 | 18 | ## File-based project format: 19 | *.ipr 20 | *.iws 21 | 22 | ## Plugin-specific files: 23 | 24 | # IntelliJ 25 | out/ 26 | 27 | # mpeltonen/sbt-idea plugin 28 | .idea_modules/ 29 | 30 | # JIRA plugin 31 | atlassian-ide-plugin.xml 32 | 33 | # Crashlytics plugin (for Android Studio and IntelliJ) 34 | com_crashlytics_export_strings.xml 35 | 36 | 37 | ### Eclipse ### 38 | *.pydevproject 39 | .metadata 40 | bin/ 41 | tmp/ 42 | *.tmp 43 | *.bak 44 | *.swp 45 | *~.nib 46 | local.properties 47 | .settings/ 48 | .loadpath 49 | 50 | # External tool builders 51 | .externalToolBuilders/ 52 | 53 | # Locally stored "Eclipse launch configurations" 54 | *.launch 55 | 56 | # CDT-specific 57 | .cproject 58 | 59 | # PDT-specific 60 | .buildpath 61 | 62 | # sbteclipse plugin 63 | .target 64 | 65 | # TeXlipse plugin 66 | .texlipse 67 | 68 | ### Java ### 69 | *.class 70 | 71 | # Mobile Tools for Java (J2ME) 72 | .mtj.tmp/ 73 | 74 | # Package Files # 75 | *.war 76 | *.ear 77 | 78 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 79 | hs_err_pid* 80 | 81 | 82 | ### NetBeans ### 83 | nbproject/private/ 84 | nbbuild/ 85 | dist/ 86 | nbdist/ 87 | nbactions.xml 88 | nb-configuration.xml 89 | 90 | 91 | ### OSX ### 92 | .DS_Store 93 | .AppleDouble 94 | .LSOverride 95 | 96 | # Icon must end with two \r 97 | Icon 98 | 99 | 100 | # Thumbnails 101 | ._* 102 | 103 | # Files that might appear on external disk 104 | .Spotlight-V100 105 | .Trashes 106 | 107 | # Directories potentially created on remote AFP share 108 | .AppleDB 109 | .AppleDesktop 110 | Network Trash Folder 111 | Temporary Items 112 | .apdisk 113 | 114 | 115 | ### Windows ### 116 | # Windows image file caches 117 | Thumbs.db 118 | ehthumbs.db 119 | 120 | # Folder config file 121 | Desktop.ini 122 | 123 | # Recycle Bin used on file shares 124 | $RECYCLE.BIN/ 125 | 126 | # Windows Installer files 127 | *.cab 128 | *.msi 129 | *.msm 130 | *.msp 131 | 132 | # Windows shortcuts 133 | *.lnk 134 | 135 | 136 | ### Linux ### 137 | *~ 138 | 139 | # KDE directory preferences 140 | .directory 141 | 142 | ### JEnv ### 143 | # JEnv local Java version configuration file 144 | .java-version 145 | 146 | # Used by previous versions of JEnv 147 | .jenv-version 148 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-gradle-plugin": { 3 | "githubUser": "xvik", 4 | "authorName": "Vyacheslav Rusakov", 5 | "authorEmail": "vyarus@gmail.com", 6 | "projectName": "gradle-java-lib-plugin", 7 | "projectGroup": "ru.vyarus", 8 | "projectPackage": "ru.vyarus.gradle.plugin.lib", 9 | "projectVersion": "0.1.0", 10 | "projectDesc": "Gradle Java-lib plugin", 11 | "pluginPortalDesc": "Common gradle configuration for Java or Groovy library", 12 | "pluginPortalTags": "java, groovy, lib", 13 | "pluginPortalUseCustomGroup": true, 14 | "usedGeneratorVersion": "2.0.0", 15 | "centralPublish": true 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### 3.0.0 (2024-03-10) 2 | * (BREAKING) Drop gradle 5 and 6 support 3 | * (BREAKING) Always use native javadoc and source jars tasks (withJavadocJar() and withSourcesJar()) 4 | (before, custom legacy tasks were used for gradle 7.6 and older) 5 | * Cleanup deprecated gradle api usages 6 | * Update pom plugin to 3.0.0 (drops pom convention in favor of type-safe maven.pom) 7 | - (BREAKING) Remove pom plugin configuration shortcut (javaLib.pom) to avoid confusion (use maven extension directly) 8 | * Fix signing error when used with plugin-publish plugin 9 | * Configuration cache compatibility 10 | 11 | ### 2.4.0 (2023-02-16) 12 | * Gradle 8 compatibility 13 | * Fix plugin-publish 1.0 compatibility for gradle 7.6 and above 14 | (older gradle versions should use plugin-publish 0.21) 15 | * (breaking) For gradle 7.6 and above use native gradle registration of javadoc sources tasks 16 | (withJavadocJar() and withSourcesJar()). 17 | Related changes: 18 | - javadoc jar always created (even if no sources) 19 | - groovydoc artifact not created (always javadoc) 20 | For gradle older 7.6 legacy behaviour preserved 21 | 22 | ### 2.3.1 (2022-11-09) 23 | * Updated pom plugin (2.2.2): support repositories declaration in settings file only 24 | 25 | ### 2.3.0 (2021-11-01) 26 | * Updated pom plugin (2.2.1): automatic detection of incorrect pom closure usage 27 | * Fix gradle 7 warnings 28 | * Remove jacocoMerge task (used for jacoco executions data merge during reports aggregation): 29 | jacocoTestReport (JacocoReport) merges coverage data directly now 30 | 31 | ### 2.2.2 (2021-10-03) 32 | * Add disable publication option: javaLib.withoutPublication() (disables all declared publications) 33 | Useful for disabling bom publication in the root project (use platform for deps management only) 34 | * Fix aggregated coverage report for case when not all submodules produce coverage 35 | 36 | ### 2.2.1 (2021-07-13) 37 | * Fix multi-module projects configuration with allprojects closure 38 | (configuration extension always created on plugin activation to avoid mis-references) 39 | 40 | ### 2.2.0 (2021-06-22) 41 | * Updated pom plugin (2.2.0): java-platform compatibility 42 | * Add java-platform plugin support (assuming declared platform published as BOM): 43 | - activates platform dependencies (javaPlatform.allowDependencies()) 44 | - register pom plugin 45 | - add install task 46 | - registers "bom" publication (intentionally different name) 47 | - configures signing if signing plugin enabled 48 | - allows overriding default artifact name with javaLib.bom configuration 49 | (by default it's a root project name) 50 | * Add automatic signing configuration when 'signing' plugin applied 51 | (for snapshots signing not required - for release, not configured signing would fail) 52 | * Add openDependencyReport task when project-report plugin enabled 53 | (task opens htmlDependencyReport directly in the browser) 54 | * Enable jacoco xml report by default (required for coverage services) 55 | * Multi-module projects support: test and coverage reports aggregation 56 | (at least "base" plugin must be applied to trigger minimal java-lib plugin activation ) 57 | * Add `javaLib` configuration closure: 58 | - withoutGradleMetadata() - disables gradle metadata publishing 59 | - withoutJavadoc() and withoutSources() - disable javadoc and sources publish 60 | - bom.artifactId and bom.description properties - updates artifact declared with java-platform 61 | - pom - shortcut for the new pom plugin configuration closure (to use instead of pomGeneration) 62 | - autoModuleName - shortcut for defining Automatic-Module-Name manifest property 63 | - aggregateReports() - supposed to be used in the root project to aggregate 64 | test reports and jacoco coverage (adds test and jacocoTestReport tasks) 65 | Also, aggregates dependency report id project-report plugin enabled 66 | 67 | ### 2.1.0 (2020-01-19) 68 | * Updated pom plugin (2.1.0): 69 | - Brings back `provided` and `optional` scopes, because gradle native features can't completely replace them 70 | - `compileOnly` dependencies no more added to pom (default behaviour reverted) 71 | 72 | Versions 2.0.0 and 2.0.1 are not recommended for usage because of referenced pom plugin 73 | (there was an attempt to replace optional and provided configurations with native gradle features, 74 | but it failed: custom configurations still required). 75 | 76 | ### 2.0.1 (2020-01-19) DON'T USE 77 | * Updated pom plugin (2.0.1) containing fix for provided dependencies declared with BOM 78 | * Revert to old behaviour: in case of gradle plugin project use "maven" publication because its not possible 79 | to differentiate gralde plugin from usual project. In any case, artifacts will be exactly the same everywhere 80 | (plugin-publish javadoc and sources tasks will be disabled). 81 | 82 | ### 2.0.0 (2020-01-17) DON'T USE 83 | * (breaking) Requires gradle 5.1 and above 84 | - Remove legacy (lazy, without strict publishing) publication configuration 85 | * (breaking) Drop java 7 support 86 | * (breaking) Updated pom plugin ([2.0.0](https://github.com/xvik/gradle-pom-plugin/releases/tag/2.0.0)) removes provided and optional scopes 87 | - provided scope replaced with standard compileOnly configuration support 88 | * Use gradle configuration avoidance to prevent not used tasks creation 89 | * Set UTF-8 encoding for JavaCompile and GroovyCompile tasks 90 | * Set file.encoding=UTF-8 system property for Test tasks 91 | * Set UTF-8 encoding for javadoc task (encoding, charSet, docencoding) 92 | * Gradle plugin projects compatibility fixes: 93 | - When used with java-gardle-plugin, re-use pluginMaven publication instead of creating 94 | new one (because java-gardle-plugin hardcode publication name and it has to init it because of alias publications ) 95 | - Plugin-publish will not create his own javadoc and sources tasks (so java-lib tasks will be used) 96 | 97 | ### 1.1.2 (2018-07-22) 98 | * Fix missed pom dependencies 99 | * Unify stable/lazy behaviours 100 | 101 | ### 1.1.1 (2018-07-13) 102 | * Fix stable publishing detection 103 | 104 | ### 1.1.0 (2018-07-13) 105 | * Gradle 4.8 [STABLE_PUBLISHING](https://docs.gradle.org/4.8/userguide/publishing_maven.html#publishing_maven:deferred_configuration) support 106 | - Plugin requires gradle 4.6 or above (will fail on earlier gradle). 107 | - Gradle 4.6, 4.7 - legacy mode (as before) 108 | - (breaking) Gradle 4.8, <5.0 - updated pom plugin (1.3.0) will automatically enable STABLE_PUBLISHING mode 109 | - Gradle 5.0 and above - assumed stable publishing enabled by default 110 | 111 | Important: when STABLE_PUBLISHING is enabled (gradle 4.8 and above) publishing configurations will NOT work 112 | in a lazy way as before. Use `afterEvaluate {}` INSIDE publication configuration in order to configure lazy properties 113 | 114 | ### 1.0.5 (2017-08-15) 115 | * Update pom plugin (support gradle java-library plugin) 116 | 117 | ### 1.0.4 (2016-09-05) 118 | * Update pom plugin (fix non string values support, add clashing tag names workaround, add manual xml configuration shortcut) 119 | 120 | ### 1.0.3 (2016-07-29) 121 | * Update pom plugin (fix pom closure merge for repeatable tags like developers) 122 | 123 | ### 1.0.2 (2016-05-20) 124 | * Update pom plugin (fix pom dependencies scopes update) 125 | 126 | ### 1.0.1 (2015-12-05) 127 | * groovydocJar use javadoc classifier if no java sources available (because maven central requires javadoc for publication) 128 | * Generate pom.properties inside jar's META-INF (like maven) 129 | 130 | ### 1.0.0 (2015-11-23) 131 | * Initial release -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-2023 Vyacheslav Rusakov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gradle Java-lib plugin 2 | [![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](http://www.opensource.org/licenses/MIT) 3 | [![CI](https://github.com/xvik/gradle-java-lib-plugin/actions/workflows/CI.yml/badge.svg)](https://github.com/xvik/gradle-java-lib-plugin/actions/workflows/CI.yml) 4 | [![Appveyor build status](https://ci.appveyor.com/api/projects/status/github/xvik/gradle-java-lib-plugin?svg=true)](https://ci.appveyor.com/project/xvik/gradle-java-lib-plugin) 5 | [![codecov](https://codecov.io/gh/xvik/gradle-java-lib-plugin/branch/master/graph/badge.svg)](https://codecov.io/gh/xvik/gradle-java-lib-plugin) 6 | 7 | 8 | ### About 9 | 10 | Plugin do all boilerplate of maven publication configuration (using [maven-publish](https://docs.gradle.org/current/userguide/publishing_maven.html)) 11 | for java (or groovy) library or gradle plugin. Simplifies POM configuration and dependencies management (BOM). 12 | Also, changes some defaults common for java projects (like UTF-8 usage). 13 | 14 | Makes gradle more "maven" (in sense of simplicity, some behaviours and for [multi-module projects](#maven-like-multi-module-project)). 15 | 16 | Features: 17 | 18 | * Maven-like `jar` configuration 19 | - put `pom.xml` and `pom.properties` inside jar 20 | - fill manifest properties 21 | * Configure javadoc and sources artifacts (required for maven central publish) 22 | (with native gradle integrations) 23 | * Prepare maven publication (`maven-publish` plugin configuration) 24 | - `maven` publication configured with all jars (jar, sources javadoc) 25 | * Applies [pom plugin](https://github.com/xvik/gradle-pom-plugin) which: 26 | - Fix [dependencies scopes](https://github.com/xvik/gradle-pom-plugin/#dependencies) 27 | in generated pom 28 | - Add `maven.pom` configuration to [simplify pom definition](https://github.com/xvik/gradle-pom-plugin#pom-configuration). 29 | - Add `maven.withPomXml` configuration closure to use if you [need manual xml configuration](https://github.com/xvik/gradle-pom-plugin#manual-pom-modification) 30 | * Add `install` task as shortcut for `publishToMavenLocal` (simpler to use) 31 | * Apply `UTF-8` encoding for: 32 | - compile tasks: `JavaCompile` and `GroovyCompile` 33 | - javadoc (encoding, charSet, docEncoding) 34 | - test tasks: set `file.encoding=UTF-8` system property (only for test tasks) 35 | * Prepares BOM publication for [java-platform](https://docs.gradle.org/current/userguide/java_platform_plugin.html) plugin 36 | * Test and coverage reports aggregation for multi-module projects 37 | * Simplifies gradle platforms usage in multi-module projects (avoid "platform" leaking in published poms) 38 | 39 | If you need [multiple publications](https://docs.gradle.org/current/userguide/publishing_maven.html#N17EB8) from the same project, 40 | then you will have to perform additional configuration or, maybe (depends on case), use only [pom plugin](https://github.com/xvik/gradle-pom-plugin). 41 | 42 | **Confusion point**: plugin named almost the same as gradle's own [java-library](https://docs.gradle.org/current/userguide/java_library_plugin.html) plugin, 43 | but plugins do *different things* (gradle plugin only provides `api` and `implementation` configurations) and plugins *could* be used together. 44 | 45 | ##### Summary 46 | 47 | * Configuration closures: `maven` (from pom plugin), `javaLib` 48 | * Tasks: `sourcesJar`, `javadocJar`, `install`, `openDependencyReport` 49 | * [Publication](https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:publications): `maven`, `bom` 50 | * Enable plugins: [maven-publish](https://docs.gradle.org/current/userguide/publishing_maven.html), 51 | [ru.vyarus.pom](https://github.com/xvik/gradle-pom-plugin) 52 | 53 | ### Setup 54 | 55 | [![Maven Central](https://img.shields.io/maven-central/v/ru.vyarus/gradle-java-lib-plugin.svg)](https://maven-badges.herokuapp.com/maven-central/ru.vyarus/gradle-java-lib-plugin) 56 | [![Gradle Plugin Portal](https://img.shields.io/maven-metadata/v/https/plugins.gradle.org/m2/ru/vyarus/java-lib/ru.vyarus.java-lib.gradle.plugin/maven-metadata.xml.svg?colorB=007ec6&label=plugins%20portal)](https://plugins.gradle.org/plugin/ru.vyarus.java-lib) 57 | 58 | ```groovy 59 | buildscript { 60 | repositories { 61 | gradlePluginPortal() 62 | } 63 | dependencies { 64 | classpath 'ru.vyarus:gradle-java-lib-plugin:3.0.0' 65 | } 66 | } 67 | apply plugin: 'ru.vyarus.java-lib' 68 | ``` 69 | 70 | OR 71 | 72 | ```groovy 73 | plugins { 74 | id 'ru.vyarus.java-lib' version '3.0.0' 75 | } 76 | ``` 77 | 78 | #### Compatibility 79 | 80 | Plugin compiled for java 8, compatible with java 17 81 | 82 | Gradle | Version 83 | --------|------- 84 | 7 | 3.0.0 85 | 5.1 | [2.4.0](https://github.com/xvik/gradle-java-lib-plugin/tree/2.4.0) 86 | 4.6 | [1.1.2](https://github.com/xvik/gradle-java-lib-plugin/tree/1.1.2) 87 | older | [1.0.5](https://github.com/xvik/gradle-java-lib-plugin/tree/1.0.5) 88 | 89 | NOTE: plugin-publish 1.x would work properly only with gradle 7.6 or above 90 | 91 | #### Snapshots 92 | 93 |
94 | Snapshots may be used through JitPack 95 | 96 | * Go to [JitPack project page](https://jitpack.io/#ru.vyarus/gradle-java-lib-plugin) 97 | * Select `Commits` section and click `Get it` on commit you want to use 98 | or use `master-SNAPSHOT` to use the most recent snapshot 99 | 100 | * Add to `settings.gradle` (top most!) (exact commit hash might be used as version): 101 | 102 | ```groovy 103 | pluginManagement { 104 | resolutionStrategy { 105 | eachPlugin { 106 | if (requested.id.id == 'ru.vyarus.java-lib') { 107 | useModule('ru.vyarus:gradle-java-lib-plugin:master-SNAPSHOT') 108 | } 109 | } 110 | } 111 | repositories { 112 | gradlePluginPortal() 113 | maven { url 'https://jitpack.io' } 114 | } 115 | } 116 | ``` 117 | * Use plugin without declaring version: 118 | 119 | ```groovy 120 | plugins { 121 | id 'ru.vyarus.java-lib' 122 | } 123 | ``` 124 | 125 |
126 | 127 | ### Usage 128 | 129 | Plugin activate features based on registered plugins. Plugin support several usage scenarios. 130 | 131 | In case of multi-module projects, plugin activate features only in applied module, ignoring submodules or root module 132 | (so to apply it in all submodules use `allprojects` or `subprojects` section) 133 | 134 | Example projects: 135 | 136 | * [Java library](https://github.com/xvik/dropwizard-guicey), published to maven central 137 | * [Multi-module java library](https://github.com/xvik/dropwizard-guicey-ext) (with BOM), published to maven central 138 | * [Simple multi-module library](https://github.com/xvik/yaml-updater) (without BOM), published to maven central 139 | * [This project](https://github.com/xvik/gradle-java-lib-plugin/blob/master/build.gradle) is an example of gradle plugin publication to maven central and plugins portal 140 | 141 | 142 | #### Java module 143 | 144 | ```groovy 145 | plugins { 146 | id 'java' // groovy or java-library 147 | // id 'signing' 148 | // id 'project-report' 149 | id 'ru.vyarus.java-lib' 150 | } 151 | 152 | group = 'your.group' 153 | version = '1.0.0' 154 | description = 'My project description' 155 | 156 | // configure target pom 157 | maven.pom { 158 | name = 'Project Name' 159 | description = 'My awesome project' 160 | ... 161 | } 162 | 163 | repositories { mavenLocal(); mavenCentral() } 164 | dependencies { 165 | ... 166 | } 167 | 168 | javaLib { 169 | // withoutJavadoc() 170 | // withoutSources() 171 | withoutGradleMetadata() 172 | 173 | // autoModuleName = 'project-module-name' 174 | 175 | pom { 176 | // removeDependencyManagement() 177 | // forceVersions() 178 | // disableScopesCorrection() 179 | // disableBomsReorder() 180 | } 181 | } 182 | 183 | ``` 184 | 185 | Activates with [java](https://docs.gradle.org/current/userguide/java_plugin.html), 186 | [groovy](https://docs.gradle.org/current/userguide/groovy_plugin.html) or 187 | [java-library](https://docs.gradle.org/current/userguide/java_library_plugin.html) plugin. 188 | Typical usage: single-module gradle project which must be published to maven central (or any other maven repo) 189 | 190 | * Adds `javadoc` and `sources` for publication 191 | * Registers `maven` publication for pom, jar, javadoc and sources artifacts 192 | * Applies UTF-8 encoding for java/groovy compile, javadoc/groovydoc and test executions 193 | * If [signing](https://docs.gradle.org/current/userguide/signing_plugin.html) plugin active, [configures publication signing](#signing) (required for maven central publication) 194 | * Adds `install` task for installation into local repository (like maven; simply shortcut for `publishToMavenLocal` task) 195 | * Enables xml jacoco reports (if jacoco enabled; required for coverage services) 196 | * Register [ru.vyarus.pom](https://github.com/xvik/gradle-pom-plugin) plugin which: 197 | - adds `optional` and `provided` configurations (in maven sense) 198 | - fixes dependency scopes in the generated pom 199 | - moves up dependencyManagement section in the generated pom (if platforms used) 200 | - adds `maven.pom` extension for pom declaration (`maven.withPomXml` might be used for low-level modification) 201 | * Utilities: 202 | - simple Auto-Module-Name declaration (java 9 modules) 203 | - option to disable gradle metadata publication (maven central fails on it sometimes) 204 | - option to remove dependencyManagement section in the generated pom (appears if platforms used): use resolved dependencies versions instead (pom plugin feature) 205 | * Adds [openDependencyReport](#dependency-report) task added if [project-report](https://docs.gradle.org/current/userguide/project_report_plugin.html) plugin enabled 206 | (opens `htmlDependencyReport` directly in browser) 207 | 208 | #### BOM module 209 | 210 | ```groovy 211 | plugins { 212 | id 'java-platform' 213 | // id 'signing' 214 | // id 'project-report' 215 | id 'ru.vyarus.java-lib' 216 | } 217 | 218 | group = 'your.group' 219 | version = '1.0.0' 220 | description = 'My project description' 221 | 222 | maven.pom { 223 | ... 224 | } 225 | 226 | repositories { mavenLocal(); mavenCentral() } 227 | dependencies { 228 | api platform('ru.vyarus.guicey:guicey-bom:5.2.0-1') 229 | constraints { 230 | api 'org.webjars:webjars-locator:0.40' 231 | } 232 | // add subprojects to published BOM 233 | project.subprojects.each { api it } 234 | } 235 | 236 | javaLib { 237 | bom { 238 | // change artifact from project name, if required 239 | artifactId = 'something-bom' 240 | description = 'Different from project description' 241 | } 242 | withoutGradleMetadata() 243 | } 244 | ``` 245 | 246 | Activates with [java-platform](https://docs.gradle.org/current/userguide/java_platform_plugin.html) plugin. 247 | Typical usage: BOM module (might be root project) in multi-module project 248 | 249 | * Activates platform dependencies (javaPlatform.allowDependencies()) to allow single dependencies declaration 250 | * Registers `bom` publication for bom artifact (produced from declared platform) 251 | * Register [ru.vyarus.pom](https://github.com/xvik/gradle-pom-plugin) plugin (with the same features as above) 252 | * If [signing](https://docs.gradle.org/current/userguide/signing_plugin.html) plugin active, [configures publication signing](#signing) (required for maven central publication) 253 | * Adds `install` task for installation into local repository (like maven; simply shortcut for `publishToMavenLocal` task) 254 | * Utilities: 255 | - option to disable gradle metadata publication (maven central fails on it sometimes) 256 | - option to change bom artifact id (useful when platform declared in the root module) 257 | * Adds [openDependencyReport](#dependency-report) task added if [project-report](https://docs.gradle.org/current/userguide/project_report_plugin.html) plugin enabled 258 | (opens `htmlDependencyReport` directly in browser) 259 | 260 | #### Root project reports aggregation 261 | 262 | ```groovy 263 | plugins { 264 | id 'base' 265 | id 'jacoco' 266 | //id 'project-report' 267 | id 'ru.vyarus.java-lib' 268 | } 269 | 270 | javaLib { 271 | aggregateReports() 272 | } 273 | 274 | // sub modules - simple java projects 275 | subprojects { 276 | apply plugin: 'java' 277 | 278 | ... 279 | } 280 | ``` 281 | 282 | Activates with [base](https://docs.gradle.org/current/userguide/base_plugin.html) plugin. 283 | Used to aggregate test and coverage reports from java submodules. 284 | 285 | By default, will only register `openDependencyReport` task added if [project-report](https://docs.gradle.org/current/userguide/project_report_plugin.html) plugin enabled. 286 | Reports aggregation must be explicitly triggered: 287 | - Adds `test` task which would simply aggregate (run if required) java submodules test reports 288 | - If jacoco plugin active, add `jacocoMerge` (not for direct usage) and 289 | `jacocoTestReport` tasks to aggregate jacoco xml and html reports from java submodules 290 | - If project-report plugin active, will aggregate dependency reports for submodules 291 | 292 | In short: it adds absolutely the same tasks as in java modules and generates 293 | reports exactly into the same locations so there would be no difference in paths 294 | when configuring external services (e.g. coveralls). 295 | 296 | NOTE: aggregation will work with `java-platform` plugin too if it used in the root module (see [complete multi-module example](#maven-like-multi-module-project)). 297 | 298 | ### Options 299 | 300 | ```groovy 301 | javaLib { 302 | 303 | /** 304 | * Do not publish javadoc (groovydoc) with `maven` publication. 305 | */ 306 | withoutJavadoc() 307 | 308 | /** 309 | * Do not publish sources with `maven` publication. 310 | */ 311 | withoutSources() 312 | 313 | /** 314 | * Do not publish gradle metadata artifact. 315 | * Affects all publications (not just registered by plugin). 316 | */ 317 | withoutGradleMetadata() 318 | 319 | /** 320 | * Disable all publications. Might be used to disable configured BOM publication or any sub-module publication. 321 | */ 322 | withoutPublication() 323 | 324 | /** 325 | * Shortcut for Auto-Module-Name meta-inf header declaration 326 | */ 327 | autoModuleName = 'project-module-name' 328 | 329 | /** 330 | * Used ONLY with java-platform plugin if published artifact must differ from 331 | * project name (for example, when declared in the root project). 332 | */ 333 | bom { 334 | // when not declared, project.name used 335 | artifactId = 'name' 336 | // when not declared, project.description used 337 | description = 'desc' 338 | } 339 | 340 | /** 341 | * Used in the root project (project with child projects) to aggregate 342 | * test, coverage (jacoco) and dependency (project-report) reports. 343 | * Requires at least `base` plugin. Will work java-platform plugin 344 | * (will not work with java plugin because such module can't aggregate). 345 | */ 346 | aggregateReports() 347 | } 348 | ``` 349 | 350 | ### POM 351 | 352 | You need to specify general project info: 353 | 354 | ```groovy 355 | group = 'your.group' // maven group 356 | version = '1.0.0' // project version 357 | description = 'My project description' // optional (affects jar manifest) 358 | ``` 359 | 360 | Note: maven `artifactId` will be the same as project name, and the default for project name 361 | is current directory name. If you need to change name, add in `settings.gradle`: 362 | 363 | ``` 364 | rootProject.name = 'the-name-you-want' 365 | ``` 366 | 367 | For maven-central publication you need to fill all required pom sections: 368 | 369 | ```groovy 370 | maven.pom { 371 | // name and desciption set automatically from project, but you can override them here 372 | //name 'Project Name' 373 | //description 'My awesome project' 374 | licenses { 375 | license { 376 | name = "The MIT License" 377 | url = "http://www.opensource.org/licenses/MIT" 378 | distribution = 'repo' 379 | } 380 | } 381 | scm { 382 | url = 'https://github.com/me/my-repo' 383 | connection = 'scm:git@github.com:me/my-repo.git' 384 | developerConnection = 'scm:git@github.com:me/my-repo.git' 385 | } 386 | developers { 387 | developer { 388 | id = "dev1" 389 | name = "Dev1 Name" 390 | email = "dev1@email.com" 391 | } 392 | } 393 | } 394 | ``` 395 | 396 | Read more about pom configuration in the [pom plugin's docs](https://github.com/xvik/gradle-pom-plugin#pom-configuration). 397 | 398 | If your project hosted on github you may use [github-info](https://github.com/xvik/gradle-github-info-plugin) plugin, 399 | which fills most github-related pom sections for you automatically. 400 | 401 | Use the following configurations to get correct scopes in the resulted pom: 402 | 403 | Maven scope | Gradle configuration 404 | ------------| ---------------- 405 | compile | implementation, api 406 | runtime | runtimeOnly 407 | provided | provided (**not** compileOnly!) 408 | optional | optional, [feature variants](https://github.com/xvik/gradle-pom-plugin#feature-variants) 409 | 410 | See [pom plugin doc](https://github.com/xvik/gradle-pom-plugin#dependencies) for more details about dependencies scopes in the generated pom 411 | 412 | #### Using BOMs 413 | 414 | When you use BOMs (for dependencies versions management) with spring plugin or gradle platform you'll have 415 | `dependencyManagement` section generated in the target pom. Often it is not desired:to use only resolved 416 | versions and avoid `dependencyManagent` use: 417 | 418 | ```groovy 419 | maven.pom.removeDependencyManagement() 420 | ``` 421 | 422 | Read more in the [pom plugin's docs](https://github.com/xvik/gradle-pom-plugin#improving-boms-usage) 423 | 424 | #### BOM declaration 425 | 426 | The simplest way to declare BOM is using [java-platform](https://docs.gradle.org/current/userguide/java_platform_plugin.html) 427 | 428 | ```groovy 429 | plugins { 430 | id 'java-platform' 431 | id 'ru.vyarus.java-lib' 432 | } 433 | 434 | repositories { mavenLocal(); mavenCentral() } 435 | dependencies { 436 | api platform('ru.vyarus.guicey:guicey-bom:5.2.0-1') 437 | constraints { 438 | api 'org.webjars:webjars-locator:0.40' 439 | } 440 | // add subprojects to published BOM 441 | project.subprojects.each { api it } 442 | } 443 | ``` 444 | 445 | Java-lib plugin would automatically activate dependencies declaration (`constraints` block). 446 | 447 | I propose to mix dependencies and modules into single BOM declaration, but you can always split 448 | dependencies management and modules BOM by declaring two platforms in two different modules. 449 | 450 | If you use `java-platform` in the root project, then you might want to change name of published artifact 451 | (by default it would be root project name in this case). To change it use: 452 | 453 | ```groovy 454 | javaLib { 455 | bom { 456 | artifactId = 'some-bom' 457 | description = 'overridden description' 458 | } 459 | } 460 | ``` 461 | 462 | ### Publication 463 | 464 | [maven-publish](https://docs.gradle.org/current/userguide/publishing_maven.html) plugin used for publication. 465 | 466 | By default, plugin configures `maven` publication with javadoc or (and) groovydoc and sources jars for `java` 467 | (`groovy` or `java-library`) plugins and `bom` publication for `java-platform` plugin. 468 | 469 | Use `install` task to deploy everything into local maven repository. 470 | 471 | ```bash 472 | $ gradlew install 473 | ``` 474 | 475 | If you don't want to publish everything (jar, sources, javadoc) then you can: 476 | 477 | ```groovy 478 | javaLib { 479 | withtouSources() 480 | withoutJavadoc() 481 | } 482 | ``` 483 | 484 | OR override list of publishing artifacts: 485 | 486 | ```groovy 487 | publishing.publications.maven.artifacts = [jar, javadocJar] 488 | ``` 489 | 490 | NOTE that for maven central publication sources and javadocs are required 491 | 492 | To ADD artifacts for publication, configure them directly for publication: 493 | 494 | ```groovy 495 | publishing { 496 | publications.maven { 497 | artifact buildDelivery { archiveClassifier.set('zip') } 498 | } 499 | } 500 | ``` 501 | 502 | Here the result of `buildDelivery` task (of type `Zip`) **added** to `maven` publication with `zip` classifier. 503 | 504 | #### Gradle metadata 505 | 506 | Since gradle 6, gradle would always publish its [metadata](https://docs.gradle.org/current/userguide/publishing_gradle_module_metadata.html): 507 | 508 | ``` 509 | Gradle Module Metadata is a unique format aimed at improving dependency resolution by making it multi-platform and variant-aware. 510 | ``` 511 | 512 | Essentially, it's an additional `.module` file containing json representation of dependencies. 513 | This is really necessary only when advanced gradle features used (constraints (not in platform), variants). 514 | 515 | But this would mean that gradle and maven projects would use *different* dependencies 516 | after publication: maven use pom, gradle would load .module file with additional dependencies info. 517 | 518 | It would be more honest to publish only pom (especially for public projects) and disable metadata publishing: 519 | 520 | ```groovy 521 | javaLib { 522 | withoutMavenMetadata() 523 | } 524 | ``` 525 | 526 | Also note, that maven central could complain about metadata file (if published). 527 | 528 | #### Publish to repository 529 | 530 | You must configure repository for actual publication [repository](https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:repositories) must be configured: 531 | 532 | ```groovy 533 | publishing { 534 | repositories { 535 | maven { 536 | // change to point to your repo, e.g. http://my.org/repo 537 | url "$buildDir/repo" 538 | } 539 | } 540 | } 541 | ``` 542 | 543 | Then [publish task](https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:publishing) may be used to perform publish. 544 | 545 | #### Publish to maven-central 546 | 547 | For maven-central publication use [nexus publish plugin](https://github.com/gradle-nexus/publish-plugin) 548 | which automates full maven central release cycle. 549 | 550 | ```groovy 551 | plugins { 552 | ... 553 | id 'io.github.gradle-nexus.publish-plugin' version '1.1.0' 554 | } 555 | 556 | nexusPublishing { 557 | repositories { 558 | sonatype { 559 | username = findProperty('sonatypeUser') 560 | password = findProperty('sonatypePassword') 561 | } 562 | } 563 | } 564 | ``` 565 | 566 | For release, you would need to call two tasks: `publishToSonatype`, `closeAndReleaseSonatypeStagingRepository` 567 | 568 | You'll need to configure `sonatypeUser` and `sonatypePassword` properties in global gradle file: 569 | `~/.gradle/gradle.properties` 570 | 571 | IMPORTANT artifacts must be [signed](#signing)! 572 | 573 | #### Gradle plugin 574 | 575 | Gradle plugin project will have [java-gradle-plugin](https://docs.gradle.org/current/userguide/java_gradle_plugin.html), 576 | which declares its own maven publication `pluginMaven` (with main jar as artifact). Also, plugin creates one more 577 | publication per declared plugin to publish [plugin marker artifact](https://docs.gradle.org/current/userguide/plugins.html#sec:plugin_markers) 578 | (required by gradle plugins dsl). 579 | 580 | Java-lib plugin will still create separate publication `maven` and you should use it for publishing with bintray 581 | (same way as for usual library) 582 | 583 | ##### Publishing to gradle plugin repository 584 | 585 | For publishing in gradle plugin repository you will use [com.gradle.plugin-publish](https://plugins.gradle.org/docs/publish-plugin) 586 | plugin. 587 | 588 | **IMPORTANT**: plugin-publish 1.x is supported for gradle 7.6 and above, for lower gradle use 0.x 589 | 590 | Use `maven` publication for publishing into maven central or other repo (optional). Plugin-publish 591 | will use it's `plugin-maven` publication for plugins portal publication. Both publications 592 | would contain the same artifacts. 593 | 594 | Example for publishing in maven central and plugin portal (gradle 7.6 or above): 595 | 596 | ```groovy 597 | plugins { 598 | id 'com.gradle.plugin-publish' version '1.2.1' 599 | id 'java-gradle-plugin' 600 | id 'ru.vyarus.java-lib' version '3.0.0' 601 | } 602 | 603 | repositories { mavenLocal(); mavenCentral(); gradlePluginPortal() } 604 | 605 | group = 'com.foo' 606 | description = 'Short description' 607 | 608 | gradlePlugin { 609 | plugins { 610 | myPlugin { 611 | id = 'com.foo.plugin' 612 | displayName = project.description 613 | description = 'Long description' 614 | tags.set(['something']) 615 | implementationClass = 'com.foo.MyPlugin' 616 | } 617 | } 618 | } 619 | ``` 620 | 621 | Here `publishMavenPublicationToMavenRepository` would publish to repository and `publishPlugins` publish into plugins portal. 622 | 623 | Assuming custom `maven` (name!) repository is configured: 624 | 625 | ```groovy 626 | publishing { 627 | repositories { maven { url "http://some.repo/"} } 628 | } 629 | ``` 630 | 631 | ##### Publishing only to custom repo 632 | 633 | This is in-house plugin case, when plugin is published only into corporate repository. 634 | 635 | The simplest solution is to disable `pluginMaven` publication tasks (but marker artifact publications should remain!) 636 | and publish only remaining `maven` publication: 637 | 638 | ```groovy 639 | tasks.withType(AbstractPublishToMaven) { Task task -> 640 | if (task.name.startsWith("publishPluginMaven")) { 641 | task.enabled(false) 642 | } 643 | } 644 | ``` 645 | 646 | This will disable: `publishPluginMavenPublicationToMavenLocal` and `publishPluginMavenPublicationToMavenRepository` 647 | 648 | And you can simply use `publish` task to trigger all required publications without duplicates. 649 | 650 | The same way, `install` will install all required artifacts locally (including markers) and so it is possible 651 | to use plugins from local maven repository too (with plugin syntax): 652 | 653 | add to settings.gradle: 654 | 655 | ```groovy 656 | pluginManagement { 657 | repositories { 658 | mavenLocal() 659 | gradlePluginPortal() 660 | } 661 | } 662 | ``` 663 | 664 | ### Encodings 665 | 666 | UTF-8 applied to: 667 | 668 | * (all `CompileJava` tasks).options.encoding 669 | * (all `CompileGrovy` tasks).options.encoding 670 | * (all `Javadoc`).options.\[encoding, charSet, docEncoding] 671 | * (all `Test`).systemProperty 'file.encoding' 672 | 673 | Note that groovydoc task does not have encoding configuration, but it should use UTF-8 by defautl. 674 | 675 | For tests, encoding is important (especially on windows) because test forked process will not inherit root gradle encoding configuration. 676 | 677 | ### Tasks 678 | 679 | NOTE: for gradle 7.6 and above [native javadoc and sources registration used](https://docs.gradle.org/current/userguide/java_plugin.html#packaging) 680 | 681 | - `sourcesJar` 682 | - `javadocJar` 683 | - `openDependencyReport` if `project-report` plugin active - opens html dependency report in browser 684 | 685 | `install` task added to simplify publication to local maven repository: this is simply shortcut for 686 | gradle's [publishToMavenLocal](https://docs.gradle.org/current/userguide/publishing_maven.html#publishing_maven:tasks) task 687 | (simply shorter to type and more common name after maven). 688 | 689 | ### Main Jar 690 | 691 | Plugin applies default manifest properties: 692 | 693 | ```groovy 694 | 'Implementation-Title': project.description ?: project.name, 695 | 'Implementation-Version': project.version, 696 | 'Built-By': System.getProperty('user.name'), 697 | 'Built-Date': new Date(), 698 | 'Built-JDK': System.getProperty('java.version'), 699 | 'Built-Gradle': gradle.gradleVersion, 700 | 'Target-JDK': project.targetCompatibility 701 | ``` 702 | 703 | You can override it: 704 | 705 | ```groovy 706 | jar { 707 | manifest { 708 | attributes 'Implementation-Title': 'My Custom value', 709 | 'Built-By': 'Me' 710 | } 711 | } 712 | ``` 713 | 714 | For all not specified properties default values will be used. 715 | 716 | Plugin will include additional files inside jar (like maven do) into `META-INF/maven/group/artifact/` 717 | 718 | * pom.xml 719 | * pom.properties 720 | 721 | pom.properties contains: 722 | 723 | * version 724 | * groupId 725 | * artifactId 726 | 727 | ### Signing 728 | 729 | Plugin will configure signing automatically for *configured publications*: `maven` and `bom` 730 | (note that in case of gradle plugin, gradle use its own publication for portal publication 731 | and it would not be signed (no need)). 732 | 733 | You only need to apply [signing](https://docs.gradle.org/current/userguide/signing_plugin.html) plugin: 734 | 735 | ```groovy 736 | plugins { 737 | id 'java' 738 | id 'signing' 739 | id 'ru.vyarus.java-lib' 740 | } 741 | ``` 742 | 743 | No additional configuration required, except properties in the global gradle config `~/.gradle/gradle.properties`: 744 | 745 | ```properties 746 | signing.keyId = 78065050 747 | signing.password = 748 | signing.secretKeyRingFile = /path/to/certs.gpg 749 | ``` 750 | 751 | IMPORTANT: password property (empty) required even if no password used! 752 | 753 | Note that project build will not complain while building snapshot versions 754 | (version ending with `-SNAPSHOT`) - signing task would be simply ignored. 755 | But, on release gradle would fail if signing not configured properly. 756 | 757 | #### Signing certificate 758 | 759 | Certificate generation described in many articles around the web, for example, sonatype 760 | [gpg guide](https://central.sonatype.org/publish/requirements/gpg/). 761 | 762 | I will just show required commands for generation and obtaining keyring file: 763 | 764 | Certificate generation: 765 | 766 | ``` 767 | gpg --gen-key 768 | ``` 769 | 770 | (if you want, you can leave passphrase blank - just hit enter several times) 771 | 772 | Alternatively, `gpg --full-gen-key` may be used to set exact algorithm and expiration (by default generated key would expire in few years) 773 | 774 | List keys: 775 | 776 | ``` 777 | gpg --list-keys 778 | gpg --list-secret-keys 779 | ``` 780 | 781 | You can always edit key if required (for example change expiration): 782 | 783 | ``` 784 | gpg --edit-key (key id) 785 | gpg> key 1 786 | gpg> expire 787 | (follow prompts) 788 | gpg> save 789 | ``` 790 | 791 | Create keyring file: 792 | 793 | ``` 794 | gpg --export-secret-keys (key id) > cert.gpg 795 | ``` 796 | 797 | Put `cert.gpg` somewhere and set full path to it in `signing.secretKeyRingFile` 798 | 799 | You also need short key id: 800 | 801 | ``` 802 | gpg --list-secret-keys --keyid-format SHORT 803 | 804 | Example output: 805 | sec rsa3072/78065050 2021-06-06 [SC] 806 | ``` 807 | 808 | Here `78065050` is your keyid which should be set as `signing.keyId` 809 | 810 | If you set passphrase, set it in `signing.password`, otherwise leave it blank 811 | 812 | IMPORTANT: for maven central, you'll need to register your public key with 813 | 814 | ``` 815 | gpg --keyserver keyserver.ubuntu.com --send-keys (short key id) 816 | ``` 817 | 818 | That's all. 819 | 820 | ### Dependency report 821 | 822 | When [project-report](https://docs.gradle.org/current/userguide/project_report_plugin.html) plugin active, 823 | `openDependencyReport` task created. 824 | 825 | This is pure utility task: it calls `htmlDependencyReport` and opens it directly 826 | in the browser (directly on page with dependencies, instead of index). 827 | 828 | This simply faster: manual `htmlDependencyReport` requires several clicks to open required report. 829 | 830 | ### Maven-like multi-module project 831 | 832 | Here is an example of how plugin could be used in multi-module project to apply 833 | maven configuration style: root project manage all dependency versions. 834 | 835 | ```groovy 836 | plugins { 837 | id 'jacoco' 838 | id 'java-platform' 839 | id 'ru.vyarus.java-lib' 840 | } 841 | 842 | description = 'Maven-like project' 843 | 844 | // dependency versions management 845 | dependencies { 846 | api platform("ru.vyarus:dropwizard-guicey:$guicey") 847 | constraints { 848 | api 'com.h2database:h2:1.4.200' 849 | 850 | // add subprojects to BOM 851 | project.subprojects.each { api it } 852 | } 853 | } 854 | 855 | javaLib { 856 | aggregateReports() 857 | // publish root BOM as custom artifact 858 | bom { 859 | artifactId = 'sample-bom' 860 | description = 'Sample project BOM' 861 | } 862 | 863 | // OR disable BOM publication 864 | // withoutPublication() 865 | } 866 | 867 | // maven publication related configuration applied to all projects 868 | allprojects { 869 | //apply plugin: 'project-report' 870 | //apply plugin: 'signing' 871 | 872 | repositories { mavenCentral(); mavenLocal() } 873 | 874 | group = 'com.test' 875 | 876 | // such delay is required because java-lib (and java) plugin would be applied only 877 | // in the subprojects section and so this would configure root project configuration 878 | // without delay 879 | plugins.withId('java') { 880 | maven.pom { 881 | licenses { 882 | license { 883 | name = "The MIT License" 884 | url = "http://www.opensource.org/licenses/MIT" 885 | distribution = 'repo' 886 | } 887 | } 888 | scm { 889 | url = 'https://github.com/me/my-repo.git' 890 | connection = 'scm:git@github.com:me/my-repo.git' 891 | developerConnection = 'scm:git@github.com:me/my-repo.git' 892 | } 893 | //... 894 | } 895 | } 896 | 897 | javaLib.withoutGradleMetadata() 898 | } 899 | 900 | // all sub-modules are normal java modules, using root BOM (like maven) 901 | subprojects { 902 | apply plugin: 'groovy' 903 | apply plugin: 'jacoco' 904 | apply plugin: 'ru.vyarus.java-lib' 905 | 906 | sourceCompatibility = 1.8 907 | 908 | // common dependencies for all modules 909 | dependencies { 910 | implementation platform(project(':')) 911 | 912 | compileOnly 'com.github.spotbugs:spotbugs-annotations:4.2.3' 913 | implementation 'ru.vyarus:dropwizard-guicey' 914 | 915 | testImplementation 'org.spockframework:spock-core' 916 | testImplementation 'io.dropwizard:dropwizard-testing' 917 | } 918 | 919 | javaLib { 920 | // java 9 auto module name 921 | autoModuleName = "com.sample.module" 922 | } 923 | 924 | maven { 925 | // use only direct dependencies in the generated pom, removing BOM 926 | removeDependencyManagement() 927 | } 928 | } 929 | ``` 930 | 931 | Here required dependency versions declared in the root project using gradle platform. 932 | Platform published as BOM with custom artifact name (dual BOM: both project modules and dependencies). 933 | 934 | Sub-projects are java modules which use platform declared in the root project for dependency management. 935 | `maven.removeDependencyManagement()` prevents "leaking" platform into module poms 936 | (generated poms would contain just required dependencies with resolved versions) 937 | 938 | `groovy` plugin used just as an example (used for spock tests, main sources might be java-only): it could be `java` or `java-library` plugin. 939 | 940 | The complete multi-module project example could be generated with [java-library generator](https://github.com/xvik/generator-lib-java). 941 | 942 | * [dropwizard-guicey-ext](https://github.com/xvik/dropwizard-guicey-ext) - multi-module project with (published) bom 943 | * [yaml-updater](https://github.com/xvik/yaml-updater) - simple multi-module without bom (simple case) 944 | 945 | ### APPENDIX: boilerplate plugin removes 946 | 947 | Section briefly shows what plugin configures so if plugin defaults didn't fit your needs, you can 948 | easily reproduce parts of it in your custom build. 949 | 950 | #### Java module boilerplate 951 | 952 | ```groovy 953 | plugins { id 'java' } 954 | 955 | apply plugin: 'ru.vyarus.pom' 956 | 957 | jar { 958 | manifest { 959 | attributes 'Implementation-Title': project.description ?: project.name, 960 | 'Implementation-Version': project.version, 961 | 'Built-By': System.getProperty('user.name'), 962 | 'Built-Date': new Date(), 963 | 'Built-JDK': System.getProperty('java.version'), 964 | 'Built-Gradle': gradle.gradleVersion, 965 | 'Target-JDK': project.targetCompatibility 966 | } 967 | } 968 | 969 | java { 970 | withJavadocJar() 971 | withSourcesJar() 972 | } 973 | 974 | task generatePomPropertiesFile { 975 | inputs.properties ([ 976 | 'version': "${ -> project.version }", 977 | 'groupId': "${ -> project.group }", 978 | 'artifactId': "${ -> project.name }" 979 | ]) 980 | outputs.file "$project.buildDir/generatePomPropertiesFile/pom.properties" 981 | doLast { 982 | File file = outputs.files.singleFile 983 | file.parentFile.mkdirs() 984 | file << inputs.properties.collect{ key, value -> "$key: $value" }.join('\n') 985 | } 986 | } 987 | 988 | model { 989 | tasks.jar { 990 | into("META-INF/maven/$project.group/$project.name") { 991 | from generatePomFileForMavenPublication 992 | rename ".*.xml", "pom.xml" 993 | from generatePomPropertiesFile 994 | } 995 | } 996 | } 997 | 998 | tasks.withType(JavaCompile).configureEach { 999 | it.options.encoding = StandardCharsets.UTF_8 1000 | } 1001 | 1002 | tasks.withType(GroovyCompile).configureEach { 1003 | it.options.encoding = StandardCharsets.UTF_8 1004 | } 1005 | 1006 | tasks.withType(Test).configureEach { 1007 | it.systemProperty JvmOptions.FILE_ENCODING_KEY, StandardCharsets.UTF_8 1008 | } 1009 | 1010 | tasks.withType(Javadoc).configureEach { 1011 | it.with { 1012 | options.encoding = StandardCharsets.UTF_8 1013 | // StandardJavadocDocletOptions 1014 | options.charSet = StandardCharsets.UTF_8 1015 | options.docEncoding = StandardCharsets.UTF_8 1016 | } 1017 | } 1018 | 1019 | jar.manifest { 1020 | attributes 'Automatic-Module-Name': 'module-name' 1021 | } 1022 | 1023 | publishing.publications { 1024 | maven(MavenPublication) { 1025 | from components.java 1026 | } 1027 | } 1028 | 1029 | task.jacocoTestReport.xml.required.set(true) 1030 | 1031 | tasks.register('install') { 1032 | dependsOn: publishToMavenLocal 1033 | group: 'publishing' 1034 | doLast { 1035 | logger.warn "INSTALLED $project.group:$project.name:$project.version" 1036 | } 1037 | } 1038 | ``` 1039 | 1040 | #### Java platform boilerplate 1041 | 1042 | ```groovy 1043 | plugins { id 'java-platform' } 1044 | 1045 | apply plugin: 'ru.vyarus.pom' 1046 | 1047 | javaPlatform.allowDependencies() 1048 | 1049 | maven.pom { 1050 | name = 'custom-name' // if differs from project name 1051 | description = 'custom description' 1052 | } 1053 | 1054 | publishing.publications { 1055 | bom(MavenPublication) { 1056 | from components.javaPlatform 1057 | artifactId = 'custom-name' // if differs from project name 1058 | } 1059 | } 1060 | 1061 | jacocoTestReport.reports.xml.required.set(true) 1062 | 1063 | tasks.register('install') { 1064 | dependsOn: publishToMavenLocal 1065 | group: 'publishing' 1066 | doLast { 1067 | logger.warn "INSTALLED $project.group:custom-name:$project.version" 1068 | } 1069 | } 1070 | ``` 1071 | 1072 | #### Reports aggregation boilerplate 1073 | 1074 | ```groovy 1075 | task test (type: TestReport, description: 'Generates aggregated test report') { 1076 | group = 'verification' 1077 | destinationDir = project.file("${project.buildDir}/reports/tests/test") 1078 | reportOn project.subprojects.findAll { it.plugins.hasPlugin(JavaPlugin) }.test 1079 | } 1080 | 1081 | def projectsWithCoverage = project.subprojects.findAll { it.plugins.hasPlugin(JacocoPlugin) } 1082 | 1083 | task jacocoTestReport (type: JacocoReport, description: 'Generates aggregated jacoco coverage report') { 1084 | dependsOn 'test' 1085 | group = 'verification' 1086 | executionData project.files(projectsWithCoverage 1087 | .collect { it.file("${it.buildDir}/jacoco/test.exec") }) 1088 | .filter { it.exists() } 1089 | sourceDirectories.from = project.files(projectsWithCoverage.sourceSets.main.allSource.srcDirs) 1090 | classDirectories.from = project.files(projectsWithCoverage.sourceSets.main.output) 1091 | reports.xml.destination = project.file("$project.buildDir/reports/jacoco/test/jacocoTestReport.xml") 1092 | reports.xml.required.set(true) 1093 | reports.html.destination = project.file("$project.buildDir/reports/jacoco/test/html/") 1094 | } 1095 | 1096 | htmlDependencyReport.projects = project.allprojects 1097 | ``` 1098 | 1099 | #### Utility boilerplate 1100 | 1101 | Signing: 1102 | 1103 | ```groovy 1104 | signing { 1105 | sign publishing.publications.maven // or bom 1106 | required = { !project.version.toString().endsWith('SNAPSHOT') } 1107 | } 1108 | ``` 1109 | 1110 | Gradle metadata disabling 1111 | 1112 | ```groovy 1113 | tasks.withType(GenerateModuleMetadata).configureEach { 1114 | enabled = false 1115 | } 1116 | ``` 1117 | 1118 | Open report: 1119 | 1120 | ```groovy 1121 | task openDependencyReport(description: 'Opens gradle htmlDependencyReport in browser', group: 'help') { 1122 | dependsOn 'htmlDependencyReport' 1123 | doLast { 1124 | java.awt.Desktop.desktop.open(file("build/reports/project/dependencies/root.${project.name}.html)) 1125 | } 1126 | } 1127 | ``` 1128 | 1129 | ### Might also like 1130 | 1131 | * [quality-plugin](https://github.com/xvik/gradle-quality-plugin) - java and groovy source quality checks 1132 | * [github-info-plugin](https://github.com/xvik/gradle-github-info-plugin) - pre-configure common plugins with github related info 1133 | * [animalsniffer-plugin](https://github.com/xvik/gradle-animalsniffer-plugin) - java compatibility checks 1134 | * [mkdocs-plugin](https://github.com/xvik/gradle-mkdocs-plugin) - project documentation generator 1135 | * [java-library generator](https://github.com/xvik/generator-lib-java) - java library project generator 1136 | 1137 | --- 1138 | [![gradle plugin generator](http://img.shields.io/badge/Powered%20by-%20Gradle%20plugin%20generator-green.svg?style=flat-square)](https://github.com/xvik/generator-gradle-plugin) 1139 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.gradle.plugin-publish' version '1.3.1' 3 | id 'java-gradle-plugin' 4 | id 'groovy' 5 | id 'jacoco' 6 | id 'signing' 7 | id 'net.researchgate.release' version '3.1.0' 8 | id 'ru.vyarus.quality' version '5.0.0' 9 | id 'io.github.gradle-nexus.publish-plugin' version '2.0.0' 10 | id 'ru.vyarus.java-lib' version '3.0.0' 11 | id 'ru.vyarus.github-info' version '2.0.0' 12 | id 'com.github.ben-manes.versions' version '0.52.0' 13 | id "pl.droidsonroids.jacoco.testkit" version "1.0.12" 14 | } 15 | 16 | java { 17 | sourceCompatibility = 1.8 18 | } 19 | 20 | wrapper { 21 | gradleVersion = '8.6' 22 | distributionType = Wrapper.DistributionType.BIN 23 | } 24 | 25 | repositories { mavenLocal(); mavenCentral(); gradlePluginPortal() } 26 | dependencies { 27 | implementation 'ru.vyarus:gradle-pom-plugin:3.0.0' 28 | 29 | testImplementation('org.spockframework:spock-core:2.3-groovy-3.0') { 30 | exclude group: 'org.codehaus.groovy' 31 | } 32 | testImplementation 'com.gradle.publish:plugin-publish-plugin:1.3.1' 33 | } 34 | 35 | group = 'ru.vyarus' 36 | description = 'Gradle Java-lib plugin' 37 | 38 | github { 39 | user 'xvik' 40 | license 'MIT' 41 | } 42 | 43 | maven.pom { 44 | developers { 45 | developer { 46 | id = 'xvik' 47 | name = 'Vyacheslav Rusakov' 48 | email = 'vyarus@gmail.com' 49 | } 50 | } 51 | } 52 | 53 | nexusPublishing { 54 | repositories { 55 | sonatype { 56 | username = findProperty('sonatypeUser') 57 | password = findProperty('sonatypePassword') 58 | } 59 | } 60 | } 61 | 62 | // skip signing for jitpack (snapshots) 63 | tasks.withType(Sign) {onlyIf { !System.getenv('JITPACK') }} 64 | 65 | // Required signing properties for release: signing.keyId, signing.password and signing.secretKeyRingFile 66 | // (https://docs.gradle.org/current/userguide/signing_plugin.html#sec:signatory_credentials) 67 | 68 | javaLib { 69 | // don't publish gradle metadata artifact 70 | withoutGradleMetadata() 71 | } 72 | 73 | 74 | gradlePlugin { 75 | plugins { 76 | javaLibPlugin { 77 | id = 'ru.vyarus.java-lib' 78 | displayName = project.description 79 | description = 'Common gradle configuration for Java or Groovy library' 80 | tags.set(['java', 'groovy', 'lib']) 81 | implementationClass = 'ru.vyarus.gradle.plugin.lib.JavaLibPlugin' 82 | } 83 | } 84 | } 85 | 86 | release.git.requireBranch.set('master') 87 | 88 | afterReleaseBuild { 89 | dependsOn = [ 90 | 'publishMavenPublicationToSonatypeRepository', 91 | 'closeAndReleaseSonatypeStagingRepository', 92 | publishPlugins 93 | ] 94 | doLast { 95 | logger.warn "RELEASED $project.group:$project.name:$project.version" 96 | } 97 | } 98 | 99 | test { 100 | useJUnitPlatform() 101 | testLogging { 102 | events 'skipped', 'failed' 103 | exceptionFormat 'full' 104 | } 105 | maxHeapSize = '512m' 106 | doLast { 107 | sleep(1000) 108 | } 109 | } 110 | 111 | dependencyUpdates.revision = 'release' 112 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | version=3.0.1-SNAPSHOT -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xvik/gradle-java-lib-plugin/59ad479c9e74ae110d3686d401511b8b45781835/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 87 | APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit 88 | 89 | # Use the maximum available, or set MAX_FD != -1 to use that value. 90 | MAX_FD=maximum 91 | 92 | warn () { 93 | echo "$*" 94 | } >&2 95 | 96 | die () { 97 | echo 98 | echo "$*" 99 | echo 100 | exit 1 101 | } >&2 102 | 103 | # OS specific support (must be 'true' or 'false'). 104 | cygwin=false 105 | msys=false 106 | darwin=false 107 | nonstop=false 108 | case "$( uname )" in #( 109 | CYGWIN* ) cygwin=true ;; #( 110 | Darwin* ) darwin=true ;; #( 111 | MSYS* | MINGW* ) msys=true ;; #( 112 | NONSTOP* ) nonstop=true ;; 113 | esac 114 | 115 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 116 | 117 | 118 | # Determine the Java command to use to start the JVM. 119 | if [ -n "$JAVA_HOME" ] ; then 120 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 121 | # IBM's JDK on AIX uses strange locations for the executables 122 | JAVACMD=$JAVA_HOME/jre/sh/java 123 | else 124 | JAVACMD=$JAVA_HOME/bin/java 125 | fi 126 | if [ ! -x "$JAVACMD" ] ; then 127 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 128 | 129 | Please set the JAVA_HOME variable in your environment to match the 130 | location of your Java installation." 131 | fi 132 | else 133 | JAVACMD=java 134 | if ! command -v java >/dev/null 2>&1 135 | then 136 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | fi 142 | 143 | # Increase the maximum file descriptors if we can. 144 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 145 | case $MAX_FD in #( 146 | max*) 147 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 148 | # shellcheck disable=SC2039,SC3045 149 | MAX_FD=$( ulimit -H -n ) || 150 | warn "Could not query maximum file descriptor limit" 151 | esac 152 | case $MAX_FD in #( 153 | '' | soft) :;; #( 154 | *) 155 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 156 | # shellcheck disable=SC2039,SC3045 157 | ulimit -n "$MAX_FD" || 158 | warn "Could not set maximum file descriptor limit to $MAX_FD" 159 | esac 160 | fi 161 | 162 | # Collect all arguments for the java command, stacking in reverse order: 163 | # * args from the command line 164 | # * the main class name 165 | # * -classpath 166 | # * -D...appname settings 167 | # * --module-path (only if needed) 168 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 169 | 170 | # For Cygwin or MSYS, switch paths to Windows format before running java 171 | if "$cygwin" || "$msys" ; then 172 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 173 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 174 | 175 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 176 | 177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 178 | for arg do 179 | if 180 | case $arg in #( 181 | -*) false ;; # don't mess with options #( 182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 183 | [ -e "$t" ] ;; #( 184 | *) false ;; 185 | esac 186 | then 187 | arg=$( cygpath --path --ignore --mixed "$arg" ) 188 | fi 189 | # Roll the args list around exactly as many times as the number of 190 | # args, so each arg winds up back in the position where it started, but 191 | # possibly modified. 192 | # 193 | # NB: a `for` loop captures its iteration list before it begins, so 194 | # changing the positional parameters here affects neither the number of 195 | # iterations, nor the values presented in `arg`. 196 | shift # remove old arg 197 | set -- "$@" "$arg" # push replacement arg 198 | done 199 | fi 200 | 201 | 202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 204 | 205 | # Collect all arguments for the java command: 206 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 207 | # and any embedded shellness will be escaped. 208 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 209 | # treated as '${Hostname}' itself on the command line. 210 | 211 | set -- \ 212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 213 | -classpath "$CLASSPATH" \ 214 | org.gradle.wrapper.GradleWrapperMain \ 215 | "$@" 216 | 217 | # Stop when "xargs" is not available. 218 | if ! command -v xargs >/dev/null 2>&1 219 | then 220 | die "xargs is not available" 221 | fi 222 | 223 | # Use "xargs" to parse quoted args. 224 | # 225 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 226 | # 227 | # In Bash we could simply go: 228 | # 229 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 230 | # set -- "${ARGS[@]}" "$@" 231 | # 232 | # but POSIX shell has neither arrays nor command substitution, so instead we 233 | # post-process each arg (as a line of input to sed) to backslash-escape any 234 | # character that might be a shell metacharacter, then use eval to reverse 235 | # that process (while maintaining the separation between arguments), and wrap 236 | # the whole thing up as a single "set" statement. 237 | # 238 | # This will of course break if any of these variables contains a newline or 239 | # an unmatched quote. 240 | # 241 | 242 | eval "set -- $( 243 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 244 | xargs -n1 | 245 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 246 | tr '\n' ' ' 247 | )" '"$@"' 248 | 249 | exec "$JAVACMD" "$@" 250 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 1>&2 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 48 | echo. 1>&2 49 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 50 | echo location of your Java installation. 1>&2 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 1>&2 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 62 | echo. 1>&2 63 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 64 | echo location of your Java installation. 1>&2 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | mavenLocal() 4 | gradlePluginPortal() 5 | } 6 | } 7 | 8 | rootProject.name = 'gradle-java-lib-plugin' 9 | -------------------------------------------------------------------------------- /src/main/groovy/ru/vyarus/gradle/plugin/lib/JavaLibExtension.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import groovy.transform.CompileStatic 4 | import org.gradle.api.Action 5 | import org.gradle.api.Project 6 | 7 | /** 8 | * Java-lib plugin extension. Accessible as `javaLib` closure. 9 | * 10 | * @author Vyacheslav Rusakov 11 | * @since 06.06.2021 12 | */ 13 | @CompileStatic 14 | @SuppressWarnings('ConfusingMethodName') 15 | class JavaLibExtension { 16 | 17 | private final Project project 18 | 19 | JavaLibExtension(Project project) { 20 | this.project = project 21 | } 22 | 23 | /** 24 | * Java-platform plugin related configurations. 25 | */ 26 | JavaPlatform bom = new JavaPlatform() 27 | 28 | /** 29 | * Automatic-Module-Name meta-inf property value (java 9 modules). 30 | * Object used as type to allow lazy-evaluated GStrings. 31 | */ 32 | Object autoModuleName 33 | 34 | // ----------------------------------- method-based configuration 35 | // (properties accessible, but not supposed to be used) 36 | 37 | boolean gradleMetadata = true 38 | boolean addJavadoc = true 39 | boolean addSources = true 40 | boolean publication = true 41 | boolean aggregatedReports = false 42 | 43 | /** 44 | * Disable gradle metadata publishing. Metadata files contains additional gradle dependencies semantic which 45 | * is impossible to express in pom file. In majority of cases this file is not required and may be excluded 46 | * to avoid publishing additional artifact (besides, some repos might complain about it). 47 | */ 48 | void withoutGradleMetadata() { 49 | gradleMetadata = false 50 | } 51 | 52 | /** 53 | * Disable javadoc (groovydoc) publication. 54 | * Ignored with java-publish plugin. 55 | */ 56 | void withoutJavadoc() { 57 | addJavadoc = false 58 | } 59 | 60 | /** 61 | * Disable sources publication. 62 | * Ignored with java-publish plugin. 63 | */ 64 | void withoutSources() { 65 | addSources = false 66 | } 67 | 68 | /** 69 | * Disable all publications. Might be used to disable configured BOM publication or any sub-module publication. 70 | */ 71 | void withoutPublication() { 72 | publication = false 73 | } 74 | 75 | /** 76 | * Aggregate test, jacoco coverage and dependency reports for subprojects (assuming 1 level hierarchy). 77 | * This option will work with "base" plugin (often used in root project to allow grouping). 78 | *

79 | * IMPORTANT: must be used in the root project or any subproject containing other subprojects. 80 | *

81 | * Aggregates only direct subprojects (ignoring lower levels). 82 | *

83 | * For jacoco reports aggregation jacoco plugin must be active. Jacoco report aggregation is important for 84 | * coverage services integration (they require single aggregated report; when aggregation enabled, report 85 | * path would be the same as with single module: build/reports/jacoco/test/jacocoTestReport.xml) 86 | *

87 | * Dependencies html report grouping activated if report-plugin is applied. 88 | */ 89 | void aggregateReports() { 90 | aggregatedReports = true 91 | } 92 | 93 | // ----------------------------------- Utility methods required for sub objects configuration 94 | 95 | /** 96 | * Bom sub-object configuration. Used only with java-platform plugin when platform declared in the root project. 97 | * 98 | * @param config configuration action 99 | */ 100 | void bom(Action config) { 101 | config.execute(bom) 102 | } 103 | 104 | /** 105 | * Configuration for java-platform plugin. Required for case when java-platform is declared in the root project, 106 | * but published bom maven coordinates must differ from root project name. 107 | */ 108 | static class JavaPlatform { 109 | /** 110 | * Used with java-platform plugin when platform is declared in the root module to rename artifact (which is by 111 | * default equal to project name) 112 | */ 113 | String artifactId 114 | 115 | /** 116 | * Used with java-platform plugin when platform is declared in the root module to specify custom description in 117 | * the generated pom (otherwise it would be root project description). 118 | */ 119 | String description 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/groovy/ru/vyarus/gradle/plugin/lib/JavaLibPlugin.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import groovy.transform.CompileStatic 4 | import groovy.transform.TypeCheckingMode 5 | import org.gradle.api.Action 6 | import org.gradle.api.DefaultTask 7 | import org.gradle.api.GradleException 8 | import org.gradle.api.Plugin 9 | import org.gradle.api.Project 10 | import org.gradle.api.Task 11 | import org.gradle.api.java.archives.Attributes 12 | import org.gradle.api.plugins.* 13 | import org.gradle.api.provider.Provider 14 | import org.gradle.api.publish.PublishingExtension 15 | import org.gradle.api.publish.maven.MavenPublication 16 | import org.gradle.api.publish.maven.tasks.AbstractPublishToMaven 17 | import org.gradle.api.publish.maven.tasks.PublishToMavenLocal 18 | import org.gradle.api.publish.maven.tasks.PublishToMavenRepository 19 | import org.gradle.api.publish.tasks.GenerateModuleMetadata 20 | import org.gradle.api.reporting.ConfigurableReport 21 | import org.gradle.api.reporting.SingleFileReport 22 | import org.gradle.api.reporting.dependencies.HtmlDependencyReportTask 23 | import org.gradle.api.tasks.Copy 24 | import org.gradle.api.tasks.SourceSetContainer 25 | import org.gradle.api.tasks.TaskCollection 26 | import org.gradle.api.tasks.compile.GroovyCompile 27 | import org.gradle.api.tasks.compile.JavaCompile 28 | import org.gradle.api.tasks.javadoc.Javadoc 29 | import org.gradle.api.tasks.testing.Test 30 | import org.gradle.api.tasks.testing.TestReport 31 | import org.gradle.jvm.tasks.Jar 32 | import org.gradle.plugins.signing.Sign 33 | import org.gradle.plugins.signing.SigningExtension 34 | import org.gradle.plugins.signing.SigningPlugin 35 | import org.gradle.process.internal.JvmOptions 36 | import org.gradle.testing.jacoco.plugins.JacocoPlugin 37 | import org.gradle.testing.jacoco.tasks.JacocoReport 38 | import org.gradle.util.GradleVersion 39 | import ru.vyarus.gradle.plugin.pom.PomExtension 40 | import ru.vyarus.gradle.plugin.pom.PomPlugin 41 | 42 | import java.nio.charset.StandardCharsets 43 | 44 | /** 45 | * Plugin performs common configuration for java or groovy library: 46 | *

55 | *

56 | * When used with java-platform plugin: 57 | *

64 | * Java-publish might be used in the root project (for multi-module project) and in this case custom artifact name 65 | * would be required (most likely, BOM artifact should not be called the same as project name. For this case 66 | * special extension must be used: {@code libJava.bom.artifactId = 'something-bom'}. Name in the generated pom would be 67 | * changed accordingly. Also, {@code libJava.bom.description} may be used to specify custom description instead 68 | * of root project description. 69 | *

70 | * Also, in the root project reports aggregation might be enabled with {@code javaLib.aggregateReports()}. 71 | * When enabled aggregates test reports, coverage report (jacoco plugin) and dependency report (project-report plugin). 72 | * Aggregation might be used with at least "base" plugin (but may be also with java-platform). 73 | *

74 | * In case of gradle plugin (java-gradle-plugin + plugin-publish) "pluginMaven" publication will be created for 75 | * plugins portal publication, but java-lib plugin will still use "maven" publication (for maven central 76 | * publication). 77 | * Overall, in case of gradle plugin, 2 maven publications should be used, but exactly the same artifacts would 78 | * be published everywhere (plugin portal will additionally receive alias publications). 79 | * 80 | * @author Vyacheslav Rusakov 81 | * @since 07.11.2015 82 | * @see JavaLibExtension for options (javaLib closure in gradle) 83 | */ 84 | @SuppressWarnings('DuplicateStringLiteral') 85 | @CompileStatic(TypeCheckingMode.SKIP) 86 | class JavaLibPlugin implements Plugin { 87 | 88 | @Override 89 | void apply(Project project) { 90 | // always creating extension to avoid hard to track mis-references in multi-module projects 91 | JavaLibExtension extension = project.extensions.create('javaLib', JavaLibExtension, project) 92 | 93 | // partial activation for java-platform plugin (when root module is a BOM) 94 | project.plugins.withType(JavaPlatformPlugin) { 95 | project.plugins.apply(PomPlugin) 96 | // different name used for publication 97 | MavenPublication bom = configureBomPublication(project) 98 | configurePlatform(project, extension, bom) 99 | configureGradleMetadata(project, extension) 100 | disablePublication(project, extension) 101 | configureSigning(project, bom) 102 | 103 | Provider name = project.provider { "$project.group:$bom.artifactId:$project.version" } 104 | addInstallTask(project, extension) { 105 | it.logger.warn "INSTALLED ${name.get()}" 106 | } 107 | } 108 | 109 | // full activation when java plugin is enabled 110 | project.plugins.withType(JavaPlugin) { 111 | project.plugins.apply(PomPlugin) 112 | // assume gradle 5.0 and above - stable publishing enabled 113 | MavenPublication publication = configureMavenPublication(project) 114 | configureEncoding(project) 115 | configureJar(project, publication) 116 | addJavadocAndSourceJars(project, extension) 117 | configureGradleMetadata(project, extension) 118 | disablePublication(project, extension) 119 | configureSigning(project, publication) 120 | applyAutoModuleName(project, extension) 121 | enableJacocoXmlReport(project) 122 | 123 | Provider name = project.provider { "$project.group:$project.name:$project.version" } 124 | addInstallTask(project, extension) { 125 | it.logger.warn "INSTALLED ${name.get()}" 126 | } 127 | } 128 | 129 | // extension applied with base plugin because it's often used in the root project for grouping 130 | project.plugins.withType(BasePlugin) { 131 | aggregateReports(project, extension) 132 | } 133 | 134 | // helper task to open dependency report in browser 135 | addOpenDependencyReportTask(project) 136 | } 137 | 138 | private void configurePlatform(Project project, JavaLibExtension extension, MavenPublication bom) { 139 | project.configure(project) { 140 | // allow dependencies declaration in BOM 141 | javaPlatform.allowDependencies() 142 | 143 | // for configuration cache support it must be direct link to simle pojo 144 | JavaLibExtension.JavaPlatform model = extension.bom 145 | // actual processing would be delayed by xml processing time in pom plugin 146 | project.extensions.getByType(PomExtension).pom { 147 | if (model?.artifactId) { 148 | // by default artifact name is project name and if root bom would be published it should 149 | // have a different name 150 | bom.artifactId = model.artifactId 151 | name = model.artifactId 152 | } 153 | if (model?.description) { 154 | description = model.description 155 | } 156 | } 157 | } 158 | } 159 | 160 | private void configureEncoding(Project project) { 161 | project.tasks.withType(JavaCompile).configureEach { 162 | it.options.encoding = StandardCharsets.UTF_8 163 | } 164 | 165 | project.tasks.withType(GroovyCompile).configureEach { 166 | it.options.encoding = StandardCharsets.UTF_8 167 | } 168 | 169 | project.tasks.withType(Test).configureEach { 170 | it.systemProperty JvmOptions.FILE_ENCODING_KEY, StandardCharsets.UTF_8 171 | } 172 | 173 | project.tasks.withType(Javadoc).configureEach { 174 | it.with { 175 | options.encoding = StandardCharsets.UTF_8 176 | // StandardJavadocDocletOptions 177 | options.charSet = StandardCharsets.UTF_8 178 | options.docEncoding = StandardCharsets.UTF_8 179 | } 180 | } 181 | } 182 | 183 | private void configureJar(Project project, MavenPublication publication) { 184 | project.tasks.register('generatePomPropertiesFile') { 185 | it.with { 186 | inputs.properties([ 187 | 'version': "${ -> project.version }", 188 | 'groupId': "${ -> project.group }", 189 | 'artifactId': "${ -> project.name }", 190 | ]) 191 | outputs.file project.layout.buildDirectory.file('generatePomPropertiesFile/pom.properties') 192 | doLast { 193 | File file = outputs.files.singleFile 194 | file.parentFile.mkdirs() 195 | file << inputs.properties.collect { key, value -> "$key: $value" }.join('\n') 196 | } 197 | } 198 | } 199 | project.configure(project) { 200 | // delayed to be able to use version 201 | afterEvaluate { 202 | // do not override user attributes 203 | tasks.named('jar').configure { 204 | Attributes attributes = it.manifest.attributes 205 | putIfAbsent(attributes, 'Implementation-Title', project.description ?: project.name) 206 | putIfAbsent(attributes, 'Implementation-Version', project.version) 207 | putIfAbsent(attributes, 'Built-By', System.getProperty('user.name')) 208 | putIfAbsent(attributes, 'Built-Date', new Date()) 209 | putIfAbsent(attributes, 'Built-JDK', System.getProperty('java.version')) 210 | putIfAbsent(attributes, 'Built-Gradle', project.gradle.gradleVersion) 211 | putIfAbsent(attributes, 'Target-JDK', project.extensions 212 | .getByType(JavaPluginExtension).targetCompatibility) 213 | } 214 | } 215 | 216 | project.tasks.named('processResources', Copy).configure { 217 | it.with { 218 | into("META-INF/maven/$project.group/$project.name") { 219 | from project.tasks.named("generatePomFileFor${publication.name.capitalize()}Publication") 220 | rename '.*.xml', 'pom.xml' 221 | from project.tasks.named('generatePomPropertiesFile') 222 | } 223 | } 224 | } 225 | } 226 | } 227 | 228 | @SuppressWarnings('Indentation') 229 | private void addJavadocAndSourceJars(Project project, JavaLibExtension extension) { 230 | // use gradle native configuration method to aovid clashes with plugin-publish 1.0 231 | JavaPluginExtension javaExt = project.extensions.getByType(JavaPluginExtension) 232 | javaExt.withJavadocJar() 233 | javaExt.withSourcesJar() 234 | project.afterEvaluate { 235 | if (!extension.addJavadoc || !extension.addSources) { 236 | project.extensions.getByType(SourceSetContainer) 237 | .named('main').configure { sourceSet -> 238 | if (!extension.addJavadoc) { 239 | project.tasks.named(sourceSet.javadocJarTaskName).configure { 240 | it.enabled = false 241 | } 242 | } 243 | if (!extension.addSources) { 244 | project.tasks.named(sourceSet.sourcesJarTaskName).configure { 245 | it.enabled = false 246 | } 247 | } 248 | } 249 | } 250 | } 251 | } 252 | 253 | private MavenPublication configureMavenPublication(Project project) { 254 | // Configure publication: 255 | // java-gradle-plugin will create its own publication pluginMaven, but still plugin configures separate 256 | // maven publication because java-gradle-plugin most likely will be applied after java-lib and so 257 | // it's not possible to detect it for sure. But it's not a problem: pom will be corrected for both 258 | // (and in any case portal does not use this pom). 259 | // NOTE: java-gradle-plugin will also create alias publications for each plugin, but we will simply don't 260 | // use them 261 | MavenPublication publication = project.extensions 262 | .findByType(PublishingExtension) 263 | .publications 264 | .maybeCreate('maven', MavenPublication) 265 | publication.from(project.components.getByName('java')) 266 | // in stable publication mode extra jars added directly after tasks registration 267 | return publication 268 | } 269 | 270 | private MavenPublication configureBomPublication(Project project) { 271 | MavenPublication publication = project.extensions 272 | .findByType(PublishingExtension) 273 | .publications 274 | .maybeCreate('bom', MavenPublication) 275 | publication.from(project.components.getByName('javaPlatform')) 276 | // in stable publication mode extra jars added directly after tasks registration 277 | return publication 278 | } 279 | 280 | private void addInstallTask(Project project, JavaLibExtension extension, Action last) { 281 | Provider publication = project.provider { extension.publication } 282 | project.tasks.register('install') { 283 | it.with { 284 | dependsOn 'publishToMavenLocal' 285 | group = 'publishing' 286 | description = 'Publish to local maven repository (alias for publishToMavenLocal)' 287 | doLast { 288 | // show message only if publication not disabled 289 | if (publication.get()) { 290 | last.execute(it) 291 | } 292 | } 293 | } 294 | } 295 | } 296 | 297 | private void configureGradleMetadata(Project project, JavaLibExtension extension) { 298 | project.afterEvaluate { 299 | // disable gradle metadata publishing (usually it confuse a lot) 300 | if (!extension.gradleMetadata) { 301 | project.tasks.withType(GenerateModuleMetadata).configureEach { 302 | enabled = false 303 | } 304 | } 305 | } 306 | } 307 | 308 | private void disablePublication(Project project, JavaLibExtension extension) { 309 | project.afterEvaluate { 310 | if (!extension.publication) { 311 | project.tasks.withType(PublishToMavenRepository).configureEach { 312 | enabled = extension.publication 313 | } 314 | project.tasks.withType(PublishToMavenLocal).configureEach { 315 | enabled = false 316 | } 317 | } 318 | } 319 | } 320 | 321 | private void configureSigning(Project project, MavenPublication publication) { 322 | project.plugins.withType(SigningPlugin) { 323 | // https://docs.gradle.org/current/userguide/signing_plugin.html#sec:signatory_credentials 324 | SigningExtension ext = project.extensions.getByType(SigningExtension) 325 | ext.sign publication 326 | ext.required = { !project.version.toString().endsWith('SNAPSHOT') } 327 | 328 | // Fix Gradle warning about signing tasks using publishing task outputs without explicit dependencies 329 | // https://github.com/gradle/gradle/issues/26091 330 | project.tasks.withType(AbstractPublishToMaven).configureEach { 331 | TaskCollection signingTasks = project.tasks.withType(Sign) 332 | mustRunAfter(signingTasks) 333 | } 334 | } 335 | } 336 | 337 | private void applyAutoModuleName(Project project, JavaLibExtension extension) { 338 | project.afterEvaluate { 339 | if (extension.autoModuleName) { 340 | // java 11 auto module name 341 | (project.tasks.jar as Jar).manifest { 342 | attributes 'Automatic-Module-Name': extension.autoModuleName 343 | } 344 | } 345 | } 346 | } 347 | 348 | private void addOpenDependencyReportTask(Project project) { 349 | project.plugins.withType(ProjectReportsPlugin) { 350 | project.tasks.register('openDependencyReport').configure { 351 | (it as DefaultTask).with { 352 | group = 'help' 353 | dependsOn 'htmlDependencyReport' 354 | description = 'Opens gradle htmlDependencyReport in browser' 355 | // prevent calling task on all subprojects 356 | impliesSubProjects = true 357 | doLast { 358 | File report = project.file("build/reports/project/dependencies/root.${project.name}.html") 359 | if (!report.exists()) { 360 | // for multi-module project root, if reports aggregation enabled name would be different 361 | report = project.file('build/reports/project/dependencies/root.html') 362 | } 363 | java.awt.Desktop.desktop.open(report) 364 | } 365 | } 366 | } 367 | } 368 | } 369 | 370 | private void enableJacocoXmlReport(Project project) { 371 | // by default jacoco xml report is disabled, but its required for coverage services 372 | project.plugins.withType(JacocoPlugin) { 373 | project.tasks.named('jacocoTestReport').configure { 374 | (it as JacocoReport).reports.xml.required.set(true) 375 | } 376 | } 377 | } 378 | 379 | @SuppressWarnings(['AbcMetric', 'MethodSize']) 380 | private void aggregateReports(Project project, JavaLibExtension extension) { 381 | project.afterEvaluate { 382 | if (!extension.aggregatedReports) { 383 | return 384 | } 385 | // makes no sense otherwise 386 | if (project.subprojects.empty) { 387 | throw new GradleException('javaLib.aggregateReports() could not be used on project ' + 388 | "'$project.name' because does not contain subprojects") 389 | } 390 | if (project.plugins.hasPlugin(JavaPlugin)) { 391 | throw new GradleException('javaLib.aggregateReports() could not be used on project ' + 392 | "'$project.name' because it contains java sources. If this is a root project use 'base' " + 393 | 'plugin instead.') 394 | } 395 | 396 | // aggregate test reports from subprojects 397 | project.tasks.register('test', TestReport) { 398 | it.with { 399 | description = 'Generates aggregated test report' 400 | // show task in common place 401 | group = 'verification' 402 | if (GradleVersion.current() < GradleVersion.version('8.0')) { 403 | destinationDir = project.file("${project.buildDir}/reports/tests/test") 404 | reportOn project.subprojects 405 | .findAll { it.plugins.hasPlugin(JavaPlugin) }.test 406 | } else { 407 | destinationDirectory.set(project.layout.buildDirectory.dir('reports/tests/test')) 408 | testResults.from(project.subprojects 409 | .findAll { it.plugins.hasPlugin(JavaPlugin) }.test) 410 | } 411 | } 412 | } 413 | 414 | // aggregate jacoco coverage from subprojects 415 | project.plugins.withType(JacocoPlugin) { 416 | Set projectsWithCoverage = project.subprojects 417 | .findAll { it.plugins.hasPlugin(JacocoPlugin) } 418 | 419 | project.tasks.register('jacocoTestReport', JacocoReport) { 420 | it.with { 421 | description = 'Generates aggregated jacoco coverage report' 422 | dependsOn 'test' 423 | // show task in common place 424 | group = 'verification' 425 | executionData project.files(projectsWithCoverage 426 | .collect { it.layout.buildDirectory.file('jacoco/test.exec') }) 427 | .filter { it.exists() } 428 | sourceDirectories.from = selectFiles(projectsWithCoverage) { SourceSetContainer sourceSets -> 429 | sourceSets.main.allSource.srcDirs 430 | } 431 | classDirectories.from = selectFiles(projectsWithCoverage) { SourceSetContainer sourceSets -> 432 | sourceSets.main.output.files 433 | } 434 | // use same location as in single-module case 435 | reportDestination(reports.xml, project, 'reports/jacoco/test/jacocoTestReport.xml') 436 | reportDestination(reports.html, project, 'reports/jacoco/test/html/') 437 | reports.xml.required.set(true) 438 | } 439 | } 440 | } 441 | 442 | // aggregated html dependency report 443 | project.plugins.withType(ProjectReportsPlugin) { 444 | project.tasks.named('htmlDependencyReport').configure { 445 | (it as HtmlDependencyReportTask).projects = project.allprojects 446 | } 447 | } 448 | } 449 | } 450 | 451 | private Set selectFiles(Set projects, Closure> extractor) { 452 | Set res = [] 453 | projects.forEach { 454 | res.addAll(extractor.call(it.extensions.getByType(SourceSetContainer))) 455 | } 456 | res 457 | } 458 | 459 | private void putIfAbsent(Attributes attributes, String name, Object value) { 460 | if (!attributes.containsKey(name)) { 461 | attributes.put(name, value) 462 | } 463 | } 464 | 465 | @SuppressWarnings('Instanceof') 466 | private void reportDestination(ConfigurableReport report, Project project, String path) { 467 | if (GradleVersion.current() < GradleVersion.version('8.0')) { 468 | report.destination = project.file("$project.buildDir/$path") 469 | } else { 470 | if (report instanceof SingleFileReport) { 471 | report.outputLocation.set(project.layout.buildDirectory.get().file(path)) 472 | } else { 473 | report.outputLocation.set(project.layout.buildDirectory.dir(path)) 474 | } 475 | } 476 | } 477 | } 478 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/AbstractKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.testkit.runner.BuildResult 4 | import org.gradle.testkit.runner.GradleRunner 5 | import spock.lang.Specification 6 | import spock.lang.TempDir 7 | 8 | /** 9 | * @author Vyacheslav Rusakov 10 | * @since 18.11.2015 11 | */ 12 | abstract class AbstractKitTest extends Specification { 13 | 14 | boolean debug 15 | @TempDir File testProjectDir 16 | File buildFile 17 | 18 | def setup() { 19 | buildFile = file('build.gradle') 20 | // jacoco coverage support 21 | fileFromClasspath('gradle.properties', 'testkit-gradle.properties') 22 | // override maven local repository 23 | // (see org.gradle.api.internal.artifacts.mvnsettings.DefaultLocalMavenRepositoryLocator.getLocalMavenRepository) 24 | System.setProperty("maven.repo.local", new File(testProjectDir, "build/repo").getAbsolutePath()) 25 | } 26 | 27 | def build(String file) { 28 | buildFile << file 29 | } 30 | 31 | File file(String path) { 32 | new File(testProjectDir, path) 33 | } 34 | 35 | File fileFromClasspath(String toFile, String source) { 36 | File target = file(toFile) 37 | target.parentFile.mkdirs() 38 | target.withOutputStream { 39 | it.write((getClass().getResourceAsStream(source) ?: getClass().classLoader.getResourceAsStream(source)).bytes) 40 | } 41 | target 42 | } 43 | 44 | /** 45 | * Enable it and run test with debugger (no manual attach required). Not always enabled to speed up tests during 46 | * normal execution. 47 | */ 48 | def debug() { 49 | debug = true 50 | } 51 | 52 | String projectName() { 53 | return testProjectDir.getName() 54 | } 55 | 56 | GradleRunner gradle(File root, String... commands) { 57 | GradleRunner.create() 58 | .withProjectDir(root) 59 | .withArguments((commands + ['--stacktrace']) as String[]) 60 | .withPluginClasspath() 61 | .withDebug(debug) 62 | .forwardOutput() 63 | } 64 | 65 | GradleRunner gradle(String... commands) { 66 | gradle(testProjectDir, commands) 67 | } 68 | 69 | BuildResult run(String... commands) { 70 | return gradle(commands).build() 71 | } 72 | 73 | BuildResult runFailed(String... commands) { 74 | return gradle(commands).buildAndFail() 75 | } 76 | 77 | BuildResult runVer(String gradleVersion, String... commands) { 78 | return gradle(commands).withGradleVersion(gradleVersion).build() 79 | } 80 | 81 | BuildResult runFailedVer(String gradleVersion, String... commands) { 82 | return gradle(commands).withGradleVersion(gradleVersion).buildAndFail() 83 | } 84 | 85 | protected String unifyString(String input) { 86 | return input 87 | // cleanup win line break for simpler comparisons 88 | .replace("\r", '') 89 | } 90 | 91 | Set withoutModuleFile(File deployDir) { 92 | // gradle 6 publish additional module file (for extended dependencies model) 93 | (deployDir.list() as Set).findAll {!it.endsWith('.module')} 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/AbstractTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.api.Project 4 | import org.gradle.testfixtures.ProjectBuilder 5 | import spock.lang.Specification 6 | import spock.lang.TempDir 7 | 8 | /** 9 | * @author Vyacheslav Rusakov 10 | * @since 18.11.2015 11 | */ 12 | abstract class AbstractTest extends Specification { 13 | 14 | @TempDir File testProjectDir 15 | 16 | Project project(Closure config = null) { 17 | projectBuilder(config).build() 18 | } 19 | 20 | ExtendedProjectBuilder projectBuilder(Closure root = null) { 21 | new ExtendedProjectBuilder().root(testProjectDir, root) 22 | } 23 | 24 | File file(String path) { 25 | new File(testProjectDir, path) 26 | } 27 | 28 | File fileFromClasspath(String toFile, String source) { 29 | File target = file(toFile) 30 | target.parentFile.mkdirs() 31 | target << getClass().getResourceAsStream(source).text 32 | } 33 | 34 | static class ExtendedProjectBuilder { 35 | Project root 36 | 37 | ExtendedProjectBuilder root(File dir, Closure config = null) { 38 | assert root == null, "Root project already declared" 39 | Project project = ProjectBuilder.builder() 40 | .withProjectDir(dir).build() 41 | if (config) { 42 | project.configure(project, config) 43 | } 44 | root = project 45 | return this 46 | } 47 | 48 | /** 49 | * Direct child of parent project 50 | * 51 | * @param name child project name 52 | * @param config optional configuration closure 53 | * @return builder 54 | */ 55 | ExtendedProjectBuilder child(String name, Closure config = null) { 56 | return childOf(null, name, config) 57 | } 58 | 59 | /** 60 | * Direct child of any registered child project 61 | * 62 | * @param projectRef name of required parent module (gradle project reference format: `:some:deep:module`) 63 | * @param name child project name 64 | * @param config optional configuration closure 65 | * @return builder 66 | */ 67 | ExtendedProjectBuilder childOf(String projectRef, String name, Closure config = null) { 68 | assert root != null, "Root project not declared" 69 | Project parent = projectRef == null ? root : root.project(projectRef) 70 | File folder = parent.file(name) 71 | if (!folder.exists()) { 72 | folder.mkdir() 73 | } 74 | Project project = ProjectBuilder.builder() 75 | .withName(name) 76 | .withProjectDir(folder) 77 | .withParent(parent) 78 | .build() 79 | if (config) { 80 | project.configure(project, config) 81 | } 82 | return this 83 | } 84 | 85 | /** 86 | * Evaluate configuration. 87 | * 88 | * @return root project 89 | */ 90 | Project build() { 91 | if (root.subprojects) { 92 | linkSubprojectsEvaluation(root) 93 | } 94 | root.evaluate() 95 | return root 96 | } 97 | 98 | private void linkSubprojectsEvaluation(Project project) { 99 | project.evaluationDependsOnChildren() 100 | project.subprojects.each { linkSubprojectsEvaluation(it) } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/ConfigurationCacheSupportKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.testkit.runner.BuildResult 4 | import org.gradle.testkit.runner.TaskOutcome 5 | 6 | import java.util.zip.ZipFile 7 | 8 | /** 9 | * @author Vyacheslav Rusakov 10 | * @since 02.03.2024 11 | */ 12 | class ConfigurationCacheSupportKitTest extends AbstractKitTest { 13 | 14 | def "Check install task"() { 15 | setup: 16 | file('src/main/java').mkdirs() 17 | build """ 18 | plugins { 19 | id 'java' 20 | id 'ru.vyarus.java-lib' 21 | } 22 | 23 | group 'ru.vyarus' 24 | version 1.0 25 | """ 26 | 27 | when: "run pom task" 28 | BuildResult result = run('--configuration-cache', '--configuration-cache-problems=warn', 'install') 29 | 30 | 31 | String artifactId = projectName() 32 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 33 | 34 | then: "no configuration cache incompatibilities" 35 | result.output.contains("1 problem was found storing the configuration cache") 36 | result.output.contains('Gradle runtime: support for using a Java agent with TestKit') 37 | result.output.contains('Calculating task graph as no cached configuration is available for tasks:') 38 | 39 | then: "task done" 40 | result.task(":install").outcome == TaskOutcome.SUCCESS 41 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 42 | 43 | then: "artifacts deployed" 44 | deploy.exists() 45 | def baseName = artifactId + '-1.0' 46 | withoutModuleFile(deploy) == 47 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 48 | 49 | 50 | when: "run from cache" 51 | println '\n\n------------------- FROM CACHE ----------------------------------------' 52 | result = run('--configuration-cache', '--configuration-cache-problems=warn', 'install') 53 | 54 | then: "cache used" 55 | result.output.contains('Reusing configuration cache.') 56 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 57 | } 58 | 59 | 60 | 61 | def "Check reports aggregation"() { 62 | setup: 63 | build """ 64 | plugins { 65 | id 'base' 66 | id 'jacoco' 67 | id 'project-report' 68 | id 'ru.vyarus.java-lib' 69 | } 70 | 71 | javaLib { 72 | aggregateReports() 73 | } 74 | 75 | allprojects { 76 | repositories { mavenCentral() } 77 | } 78 | 79 | subprojects { 80 | apply plugin: 'groovy' 81 | apply plugin: 'jacoco' 82 | apply plugin: 'project-report' 83 | apply plugin: 'ru.vyarus.java-lib' 84 | 85 | dependencies { 86 | testImplementation 'org.spockframework:spock-core:2.3-groovy-3.0' 87 | } 88 | 89 | test { 90 | useJUnitPlatform() 91 | } 92 | } 93 | """ 94 | file('settings.gradle') << "include 'sub1', 'sub2'" 95 | 96 | fileFromClasspath('sub1/src/main/java/sample/Sample.java', '/sample/Sample.java') 97 | fileFromClasspath('sub1/src/test/groovy/sample/SampleTest.groovy', '/sample/SampleTest.groovy') 98 | 99 | fileFromClasspath('sub2/src/main/java/sample/Sample2.java', '/sample/Sample2.java') 100 | fileFromClasspath('sub2/src/test/groovy/sample/SampleTest2.groovy', '/sample/SampleTest2.groovy') 101 | 102 | when: "run test task" 103 | def result = run('--configuration-cache', '--configuration-cache-problems=warn', 'test') 104 | 105 | then: "no configuration cache incompatibilities" 106 | result.output.contains("1 problem was found storing the configuration cache") 107 | result.output.contains('Gradle runtime: support for using a Java agent with TestKit') 108 | result.output.contains('Calculating task graph as no cached configuration is available for tasks:') 109 | 110 | then: "task done" 111 | result.task(":test").outcome == TaskOutcome.SUCCESS 112 | 113 | then: "test report created" 114 | def test = file('build/reports/tests/test/index.html') 115 | test.exists() 116 | 117 | when: "run coverage task" 118 | result = run('--configuration-cache', '--configuration-cache-problems=warn', 'clean', 'jacocoTestReport') 119 | 120 | then: "no configuration cache incompatibilities" 121 | result.output.contains("1 problem was found storing the configuration cache") 122 | result.output.contains('Gradle runtime: support for using a Java agent with TestKit') 123 | result.output.contains('Calculating task graph as no cached configuration is available for tasks:') 124 | 125 | then: "task done" 126 | result.task(":jacocoTestReport").outcome == TaskOutcome.SUCCESS 127 | 128 | then: "coverage aggregated" 129 | def cov = file('build/reports/jacoco/test/jacocoTestReport.xml') 130 | cov.exists() 131 | cov.length() > 0 132 | 133 | when: "run dependencies task" 134 | result = run('--configuration-cache', '--configuration-cache-problems=warn', 'htmlDependencyReport') 135 | 136 | then: "no configuration cache incompatibilities" 137 | result.output.contains("1 problem was found storing the configuration cache") 138 | result.output.contains('Gradle runtime: support for using a Java agent with TestKit') 139 | result.output.contains('Calculating task graph as no cached configuration is available for tasks:') 140 | 141 | then: "task done" 142 | result.task(":htmlDependencyReport").outcome == TaskOutcome.SUCCESS 143 | 144 | then: "aggregated dependency report" 145 | file('build/reports/project/dependencies/root.sub1.html').exists() 146 | file('build/reports/project/dependencies/root.sub2.html').exists() 147 | file('build/reports/project/dependencies/root.html').exists() 148 | 149 | 150 | 151 | when: "run test task from cache" 152 | println '\n\n------------------- FROM CACHE ----------------------------------------' 153 | result = run('--configuration-cache', '--configuration-cache-problems=warn', 'test') 154 | 155 | then: "cache used" 156 | result.output.contains('Reusing configuration cache.') 157 | 158 | then: "task done" 159 | result.task(":test").outcome == TaskOutcome.UP_TO_DATE 160 | 161 | then: "test report created" 162 | test.exists() 163 | 164 | when: "run coverage task" 165 | result = run('--configuration-cache', '--configuration-cache-problems=warn', 'clean', 'jacocoTestReport') 166 | 167 | then: "cache used" 168 | result.output.contains('Reusing configuration cache.') 169 | 170 | then: "task done" 171 | result.task(":jacocoTestReport").outcome == TaskOutcome.SUCCESS 172 | 173 | then: "coverage aggregated" 174 | cov.exists() 175 | cov.length() > 0 176 | 177 | when: "run dependencies task" 178 | result = run('--configuration-cache', '--configuration-cache-problems=warn', 'htmlDependencyReport') 179 | 180 | then: "cache used" 181 | result.output.contains('Reusing configuration cache.') 182 | 183 | then: "task done" 184 | result.task(":htmlDependencyReport").outcome == TaskOutcome.SUCCESS 185 | 186 | then: "aggregated dependency report" 187 | file('build/reports/project/dependencies/root.sub1.html').exists() 188 | file('build/reports/project/dependencies/root.sub2.html').exists() 189 | file('build/reports/project/dependencies/root.html').exists() 190 | } 191 | 192 | 193 | def "Check automatic signing"() { 194 | setup: 195 | file('src/main/java').mkdirs() 196 | build """ 197 | plugins { 198 | id 'java' 199 | id 'signing' 200 | id 'ru.vyarus.java-lib' 201 | } 202 | 203 | javaLib { 204 | withoutGradleMetadata() 205 | withoutJavadoc() 206 | withoutSources() 207 | } 208 | 209 | group 'ru.vyarus' 210 | version 1.0 211 | 212 | ext['signing.keyId']='78065050' 213 | ext['signing.password']= 214 | ext['signing.secretKeyRingFile']='test.gpg' 215 | """ 216 | fileFromClasspath('test.gpg', '/cert/test.gpg') 217 | file('settings.gradle') << """ 218 | rootProject.name = "test" 219 | """ 220 | 221 | when: "run pom task" 222 | BuildResult result = run('--configuration-cache', '--configuration-cache-problems=warn', 'install') 223 | 224 | 225 | String artifactId = 'test' 226 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 227 | 228 | then: "no configuration cache incompatibilities" 229 | result.output.contains("1 problem was found storing the configuration cache") 230 | result.output.contains('Gradle runtime: support for using a Java agent with TestKit') 231 | result.output.contains('Calculating task graph as no cached configuration is available for tasks:') 232 | 233 | then: "task done" 234 | result.task(":install").outcome == TaskOutcome.SUCCESS 235 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 236 | 237 | then: "artifacts deployed" 238 | deploy.exists() 239 | def baseName = artifactId + '-1.0' 240 | withoutModuleFile(deploy) == 241 | ["${baseName}.jar", "${baseName}.pom", "${baseName}.jar.asc", "${baseName}.pom.asc"] as Set 242 | 243 | 244 | when: "run from cache" 245 | println '\n\n------------------- FROM CACHE ----------------------------------------' 246 | result = run('--configuration-cache', '--configuration-cache-problems=warn', 'install') 247 | 248 | then: "cache used" 249 | result.output.contains('Reusing configuration cache.') 250 | } 251 | 252 | 253 | 254 | def "Check current publish plugin with signing integration correctness"() { 255 | setup: 256 | fileFromClasspath('src/main/java/ru/vyarus/TestPlugin.java', '/sample/TestPlugin.java') 257 | 258 | build """ 259 | plugins { 260 | id 'com.gradle.plugin-publish' version '1.2.1' 261 | id 'java-gradle-plugin' 262 | id 'ru.vyarus.java-lib' 263 | id 'java' 264 | id 'signing' 265 | } 266 | 267 | gradlePlugin { 268 | plugins { 269 | testPlugin { 270 | description = 'Test plugin' 271 | tags.set(['java']) 272 | id = 'ru.vyarus.test' 273 | implementationClass = 'ru.vyarus.TestPlugin' 274 | } 275 | } 276 | } 277 | 278 | maven.pom { 279 | name = 'customName' 280 | } 281 | 282 | group 'ru.vyarus' 283 | version 1.0 284 | 285 | ext['signing.keyId']='78065050' 286 | ext['signing.password']= 287 | ext['signing.secretKeyRingFile']='test.gpg' 288 | """ 289 | fileFromClasspath('test.gpg', '/cert/test.gpg') 290 | file('settings.gradle') << """ 291 | rootProject.name = "test" 292 | """ 293 | 294 | when: "run pom task" 295 | def result = run('--configuration-cache', '--configuration-cache-problems=warn', 'install') 296 | 297 | 298 | String artifactId = 'test' 299 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 300 | 301 | then: "no configuration cache incompatibilities" 302 | result.output.contains("1 problem was found storing the configuration cache") 303 | result.output.contains('Gradle runtime: support for using a Java agent with TestKit') 304 | result.output.contains('Calculating task graph as no cached configuration is available for tasks:') 305 | 306 | then: "task done" 307 | result.task(":install").outcome == TaskOutcome.SUCCESS 308 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 309 | 310 | then: "alias publication created" 311 | result.task(":publishMavenPublicationToMavenLocal").outcome == TaskOutcome.SUCCESS 312 | result.task(":publishTestPluginPluginMarkerMavenPublicationToMavenLocal").outcome == TaskOutcome.SUCCESS 313 | 314 | then: "custom jar tasks used" 315 | result.task(":sourcesJar").outcome == TaskOutcome.SUCCESS 316 | result.task(":javadocJar").outcome == TaskOutcome.SUCCESS 317 | 318 | then: "plugin descriptors generation executed" 319 | result.task(":pluginDescriptors").outcome == TaskOutcome.SUCCESS 320 | 321 | then: "artifacts deployed" 322 | deploy.exists() 323 | def baseName = artifactId + '-1.0' 324 | withoutModuleFile(deploy) == 325 | ["${baseName}.jar", "${baseName}.jar.asc", 326 | "${baseName}.pom", "${baseName}.pom.asc", 327 | "${baseName}-sources.jar", "${baseName}-sources.jar.asc", 328 | "${baseName}-javadoc.jar", "${baseName}-javadoc.jar.asc", 329 | "${baseName}.module.asc"] as Set 330 | 331 | then: "jar modifiers applied" 332 | ZipFile jar = new ZipFile(file("build/repo/ru/vyarus/$artifactId/1.0/${baseName}.jar")) 333 | String manifest = jar.getInputStream(jar.getEntry('META-INF/MANIFEST.MF')).text 334 | println manifest 335 | manifest.contains("Implementation-Title: $artifactId") 336 | manifest.contains("Implementation-Version: 1.0") 337 | manifest.contains("Built-By: ${System.getProperty('user.name')}") 338 | manifest.contains("Built-Date:") 339 | manifest.contains("Built-JDK:") 340 | manifest.contains("Built-Gradle:") 341 | manifest.contains("Target-JDK:") 342 | 343 | then: "jar contains pom" 344 | String jarPom = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.xml")).text 345 | println jarPom 346 | jarPom != null 347 | jarPom.contains("ru.vyarus") 348 | jarPom.contains("$artifactId") 349 | 350 | then: "pom closure applied" 351 | jarPom.contains("customName") 352 | 353 | then: "jar contains pom.properties" 354 | String props = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.properties")).text 355 | println props 356 | props != null 357 | props.contains('groupId: ru.vyarus') 358 | props.contains("artifactId: $artifactId") 359 | props.contains('version: 1.0') 360 | 361 | then: "jar contains plugin desriptor" 362 | String gradleDesc = jar.getInputStream(jar.getEntry("META-INF/gradle-plugins/ru.vyarus.test.properties")).text 363 | println gradleDesc 364 | gradleDesc.trim() == 'implementation-class=ru.vyarus.TestPlugin' 365 | 366 | 367 | when: "run from cache" 368 | println '\n\n------------------- FROM CACHE ----------------------------------------' 369 | result = run('--configuration-cache', '--configuration-cache-problems=warn', 'install') 370 | 371 | then: "cache used" 372 | result.output.contains('Reusing configuration cache.') 373 | 374 | cleanup: 375 | jar?.close() 376 | } 377 | } 378 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/EncodingConfigurationTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.api.Project 4 | 5 | /** 6 | * @author Vyacheslav Rusakov 7 | * @since 09.11.2019 8 | */ 9 | class EncodingConfigurationTest extends AbstractTest { 10 | 11 | def "Check encoding set for java tasks"() { 12 | 13 | when: "activating plugin" 14 | file('src/main/java').mkdirs() 15 | Project project = project { 16 | apply plugin: 'java' 17 | apply plugin: "ru.vyarus.java-lib" 18 | } 19 | 20 | then: "compile tasks affected" 21 | project.tasks.compileJava.options.encoding == 'UTF-8' 22 | project.tasks.compileTestJava.options.encoding == 'UTF-8' 23 | 24 | then: "javadoc affected" 25 | project.tasks.javadoc.options.encoding == 'UTF-8' 26 | project.tasks.javadoc.options.charSet == 'UTF-8' 27 | project.tasks.javadoc.options.docEncoding == 'UTF-8' 28 | 29 | then: "test sys property set" 30 | project.tasks.test.allJvmArgs.contains('-Dfile.encoding=UTF-8') 31 | } 32 | 33 | def "Check encoding set for groovy tasks"() { 34 | 35 | when: "activating plugin" 36 | file('src/main/java').mkdirs() 37 | file('src/main/groovy').mkdirs() 38 | Project project = project { 39 | apply plugin: 'groovy' 40 | apply plugin: "ru.vyarus.java-lib" 41 | } 42 | 43 | then: "compile tasks affected" 44 | project.tasks.compileJava.options.encoding == 'UTF-8' 45 | project.tasks.compileGroovy.options.encoding == 'UTF-8' 46 | project.tasks.compileGroovy.groovyOptions.encoding == 'UTF-8' 47 | project.tasks.compileTestJava.options.encoding == 'UTF-8' 48 | project.tasks.compileTestGroovy.options.encoding == 'UTF-8' 49 | project.tasks.compileTestGroovy.groovyOptions.encoding == 'UTF-8' 50 | 51 | then: "javadoc affected" 52 | project.tasks.javadoc.options.encoding == 'UTF-8' 53 | project.tasks.javadoc.options.charSet == 'UTF-8' 54 | project.tasks.javadoc.options.docEncoding == 'UTF-8' 55 | 56 | then: "test sys property set" 57 | project.tasks.test.allJvmArgs.contains('-Dfile.encoding=UTF-8') 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/GradleMetadataDisableKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.testkit.runner.TaskOutcome 4 | 5 | /** 6 | * @author Vyacheslav Rusakov 7 | * @since 06.06.2021 8 | */ 9 | class GradleMetadataDisableKitTest extends AbstractKitTest { 10 | 11 | def "Check metadata disable"() { 12 | setup: 13 | file('src/main/java').mkdirs() 14 | build """ 15 | plugins { 16 | id 'java' 17 | id 'ru.vyarus.java-lib' 18 | } 19 | 20 | group 'ru.vyarus' 21 | version 1.0 22 | 23 | dependencies { 24 | implementation 'ru.vyarus:guice-validator:2.0.0' 25 | } 26 | 27 | javaLib { 28 | withoutGradleMetadata() 29 | } 30 | """ 31 | 32 | when: "run install task" 33 | def result = run('install') 34 | 35 | String artifactId = projectName() 36 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 37 | 38 | then: "task done" 39 | result.task(":install").outcome == TaskOutcome.SUCCESS 40 | 41 | then: "artifacts deployed" 42 | deploy.exists() 43 | def baseName = artifactId + '-1.0' 44 | deploy.list().size() == 4 45 | withoutModuleFile(deploy) == 46 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 47 | } 48 | 49 | def "Check metadata disable for bom"() { 50 | setup: 51 | file('src/main/java').mkdirs() 52 | build """ 53 | plugins { 54 | id 'java-platform' 55 | id 'ru.vyarus.java-lib' 56 | } 57 | 58 | group 'ru.vyarus' 59 | version 1.0 60 | 61 | dependencies { 62 | constraints { 63 | api 'ru.vyarus:guice-validator:2.0.0' 64 | } 65 | } 66 | 67 | javaLib { 68 | withoutGradleMetadata() 69 | } 70 | """ 71 | 72 | when: "run install task" 73 | def result = run('install') 74 | 75 | String artifactId = projectName() 76 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 77 | 78 | then: "task done" 79 | result.task(":install").outcome == TaskOutcome.SUCCESS 80 | 81 | then: "artifacts deployed" 82 | deploy.exists() 83 | def baseName = artifactId + '-1.0' 84 | deploy.list().size() == 1 85 | withoutModuleFile(deploy) == ["${baseName}.pom"] as Set 86 | } 87 | 88 | def "Check metadata disable in allprojects"() { 89 | setup: 90 | build """ 91 | plugins { 92 | id 'base' 93 | id 'ru.vyarus.java-lib' 94 | } 95 | 96 | allprojects { 97 | println '!!!!!!!!'+it.name 98 | 99 | apply plugin: 'ru.vyarus.java-lib' 100 | 101 | group 'ru.vyarus' 102 | version 1.0 103 | 104 | repositories { mavenCentral() } 105 | 106 | javaLib.withoutGradleMetadata() 107 | } 108 | 109 | subprojects { 110 | apply plugin: 'groovy' 111 | } 112 | """ 113 | file('settings.gradle') << "include 'sub'" 114 | file('sub').mkdirs() 115 | 116 | when: "run install task" 117 | def result = run('install') 118 | 119 | String artifactId = 'sub' 120 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 121 | 122 | then: "task done" 123 | result.task(":sub:install").outcome == TaskOutcome.SUCCESS 124 | 125 | then: "artifacts deployed" 126 | deploy.exists() 127 | def baseName = artifactId + '-1.0' 128 | 129 | then: "pom does not have metadata comment" 130 | def pom = new File(deploy, "${baseName}.pom").text 131 | !pom.contains('') 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/GradlePluginCompatibilityKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.testkit.runner.TaskOutcome 4 | 5 | import java.util.zip.ZipFile 6 | 7 | /** 8 | * @author Vyacheslav Rusakov 9 | * @since 13.11.2019 10 | */ 11 | class GradlePluginCompatibilityKitTest extends AbstractKitTest { 12 | 13 | def "Check legacy publish plugin integration correctness"() { 14 | setup: 15 | fileFromClasspath('src/main/java/ru/vyarus/TestPlugin.java', '/sample/TestPlugin.java') 16 | 17 | build """ 18 | plugins { 19 | id 'com.gradle.plugin-publish' version '0.21.0' 20 | id 'java-gradle-plugin' 21 | id 'ru.vyarus.java-lib' 22 | id 'java' 23 | id 'signing' 24 | } 25 | 26 | gradlePlugin { 27 | plugins { 28 | testPlugin { 29 | id = 'ru.vyarus.test' 30 | implementationClass = 'ru.vyarus.TestPlugin' 31 | } 32 | } 33 | } 34 | pluginBundle { 35 | description = 'Test plugin' 36 | tags = ['java'] 37 | 38 | mavenCoordinates { 39 | groupId = project.group 40 | artifactId = project.name 41 | } 42 | } 43 | 44 | maven.pom { 45 | name = 'customName' 46 | } 47 | 48 | group 'ru.vyarus' 49 | version 1.0 50 | 51 | ext['signing.keyId']='78065050' 52 | ext['signing.password']= 53 | ext['signing.secretKeyRingFile']='test.gpg' 54 | """ 55 | fileFromClasspath('test.gpg', '/cert/test.gpg') 56 | file('settings.gradle') << """ 57 | rootProject.name = "test" 58 | """ 59 | 60 | when: "run pom task" 61 | def result = run('install') 62 | 63 | 64 | String artifactId = 'test' 65 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 66 | 67 | then: "task done" 68 | result.task(":install").outcome == TaskOutcome.SUCCESS 69 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 70 | 71 | then: "alias publication created" 72 | result.task(":publishMavenPublicationToMavenLocal").outcome == TaskOutcome.SUCCESS 73 | result.task(":publishTestPluginPluginMarkerMavenPublicationToMavenLocal").outcome == TaskOutcome.SUCCESS 74 | 75 | then: "custom jar tasks used" 76 | result.task(":sourcesJar").outcome == TaskOutcome.SUCCESS 77 | result.task(":javadocJar").outcome == TaskOutcome.SUCCESS 78 | 79 | then: "plugin-publish did not register custom tasks" 80 | result.task(":publishPluginJar") == null 81 | result.task(":publishPluginJavaDocsJar") == null 82 | result.task(":publishPluginGroovyDocsJar") == null 83 | 84 | then: "plugin descriptors generation executed" 85 | result.task(":pluginDescriptors").outcome == TaskOutcome.SUCCESS 86 | 87 | then: "artifacts deployed" 88 | deploy.exists() 89 | def baseName = artifactId + '-1.0' 90 | withoutModuleFile(deploy) == 91 | ["${baseName}.jar", "${baseName}.jar.asc", 92 | "${baseName}.pom", "${baseName}.pom.asc", 93 | "${baseName}-sources.jar", "${baseName}-sources.jar.asc", 94 | "${baseName}-javadoc.jar", "${baseName}-javadoc.jar.asc", 95 | "${baseName}.module.asc"] as Set 96 | 97 | then: "jar modifiers applied" 98 | ZipFile jar = new ZipFile(file("build/repo/ru/vyarus/$artifactId/1.0/${baseName}.jar")) 99 | String manifest = jar.getInputStream(jar.getEntry('META-INF/MANIFEST.MF')).text 100 | println manifest 101 | manifest.contains("Implementation-Title: $artifactId") 102 | manifest.contains("Implementation-Version: 1.0") 103 | manifest.contains("Built-By: ${System.getProperty('user.name')}") 104 | manifest.contains("Built-Date:") 105 | manifest.contains("Built-JDK:") 106 | manifest.contains("Built-Gradle:") 107 | manifest.contains("Target-JDK:") 108 | 109 | then: "jar contains pom" 110 | String jarPom = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.xml")).text 111 | println jarPom 112 | jarPom != null 113 | jarPom.contains("ru.vyarus") 114 | jarPom.contains("$artifactId") 115 | 116 | then: "pom closure applied" 117 | jarPom.contains("customName") 118 | 119 | then: "jar contains pom.properties" 120 | String props = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.properties")).text 121 | println props 122 | props != null 123 | props.contains('groupId: ru.vyarus') 124 | props.contains("artifactId: $artifactId") 125 | props.contains('version: 1.0') 126 | 127 | then: "jar contains plugin desriptor" 128 | String gradleDesc = jar.getInputStream(jar.getEntry("META-INF/gradle-plugins/ru.vyarus.test.properties")).text 129 | println gradleDesc 130 | gradleDesc.trim() == 'implementation-class=ru.vyarus.TestPlugin' 131 | 132 | cleanup: 133 | jar?.close() 134 | } 135 | 136 | 137 | def "Check current publish plugin integration correctness"() { 138 | setup: 139 | fileFromClasspath('src/main/java/ru/vyarus/TestPlugin.java', '/sample/TestPlugin.java') 140 | 141 | build """ 142 | plugins { 143 | id 'com.gradle.plugin-publish' version '1.2.1' 144 | id 'java-gradle-plugin' 145 | id 'ru.vyarus.java-lib' 146 | id 'java' 147 | } 148 | 149 | gradlePlugin { 150 | plugins { 151 | testPlugin { 152 | description = 'Test plugin' 153 | tags.set(['java']) 154 | id = 'ru.vyarus.test' 155 | implementationClass = 'ru.vyarus.TestPlugin' 156 | } 157 | } 158 | } 159 | 160 | maven.pom { 161 | name = 'customName' 162 | } 163 | 164 | group 'ru.vyarus' 165 | version 1.0 166 | """ 167 | file('settings.gradle') << """ 168 | rootProject.name = "test" 169 | """ 170 | 171 | when: "run pom task" 172 | def result = run('install') 173 | 174 | 175 | String artifactId = 'test' 176 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 177 | 178 | then: "task done" 179 | result.task(":install").outcome == TaskOutcome.SUCCESS 180 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 181 | 182 | then: "alias publication created" 183 | result.task(":publishMavenPublicationToMavenLocal").outcome == TaskOutcome.SUCCESS 184 | result.task(":publishTestPluginPluginMarkerMavenPublicationToMavenLocal").outcome == TaskOutcome.SUCCESS 185 | 186 | then: "custom jar tasks used" 187 | result.task(":sourcesJar").outcome == TaskOutcome.SUCCESS 188 | result.task(":javadocJar").outcome == TaskOutcome.SUCCESS 189 | 190 | then: "plugin descriptors generation executed" 191 | result.task(":pluginDescriptors").outcome == TaskOutcome.SUCCESS 192 | 193 | then: "artifacts deployed" 194 | deploy.exists() 195 | def baseName = artifactId + '-1.0' 196 | withoutModuleFile(deploy) == 197 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 198 | 199 | then: "jar modifiers applied" 200 | ZipFile jar = new ZipFile(file("build/repo/ru/vyarus/$artifactId/1.0/${baseName}.jar")) 201 | String manifest = jar.getInputStream(jar.getEntry('META-INF/MANIFEST.MF')).text 202 | println manifest 203 | manifest.contains("Implementation-Title: $artifactId") 204 | manifest.contains("Implementation-Version: 1.0") 205 | manifest.contains("Built-By: ${System.getProperty('user.name')}") 206 | manifest.contains("Built-Date:") 207 | manifest.contains("Built-JDK:") 208 | manifest.contains("Built-Gradle:") 209 | manifest.contains("Target-JDK:") 210 | 211 | then: "jar contains pom" 212 | String jarPom = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.xml")).text 213 | println jarPom 214 | jarPom != null 215 | jarPom.contains("ru.vyarus") 216 | jarPom.contains("$artifactId") 217 | 218 | then: "pom closure applied" 219 | jarPom.contains("customName") 220 | 221 | then: "jar contains pom.properties" 222 | String props = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.properties")).text 223 | println props 224 | props != null 225 | props.contains('groupId: ru.vyarus') 226 | props.contains("artifactId: $artifactId") 227 | props.contains('version: 1.0') 228 | 229 | then: "jar contains plugin desriptor" 230 | String gradleDesc = jar.getInputStream(jar.getEntry("META-INF/gradle-plugins/ru.vyarus.test.properties")).text 231 | println gradleDesc 232 | gradleDesc.trim() == 'implementation-class=ru.vyarus.TestPlugin' 233 | 234 | cleanup: 235 | jar?.close() 236 | } 237 | 238 | 239 | def "Check current publish plugin with signing integration correctness"() { 240 | setup: 241 | fileFromClasspath('src/main/java/ru/vyarus/TestPlugin.java', '/sample/TestPlugin.java') 242 | 243 | build """ 244 | plugins { 245 | id 'com.gradle.plugin-publish' version '1.2.1' 246 | id 'java-gradle-plugin' 247 | id 'ru.vyarus.java-lib' 248 | id 'java' 249 | id 'signing' 250 | } 251 | 252 | gradlePlugin { 253 | plugins { 254 | testPlugin { 255 | description = 'Test plugin' 256 | tags.set(['java']) 257 | id = 'ru.vyarus.test' 258 | implementationClass = 'ru.vyarus.TestPlugin' 259 | } 260 | } 261 | } 262 | 263 | maven.pom { 264 | name = 'customName' 265 | } 266 | 267 | group 'ru.vyarus' 268 | version 1.0 269 | 270 | ext['signing.keyId']='78065050' 271 | ext['signing.password']= 272 | ext['signing.secretKeyRingFile']='test.gpg' 273 | """ 274 | fileFromClasspath('test.gpg', '/cert/test.gpg') 275 | file('settings.gradle') << """ 276 | rootProject.name = "test" 277 | """ 278 | 279 | when: "run pom task" 280 | def result = run('install') 281 | 282 | 283 | String artifactId = 'test' 284 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 285 | 286 | then: "task done" 287 | result.task(":install").outcome == TaskOutcome.SUCCESS 288 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 289 | 290 | then: "alias publication created" 291 | result.task(":publishMavenPublicationToMavenLocal").outcome == TaskOutcome.SUCCESS 292 | result.task(":publishTestPluginPluginMarkerMavenPublicationToMavenLocal").outcome == TaskOutcome.SUCCESS 293 | 294 | then: "custom jar tasks used" 295 | result.task(":sourcesJar").outcome == TaskOutcome.SUCCESS 296 | result.task(":javadocJar").outcome == TaskOutcome.SUCCESS 297 | 298 | then: "plugin descriptors generation executed" 299 | result.task(":pluginDescriptors").outcome == TaskOutcome.SUCCESS 300 | 301 | then: "artifacts deployed" 302 | deploy.exists() 303 | def baseName = artifactId + '-1.0' 304 | withoutModuleFile(deploy) == 305 | ["${baseName}.jar", "${baseName}.jar.asc", 306 | "${baseName}.pom", "${baseName}.pom.asc", 307 | "${baseName}-sources.jar", "${baseName}-sources.jar.asc", 308 | "${baseName}-javadoc.jar", "${baseName}-javadoc.jar.asc", 309 | "${baseName}.module.asc"] as Set 310 | 311 | then: "jar modifiers applied" 312 | ZipFile jar = new ZipFile(file("build/repo/ru/vyarus/$artifactId/1.0/${baseName}.jar")) 313 | String manifest = jar.getInputStream(jar.getEntry('META-INF/MANIFEST.MF')).text 314 | println manifest 315 | manifest.contains("Implementation-Title: $artifactId") 316 | manifest.contains("Implementation-Version: 1.0") 317 | manifest.contains("Built-By: ${System.getProperty('user.name')}") 318 | manifest.contains("Built-Date:") 319 | manifest.contains("Built-JDK:") 320 | manifest.contains("Built-Gradle:") 321 | manifest.contains("Target-JDK:") 322 | 323 | then: "jar contains pom" 324 | String jarPom = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.xml")).text 325 | println jarPom 326 | jarPom != null 327 | jarPom.contains("ru.vyarus") 328 | jarPom.contains("$artifactId") 329 | 330 | then: "pom closure applied" 331 | jarPom.contains("customName") 332 | 333 | then: "jar contains pom.properties" 334 | String props = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.properties")).text 335 | println props 336 | props != null 337 | props.contains('groupId: ru.vyarus') 338 | props.contains("artifactId: $artifactId") 339 | props.contains('version: 1.0') 340 | 341 | then: "jar contains plugin desriptor" 342 | String gradleDesc = jar.getInputStream(jar.getEntry("META-INF/gradle-plugins/ru.vyarus.test.properties")).text 343 | println gradleDesc 344 | gradleDesc.trim() == 'implementation-class=ru.vyarus.TestPlugin' 345 | 346 | cleanup: 347 | jar?.close() 348 | } 349 | 350 | 351 | def "Check publishing only maven publication (with signing)"() { 352 | setup: 353 | fileFromClasspath('src/main/java/ru/vyarus/TestPlugin.java', '/sample/TestPlugin.java') 354 | 355 | build """ 356 | plugins { 357 | id 'com.gradle.plugin-publish' version '1.2.1' 358 | id 'java-gradle-plugin' 359 | id 'ru.vyarus.java-lib' 360 | id 'java' 361 | id 'signing' 362 | } 363 | 364 | gradlePlugin { 365 | plugins { 366 | testPlugin { 367 | description = 'Test plugin' 368 | tags.set(['java']) 369 | id = 'ru.vyarus.test' 370 | implementationClass = 'ru.vyarus.TestPlugin' 371 | } 372 | } 373 | } 374 | 375 | maven.pom { 376 | name = 'customName' 377 | } 378 | 379 | group 'ru.vyarus' 380 | version 1.0 381 | 382 | ext['signing.keyId']='78065050' 383 | ext['signing.password']= 384 | ext['signing.secretKeyRingFile']='test.gpg' 385 | """ 386 | fileFromClasspath('test.gpg', '/cert/test.gpg') 387 | file('settings.gradle') << """ 388 | rootProject.name = "test" 389 | """ 390 | 391 | when: "run pom task" 392 | def result = run('publishMavenPublicationToMavenLocal') 393 | 394 | 395 | String artifactId = 'test' 396 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 397 | 398 | then: "task done" 399 | result.task(":publishMavenPublicationToMavenLocal").outcome == TaskOutcome.SUCCESS 400 | 401 | then: "custom jar tasks used" 402 | result.task(":sourcesJar").outcome == TaskOutcome.SUCCESS 403 | result.task(":javadocJar").outcome == TaskOutcome.SUCCESS 404 | 405 | then: "plugin descriptors generation executed" 406 | result.task(":pluginDescriptors").outcome == TaskOutcome.SUCCESS 407 | 408 | then: "artifacts deployed" 409 | deploy.exists() 410 | def baseName = artifactId + '-1.0' 411 | withoutModuleFile(deploy) == 412 | ["${baseName}.jar", "${baseName}.jar.asc", 413 | "${baseName}.pom", "${baseName}.pom.asc", 414 | "${baseName}-sources.jar", "${baseName}-sources.jar.asc", 415 | "${baseName}-javadoc.jar", "${baseName}-javadoc.jar.asc", 416 | "${baseName}.module.asc"] as Set 417 | 418 | then: "jar modifiers applied" 419 | ZipFile jar = new ZipFile(file("build/repo/ru/vyarus/$artifactId/1.0/${baseName}.jar")) 420 | String manifest = jar.getInputStream(jar.getEntry('META-INF/MANIFEST.MF')).text 421 | println manifest 422 | manifest.contains("Implementation-Title: $artifactId") 423 | manifest.contains("Implementation-Version: 1.0") 424 | manifest.contains("Built-By: ${System.getProperty('user.name')}") 425 | manifest.contains("Built-Date:") 426 | manifest.contains("Built-JDK:") 427 | manifest.contains("Built-Gradle:") 428 | manifest.contains("Target-JDK:") 429 | 430 | then: "jar contains pom" 431 | String jarPom = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.xml")).text 432 | println jarPom 433 | jarPom != null 434 | jarPom.contains("ru.vyarus") 435 | jarPom.contains("$artifactId") 436 | 437 | then: "pom closure applied" 438 | jarPom.contains("customName") 439 | 440 | then: "jar contains pom.properties" 441 | String props = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.properties")).text 442 | println props 443 | props != null 444 | props.contains('groupId: ru.vyarus') 445 | props.contains("artifactId: $artifactId") 446 | props.contains('version: 1.0') 447 | 448 | then: "jar contains plugin desriptor" 449 | String gradleDesc = jar.getInputStream(jar.getEntry("META-INF/gradle-plugins/ru.vyarus.test.properties")).text 450 | println gradleDesc 451 | gradleDesc.trim() == 'implementation-class=ru.vyarus.TestPlugin' 452 | 453 | cleanup: 454 | jar?.close() 455 | } 456 | } 457 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/GradlePluginCompatibilityTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.api.Project 4 | import ru.vyarus.gradle.plugin.pom.PomPlugin 5 | 6 | /** 7 | * java-gradle-plugin crete separate pluginMaven publication + publication-link for each plugin (alias for plugin). 8 | * plugin-publish creates source and javadoc tasks but avoid this if project.archives already contains them 9 | * 10 | * @author Vyacheslav Rusakov 11 | * @since 13.11.2019 12 | */ 13 | class GradlePluginCompatibilityTest extends AbstractTest { 14 | 15 | def "Check default plugins behaviour"() { 16 | 17 | when: "activating plugin" 18 | file('src/main/java').mkdirs() 19 | Project project = project { 20 | apply plugin: 'com.gradle.plugin-publish' 21 | apply plugin: 'java-gradle-plugin' 22 | apply plugin: 'groovy' 23 | apply plugin: 'maven-publish' 24 | } 25 | 26 | then: "mavenJava publication registered" 27 | project.publishing.publications.names == ["pluginMaven"] as Set 28 | 29 | then: "artifacts initialized" 30 | project.publishing.publications.pluginMaven.artifacts.collect {it.file.name} as Set == ['test.jar', 'test-sources.jar', 'test-javadoc.jar'] as Set 31 | } 32 | 33 | def "Check plugin registration"() { 34 | 35 | when: "activating plugin" 36 | file('src/main/java').mkdirs() 37 | Project project = project { 38 | apply plugin: 'com.gradle.plugin-publish' 39 | apply plugin: 'java-gradle-plugin' 40 | apply plugin: 'ru.vyarus.java-lib' 41 | apply plugin: 'groovy' 42 | } 43 | 44 | then: "java and pom plugins activated" 45 | project.plugins.findPlugin(PomPlugin) 46 | 47 | then: "mavenJava publication used" 48 | project.publishing.publications.names == ['maven', 'pluginMaven'] as Set 49 | 50 | then: "javadoc and sources tasks created" 51 | project.tasks.javadocJar 52 | project.tasks.sourcesJar 53 | 54 | then: "install task created" 55 | project.tasks.install 56 | 57 | then: "artifacts initialized" 58 | project.publishing.publications.maven.artifacts.collect {it.file.name} as Set == ['test.jar', 'test-sources.jar', 'test-javadoc.jar'] as Set 59 | project.publishing.publications.pluginMaven.artifacts.collect {it.file.name} as Set == ['test.jar', 'test-sources.jar', 'test-javadoc.jar'] as Set 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/JarModificationKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import java.util.zip.ZipFile 4 | 5 | /** 6 | * @author Vyacheslav Rusakov 7 | * @since 23.11.2015 8 | */ 9 | class JarModificationKitTest extends AbstractKitTest { 10 | 11 | def "Check jar modification"() { 12 | 13 | setup: 14 | file('src/main/java').mkdirs() 15 | build """ 16 | plugins { 17 | id 'java' 18 | id 'ru.vyarus.java-lib' 19 | } 20 | 21 | group 'ru.vyarus' 22 | version 1.0 23 | """ 24 | file('settings.gradle') << """ 25 | rootProject.name = "test" 26 | """ 27 | 28 | when: "run pom task" 29 | def result = run('install') 30 | 31 | 32 | String artifactId = 'test' 33 | String baseName = artifactId + '-1.0' 34 | ZipFile jar = new ZipFile(file("build/repo/ru/vyarus/$artifactId/1.0/${baseName}.jar")) 35 | 36 | then: "jar manifest correct" 37 | String manifest = jar.getInputStream(jar.getEntry('META-INF/MANIFEST.MF')).text 38 | println manifest 39 | manifest.contains("Implementation-Title: $artifactId") 40 | manifest.contains("Implementation-Version: 1.0") 41 | manifest.contains("Built-By: ${System.getProperty('user.name')}") 42 | manifest.contains("Built-Date:") 43 | manifest.contains("Built-JDK:") 44 | manifest.contains("Built-Gradle:") 45 | manifest.contains("Target-JDK:") 46 | 47 | then: "jar contains pom" 48 | String jarPom = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.xml")).text 49 | jarPom != null 50 | println jarPom 51 | 52 | then: "jar contains pom.properties" 53 | String props = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.properties")).text 54 | props != null 55 | println props 56 | props.contains('groupId: ru.vyarus') 57 | props.contains("artifactId: $artifactId") 58 | props.contains('version: 1.0') 59 | 60 | cleanup: 61 | jar?.close() 62 | } 63 | 64 | def "Check jar manifest override"() { 65 | 66 | setup: 67 | file('src/main/java').mkdirs() 68 | build """ 69 | plugins { 70 | id 'java' 71 | id 'ru.vyarus.java-lib' 72 | } 73 | 74 | group 'ru.vyarus' 75 | version 1.0 76 | 77 | jar { 78 | manifest { 79 | attributes 'Implementation-Title': 'Custom', 80 | 'Target-JDK': '1.0' 81 | } 82 | } 83 | """ 84 | 85 | when: "run pom task" 86 | def result = run('install') 87 | String artifactId = projectName() 88 | String baseName = artifactId + '-1.0' 89 | ZipFile jar = new ZipFile(file("build/repo/ru/vyarus/$artifactId/1.0/${baseName}.jar")) 90 | String manifest = jar.getInputStream(jar.getEntry('META-INF/MANIFEST.MF')).text 91 | println manifest 92 | 93 | then: "user attributes preserved" 94 | manifest.contains("Implementation-Title: Custom") 95 | manifest.contains("Target-JDK: 1.0") 96 | 97 | then: "default attributes added" 98 | manifest.contains("Implementation-Version: 1.0") 99 | manifest.contains("Built-By: ${System.getProperty('user.name')}") 100 | manifest.contains("Built-Date:") 101 | manifest.contains("Built-JDK:") 102 | manifest.contains("Built-Gradle:") 103 | 104 | cleanup: 105 | jar?.close() 106 | } 107 | 108 | def "Check auto module name appliance"() { 109 | 110 | setup: 111 | file('src/main/java').mkdirs() 112 | build """ 113 | plugins { 114 | id 'java' 115 | id 'ru.vyarus.java-lib' 116 | } 117 | 118 | group 'ru.vyarus' 119 | version 1.0 120 | 121 | javaLib.autoModuleName = "\$project.group-test" 122 | """ 123 | 124 | when: "run pom task" 125 | def result = run('install') 126 | String artifactId = projectName() 127 | String baseName = artifactId + '-1.0' 128 | ZipFile jar = new ZipFile(file("build/repo/ru/vyarus/$artifactId/1.0/${baseName}.jar")) 129 | String manifest = jar.getInputStream(jar.getEntry('META-INF/MANIFEST.MF')).text 130 | println manifest 131 | 132 | then: "module name applied" 133 | manifest.contains("Automatic-Module-Name: ru.vyarus-test") 134 | 135 | cleanup: 136 | jar?.close() 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/JavaLibPluginKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.testkit.runner.TaskOutcome 4 | 5 | /** 6 | * @author Vyacheslav Rusakov 7 | * @since 10.11.2015 8 | */ 9 | class JavaLibPluginKitTest extends AbstractKitTest { 10 | 11 | def "Check install task"() { 12 | setup: 13 | file('src/main/java').mkdirs() 14 | build """ 15 | plugins { 16 | id 'java' 17 | id 'ru.vyarus.java-lib' 18 | } 19 | 20 | group 'ru.vyarus' 21 | version 1.0 22 | """ 23 | 24 | when: "run pom task" 25 | def result = run('install') 26 | 27 | 28 | String artifactId = projectName() 29 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 30 | 31 | then: "task done" 32 | result.task(":install").outcome == TaskOutcome.SUCCESS 33 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 34 | 35 | then: "artifacts deployed" 36 | deploy.exists() 37 | def baseName = artifactId + '-1.0' 38 | withoutModuleFile(deploy) == 39 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 40 | } 41 | 42 | def "Check jar only publish"() { 43 | setup: 44 | file('src/main/java').mkdirs() 45 | build """ 46 | plugins { 47 | id 'java' 48 | id 'ru.vyarus.java-lib' 49 | } 50 | 51 | javaLib { 52 | withoutJavadoc() 53 | withoutSources() 54 | } 55 | 56 | group 'ru.vyarus' 57 | version 1.0 58 | """ 59 | 60 | when: "run pom task" 61 | def result = run('install') 62 | 63 | 64 | String artifactId = projectName() 65 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 66 | 67 | then: "task done" 68 | result.task(":install").outcome == TaskOutcome.SUCCESS 69 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 70 | 71 | then: "artifacts deployed" 72 | deploy.exists() 73 | def baseName = artifactId + '-1.0' 74 | withoutModuleFile(deploy) == 75 | ["${baseName}.jar", "${baseName}.pom"] as Set 76 | } 77 | 78 | def "Check install task for groovy"() { 79 | setup: 80 | file('src/main/groovy').mkdirs() 81 | build """ 82 | plugins { 83 | id 'groovy' 84 | id 'ru.vyarus.java-lib' 85 | } 86 | 87 | group 'ru.vyarus' 88 | version 1.0 89 | """ 90 | 91 | when: "run pom task" 92 | def result = run('install') 93 | 94 | 95 | String artifactId = projectName() 96 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 97 | 98 | then: "task done" 99 | result.task(":install").outcome == TaskOutcome.SUCCESS 100 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 101 | 102 | then: "artifacts deployed" 103 | deploy.exists() 104 | def baseName = artifactId + '-1.0' 105 | // javadoc will be produced instead of groovydoc! important for maven central 106 | withoutModuleFile(deploy) == 107 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 108 | } 109 | 110 | def "Check install for both sources"() { 111 | setup: 112 | file('src/main/java').mkdirs() 113 | file('src/main/groovy').mkdirs() 114 | build """ 115 | plugins { 116 | id 'groovy' 117 | id 'ru.vyarus.java-lib' 118 | } 119 | 120 | group 'ru.vyarus' 121 | version 1.0 122 | """ 123 | 124 | when: "run pom task" 125 | def result = run('install') 126 | 127 | 128 | String artifactId = projectName() 129 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 130 | 131 | then: "task done" 132 | result.task(":install").outcome == TaskOutcome.SUCCESS 133 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 134 | 135 | then: "artifacts deployed" 136 | deploy.exists() 137 | def baseName = artifactId + '-1.0' 138 | withoutModuleFile(deploy) == 139 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 140 | } 141 | 142 | def "Check install for no sources"() { 143 | setup: 144 | build """ 145 | plugins { 146 | id 'groovy' 147 | id 'ru.vyarus.java-lib' 148 | } 149 | 150 | group 'ru.vyarus' 151 | version 1.0 152 | """ 153 | 154 | when: "run pom task" 155 | def result = run('install') 156 | 157 | 158 | String artifactId = projectName() 159 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 160 | 161 | then: "task done" 162 | result.task(":install").outcome == TaskOutcome.SUCCESS 163 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 164 | 165 | then: "artifacts deployed" 166 | deploy.exists() 167 | def baseName = artifactId + '-1.0' 168 | withoutModuleFile(deploy) == 169 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 170 | } 171 | 172 | def "Check behaviour on test sources"() { 173 | setup: 174 | file('src/test/java').mkdirs() 175 | file('src/test/groovy').mkdirs() 176 | build """ 177 | plugins { 178 | id 'groovy' 179 | id 'ru.vyarus.java-lib' 180 | } 181 | 182 | group 'ru.vyarus' 183 | version 1.0 184 | """ 185 | 186 | when: "run pom task" 187 | def result = run('install') 188 | 189 | 190 | String artifactId = projectName() 191 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 192 | 193 | then: "task done" 194 | result.task(":install").outcome == TaskOutcome.SUCCESS 195 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 196 | 197 | then: "artifacts deployed" 198 | deploy.exists() 199 | def baseName = artifactId + '-1.0' 200 | withoutModuleFile(deploy) == 201 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 202 | } 203 | } -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/JavaLibPluginTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.api.Project 4 | import org.gradle.testing.jacoco.tasks.JacocoReport 5 | import ru.vyarus.gradle.plugin.pom.PomPlugin 6 | 7 | /** 8 | * @author Vyacheslav Rusakov 9 | * @since 07.11.2015 10 | */ 11 | class JavaLibPluginTest extends AbstractTest { 12 | 13 | def "Check plugin registration"() { 14 | 15 | when: "activating plugin" 16 | file('src/main/java').mkdirs() 17 | Project project = project { 18 | apply plugin: 'java' 19 | apply plugin: "ru.vyarus.java-lib" 20 | } 21 | 22 | then: "java and pom plugins activated" 23 | project.plugins.findPlugin(PomPlugin) 24 | 25 | then: "mavenJava publication registered" 26 | project.publishing.publications.maven 27 | 28 | then: "javadoc and sources tasks created" 29 | project.tasks.javadocJar 30 | project.tasks.sourcesJar 31 | 32 | then: "install task created" 33 | project.tasks.install 34 | } 35 | 36 | def "Check plugin registration for groovy"() { 37 | 38 | when: "activating plugin" 39 | file('src/main/groovy').mkdirs() 40 | Project project = project { 41 | apply plugin: 'groovy' 42 | apply plugin: "ru.vyarus.java-lib" 43 | } 44 | 45 | then: "java and pom plugins activated" 46 | project.plugins.findPlugin(PomPlugin) 47 | 48 | then: "mavenJava publication registered" 49 | project.publishing.publications.maven 50 | 51 | then: "javadoc and sources tasks created" 52 | project.tasks.javadocJar 53 | project.tasks.sourcesJar 54 | 55 | then: "install task created" 56 | project.tasks.install 57 | } 58 | 59 | def "Check plugin registration for java-library"() { 60 | 61 | when: "activating plugin" 62 | file('src/main/java').mkdirs() 63 | Project project = project { 64 | apply plugin: 'java-library' 65 | apply plugin: "ru.vyarus.java-lib" 66 | } 67 | 68 | then: "java and pom plugins activated" 69 | project.plugins.findPlugin(PomPlugin) 70 | 71 | then: "mavenJava publication registered" 72 | project.publishing.publications.maven 73 | 74 | then: "javadoc and sources tasks created" 75 | project.tasks.javadocJar 76 | project.tasks.sourcesJar 77 | 78 | then: "install task created" 79 | project.tasks.install 80 | } 81 | 82 | def "Check plugin registration for java-platform"() { 83 | 84 | when: "activating plugin" 85 | file('src/main/java').mkdirs() 86 | Project project = project { 87 | apply plugin: 'java-platform' 88 | apply plugin: "ru.vyarus.java-lib" 89 | } 90 | 91 | then: "pom plugin activated" 92 | project.plugins.findPlugin(PomPlugin) 93 | 94 | then: "bom publication registered" 95 | project.publishing.publications.bom 96 | 97 | then: "install task created" 98 | project.tasks.install 99 | } 100 | 101 | def "Check jacoco xml report active"() { 102 | 103 | when: "activating plugin" 104 | file('src/main/java').mkdirs() 105 | Project project = project { 106 | apply plugin: 'java' 107 | apply plugin: 'jacoco' 108 | apply plugin: "ru.vyarus.java-lib" 109 | } 110 | 111 | then: "xml report active" 112 | (project.tasks.findByName('jacocoTestReport') as JacocoReport).reports.xml.required.get() 113 | } 114 | } -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/JavaPlatformKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import groovy.xml.XmlParser 4 | import org.gradle.testkit.runner.TaskOutcome 5 | 6 | /** 7 | * @author Vyacheslav Rusakov 8 | * @since 06.06.2021 9 | */ 10 | class JavaPlatformKitTest extends AbstractKitTest { 11 | 12 | def "Check install task for BOM"() { 13 | setup: 14 | file('src/main/java').mkdirs() 15 | build """ 16 | plugins { 17 | id 'java-platform' 18 | id 'ru.vyarus.java-lib' 19 | } 20 | 21 | group 'ru.vyarus' 22 | version 1.0 23 | 24 | dependencies { 25 | constraints { 26 | api 'ru.vyarus:guice-validator:2.0.0' 27 | } 28 | } 29 | """ 30 | 31 | when: "run install task" 32 | def result = run('install') 33 | 34 | 35 | String artifactId = projectName() 36 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 37 | 38 | then: "task done" 39 | result.task(":install").outcome == TaskOutcome.SUCCESS 40 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 41 | 42 | then: "artifacts deployed" 43 | deploy.exists() 44 | def baseName = artifactId + '-1.0' 45 | withoutModuleFile(deploy) == 46 | ["${baseName}.pom"] as Set 47 | } 48 | 49 | def "Check custom BOM artifact name"() { 50 | setup: 51 | file('src/main/java').mkdirs() 52 | build """ 53 | plugins { 54 | id 'java-platform' 55 | id 'ru.vyarus.java-lib' 56 | } 57 | 58 | javaLib.bom { 59 | artifactId = 'bom' 60 | description = 'Sample BOM' 61 | } 62 | 63 | group 'ru.vyarus' 64 | version 1.0 65 | 66 | dependencies { 67 | constraints { 68 | api 'ru.vyarus:guice-validator:2.0.0' 69 | } 70 | } 71 | """ 72 | 73 | when: "run install task" 74 | def result = run('install') 75 | 76 | 77 | String artifactId = 'bom' 78 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 79 | 80 | then: "task done" 81 | result.task(":install").outcome == TaskOutcome.SUCCESS 82 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 83 | 84 | then: "artifacts deployed" 85 | deploy.exists() 86 | def baseName = artifactId + '-1.0' 87 | withoutModuleFile(deploy) == 88 | ["${baseName}.pom"] as Set 89 | 90 | when: "get pom" 91 | def pomFile = new File(deploy, "${baseName}.pom") 92 | def pom = new XmlParser().parse(pomFile) 93 | // for debug 94 | println pomFile.getText() 95 | 96 | then: "pom is correct" 97 | pom.dependencyManagement.dependencies.'*'.find { it.artifactId.text() == 'guice-validator' } 98 | pom.name.text() == 'bom' 99 | pom.description.text() == 'Sample BOM' 100 | } 101 | 102 | def "Check avoid local bom publishing"() { 103 | setup: 104 | file('src/main/java').mkdirs() 105 | build """ 106 | plugins { 107 | id 'java-platform' 108 | id 'ru.vyarus.java-lib' 109 | } 110 | 111 | group 'ru.vyarus' 112 | version 1.0 113 | 114 | javaLib.withoutPublication() 115 | 116 | dependencies { 117 | constraints { 118 | api 'ru.vyarus:guice-validator:2.0.0' 119 | } 120 | } 121 | """ 122 | 123 | when: "run install task" 124 | def result = run('install') 125 | 126 | 127 | String artifactId = projectName() 128 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 129 | 130 | then: "task done" 131 | result.task(":install").outcome == TaskOutcome.SUCCESS 132 | !result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 133 | 134 | then: "artifacts not deployed" 135 | !deploy.exists() 136 | } 137 | 138 | def "Check avoid external repo bom publishing"() { 139 | setup: 140 | file('src/main/java').mkdirs() 141 | build """ 142 | plugins { 143 | id 'java-platform' 144 | id 'ru.vyarus.java-lib' 145 | } 146 | 147 | group 'ru.vyarus' 148 | version 1.0 149 | 150 | javaLib.withoutPublication() 151 | 152 | publishing { 153 | repositories { 154 | maven { 155 | url = layout.buildDirectory.dir('repo2') 156 | } 157 | } 158 | } 159 | 160 | dependencies { 161 | constraints { 162 | api 'ru.vyarus:guice-validator:2.0.0' 163 | } 164 | } 165 | """ 166 | 167 | when: "run install task" 168 | def result = run('publish') 169 | 170 | String artifactId = projectName() 171 | File deploy = file("build/repo2/ru/vyarus/$artifactId/1.0/") 172 | 173 | then: "task done" 174 | result.task(":publish").outcome == TaskOutcome.UP_TO_DATE 175 | !result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 176 | 177 | then: "artifacts not deployed" 178 | !deploy.exists() 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/LegacyModeKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.testkit.runner.TaskOutcome 4 | import spock.lang.IgnoreIf 5 | 6 | /** 7 | * @author Vyacheslav Rusakov 8 | * @since 11.07.2018 9 | */ 10 | @IgnoreIf({jvm.java17Compatible}) // only gradle 7.3 supports java 17 11 | class LegacyModeKitTest extends AbstractKitTest { 12 | 13 | String GRADLE_VERSION = '7.0' 14 | 15 | def "Check install task"() { 16 | setup: 17 | file('src/main/java').mkdirs() 18 | build """ 19 | plugins { 20 | id 'java' 21 | id 'ru.vyarus.java-lib' 22 | } 23 | 24 | group 'ru.vyarus' 25 | version 1.0 26 | """ 27 | 28 | when: "run pom task" 29 | def result = runVer(GRADLE_VERSION,'install') 30 | 31 | 32 | String artifactId = projectName() 33 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 34 | 35 | then: "task done" 36 | result.task(":install").outcome == TaskOutcome.SUCCESS 37 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 38 | 39 | then: "artifacts deployed" 40 | deploy.exists() 41 | def baseName = artifactId + '-1.0' 42 | withoutModuleFile(deploy) == 43 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 44 | } 45 | 46 | def "Check install task for groovy"() { 47 | setup: 48 | file('src/main/groovy').mkdirs() 49 | build """ 50 | plugins { 51 | id 'groovy' 52 | id 'ru.vyarus.java-lib' 53 | } 54 | 55 | group 'ru.vyarus' 56 | version 1.0 57 | """ 58 | 59 | when: "run pom task" 60 | def result = runVer(GRADLE_VERSION, 'install') 61 | 62 | 63 | String artifactId = projectName() 64 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 65 | 66 | then: "task done" 67 | result.task(":install").outcome == TaskOutcome.SUCCESS 68 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 69 | 70 | then: "artifacts deployed" 71 | deploy.exists() 72 | def baseName = artifactId + '-1.0' 73 | // javadoc will be produced instead of groovydoc! important for maven central 74 | withoutModuleFile(deploy) == 75 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 76 | } 77 | 78 | def "Check install for both sources"() { 79 | setup: 80 | file('src/main/java').mkdirs() 81 | file('src/main/groovy').mkdirs() 82 | build """ 83 | plugins { 84 | id 'groovy' 85 | id 'ru.vyarus.java-lib' 86 | } 87 | 88 | group 'ru.vyarus' 89 | version 1.0 90 | """ 91 | 92 | when: "run pom task" 93 | def result = runVer(GRADLE_VERSION,'install') 94 | 95 | 96 | String artifactId = projectName() 97 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 98 | 99 | then: "task done" 100 | result.task(":install").outcome == TaskOutcome.SUCCESS 101 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 102 | 103 | then: "artifacts deployed" 104 | deploy.exists() 105 | def baseName = artifactId + '-1.0' 106 | withoutModuleFile(deploy) == 107 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 108 | } 109 | 110 | def "Check install for no sources"() { 111 | setup: 112 | build """ 113 | plugins { 114 | id 'groovy' 115 | id 'ru.vyarus.java-lib' 116 | } 117 | 118 | group 'ru.vyarus' 119 | version 1.0 120 | """ 121 | 122 | when: "run pom task" 123 | def result = runVer(GRADLE_VERSION, 'install') 124 | 125 | 126 | String artifactId = projectName() 127 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 128 | 129 | then: "task done" 130 | result.task(":install").outcome == TaskOutcome.SUCCESS 131 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 132 | 133 | then: "artifacts deployed" 134 | deploy.exists() 135 | def baseName = artifactId + '-1.0' 136 | withoutModuleFile(deploy) == 137 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 138 | } 139 | 140 | def "Check behaviour on test sources"() { 141 | setup: 142 | file('src/test/java').mkdirs() 143 | file('src/test/groovy').mkdirs() 144 | build """ 145 | plugins { 146 | id 'groovy' 147 | id 'ru.vyarus.java-lib' 148 | } 149 | 150 | group 'ru.vyarus' 151 | version 1.0 152 | """ 153 | 154 | when: "run pom task" 155 | def result = runVer(GRADLE_VERSION, 'install') 156 | 157 | 158 | String artifactId = projectName() 159 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 160 | 161 | then: "task done" 162 | result.task(":install").outcome == TaskOutcome.SUCCESS 163 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 164 | 165 | then: "artifacts deployed" 166 | deploy.exists() 167 | def baseName = artifactId + '-1.0' 168 | withoutModuleFile(deploy) as Set == 169 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 170 | } 171 | 172 | def "Check publication override"() { 173 | setup: 174 | file('src/main/java').mkdirs() 175 | build """ 176 | plugins { 177 | id 'java' 178 | id 'ru.vyarus.java-lib' 179 | } 180 | 181 | group 'ru.vyarus' 182 | version 1.0 183 | 184 | javaLib { 185 | // artifacts could be changed when metadata enabled 186 | withoutGradleMetadata() 187 | } 188 | 189 | publishing.publications.maven.artifacts = [jar, javadocJar] 190 | """ 191 | 192 | when: "run pom task" 193 | def result = runVer(GRADLE_VERSION,'install') 194 | 195 | 196 | String artifactId = projectName() 197 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 198 | 199 | then: "task done" 200 | result.task(":install").outcome == TaskOutcome.SUCCESS 201 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 202 | 203 | then: "artifacts deployed, but without sources" 204 | deploy.exists() 205 | def baseName = artifactId + '-1.0' 206 | withoutModuleFile(deploy) as Set == 207 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-javadoc.jar"] as Set 208 | } 209 | 210 | def "Check reports aggregation"() { 211 | setup: 212 | build """ 213 | plugins { 214 | id 'base' 215 | id 'jacoco' 216 | id 'project-report' 217 | id 'ru.vyarus.java-lib' 218 | } 219 | 220 | javaLib { 221 | aggregateReports() 222 | } 223 | 224 | allprojects { 225 | repositories { mavenCentral() } 226 | } 227 | 228 | subprojects { 229 | apply plugin: 'groovy' 230 | apply plugin: 'jacoco' 231 | apply plugin: 'project-report' 232 | apply plugin: 'ru.vyarus.java-lib' 233 | 234 | dependencies { 235 | testImplementation 'org.spockframework:spock-core:2.3-groovy-3.0' 236 | } 237 | 238 | test { 239 | useJUnitPlatform() 240 | } 241 | } 242 | """ 243 | file('settings.gradle') << "include 'sub1', 'sub2'" 244 | 245 | fileFromClasspath('sub1/src/main/java/sample/Sample.java', '/sample/Sample.java') 246 | fileFromClasspath('sub1/src/test/groovy/sample/SampleTest.groovy', '/sample/SampleTest.groovy') 247 | 248 | fileFromClasspath('sub2/src/main/java/sample/Sample2.java', '/sample/Sample2.java') 249 | fileFromClasspath('sub2/src/test/groovy/sample/SampleTest2.groovy', '/sample/SampleTest2.groovy') 250 | 251 | when: "run test task" 252 | def result = runVer(GRADLE_VERSION, 'test') 253 | 254 | then: "task done" 255 | result.task(":test").outcome == TaskOutcome.SUCCESS 256 | 257 | then: "test report created" 258 | def test = file('build/reports/tests/test/index.html') 259 | test.exists() 260 | 261 | when: "run coverage task" 262 | result = runVer(GRADLE_VERSION, 'clean', 'jacocoTestReport') 263 | 264 | then: "task done" 265 | result.task(":jacocoTestReport").outcome == TaskOutcome.SUCCESS 266 | 267 | then: "coverage aggregated" 268 | def cov = file('build/reports/jacoco/test/jacocoTestReport.xml') 269 | cov.exists() 270 | cov.length() > 0 271 | 272 | when: "run dependencies task" 273 | result = runVer(GRADLE_VERSION, 'htmlDependencyReport') 274 | 275 | then: "task done" 276 | result.task(":htmlDependencyReport").outcome == TaskOutcome.SUCCESS 277 | 278 | then: "aggregated dependency report" 279 | file('build/reports/project/dependencies/root.sub1.html').exists() 280 | file('build/reports/project/dependencies/root.sub2.html').exists() 281 | file('build/reports/project/dependencies/root.html').exists() 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/OpenDepsReportTasksTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.api.Project 4 | 5 | /** 6 | * @author Vyacheslav Rusakov 7 | * @since 10.06.2021 8 | */ 9 | class OpenDepsReportTasksTest extends AbstractTest { 10 | 11 | def "Check show dependencies task appear"() { 12 | 13 | when: "activating plugin" 14 | file('src/main/java').mkdirs() 15 | Project project = project { 16 | apply plugin: 'project-report' 17 | apply plugin: "ru.vyarus.java-lib" 18 | } 19 | 20 | then: "task applied" 21 | project.tasks.findByName('openDependencyReport') 22 | } 23 | 24 | def "Check show dependencies task appear in multi-module configuration"() { 25 | 26 | when: "activating plugin" 27 | file('src/main/java').mkdirs() 28 | Project project = project { 29 | apply plugin: "ru.vyarus.java-lib" 30 | 31 | allprojects { 32 | apply plugin: 'project-report' 33 | } 34 | } 35 | 36 | then: "task applied" 37 | project.tasks.findByName('openDependencyReport') 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/PomConfigurationTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import groovy.xml.XmlParser 4 | import org.gradle.testkit.runner.TaskOutcome 5 | 6 | /** 7 | * @author Vyacheslav Rusakov 8 | * @since 09.06.2021 9 | */ 10 | class PomConfigurationTest extends AbstractKitTest { 11 | 12 | def "Check install task"() { 13 | setup: 14 | file('src/main/java').mkdirs() 15 | build """ 16 | plugins { 17 | id 'java' 18 | id 'ru.vyarus.java-lib' 19 | } 20 | 21 | repositories {mavenCentral()} 22 | dependencies { 23 | implementation platform('com.google.inject:guice-bom:4.0') 24 | implementation 'com.google.inject:guice' 25 | } 26 | 27 | maven { 28 | removeDependencyManagement() 29 | } 30 | 31 | group 'ru.vyarus' 32 | version 1.0 33 | """ 34 | 35 | when: "run pom task" 36 | def result = run('install') 37 | 38 | 39 | String artifactId = projectName() 40 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 41 | 42 | then: "task done" 43 | result.task(":install").outcome == TaskOutcome.SUCCESS 44 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 45 | 46 | when: "find pom" 47 | def pomFile = new File(deploy, "$artifactId-1.0.pom") 48 | // for debug 49 | println pomFile.getText() 50 | def pom = new XmlParser().parse(pomFile) 51 | 52 | then: "no dependency management section" 53 | !pom.dependencyManagement 54 | pom.dependencies.'*'.find { it.artifactId.text() == 'guice' }.version.text() == '4.0' 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/PomCorrectnessKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import groovy.xml.XmlParser 4 | import org.gradle.testkit.runner.TaskOutcome 5 | 6 | /** 7 | * @author Vyacheslav Rusakov 8 | * @since 17.07.2018 9 | */ 10 | class PomCorrectnessKitTest extends AbstractKitTest { 11 | 12 | def "Check install task"() { 13 | setup: 14 | file('src/main/java').mkdirs() 15 | build """ 16 | plugins { 17 | id 'java' 18 | id 'ru.vyarus.java-lib' 19 | } 20 | 21 | dependencies { 22 | provided 'com.google.code.findbugs:annotations:3.0.0' 23 | implementation 'org.javassist:javassist:3.16.1-GA' 24 | } 25 | 26 | maven.pom { 27 | name = 'sample' 28 | } 29 | 30 | group 'ru.vyarus' 31 | version 1.0 32 | """ 33 | 34 | when: "run pom task" 35 | def result = run('install') 36 | 37 | 38 | String artifactId = projectName() 39 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 40 | 41 | then: "task done" 42 | result.task(":install").outcome == TaskOutcome.SUCCESS 43 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 44 | 45 | then: "artifacts deployed" 46 | deploy.exists() 47 | def baseName = artifactId + '-1.0' 48 | withoutModuleFile(deploy) == 49 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 50 | 51 | when: "get pom" 52 | def pomFile = new File(deploy, "${baseName}.pom") 53 | def pom = new XmlParser().parse(pomFile) 54 | // for debug 55 | println pomFile.getText() 56 | 57 | then: "pom is correct" 58 | pom.dependencies.'*'.find { it.artifactId.text() == 'javassist' }.scope.text() == 'compile' 59 | pom.dependencies.'*'.find { it.artifactId.text() == 'annotations' }.scope.text() == 'provided' 60 | pom.name.text() == 'sample' 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/PublicationOverrideKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.testkit.runner.TaskOutcome 4 | 5 | /** 6 | * @author Vyacheslav Rusakov 7 | * @since 05.12.2015 8 | */ 9 | class PublicationOverrideKitTest extends AbstractKitTest { 10 | 11 | def "Check publication override"() { 12 | setup: 13 | file('src/main/java').mkdirs() 14 | build """ 15 | plugins { 16 | id 'java' 17 | id 'ru.vyarus.java-lib' 18 | } 19 | 20 | group 'ru.vyarus' 21 | version 1.0 22 | 23 | javaLib { 24 | // metadata publishing would fail build with modified artifacts 25 | withoutGradleMetadata() 26 | } 27 | 28 | publishing.publications.maven.artifacts = [jar, javadocJar] 29 | """ 30 | file('settings.gradle') << """ 31 | rootProject.name = "test" 32 | """ 33 | 34 | when: "run pom task" 35 | def result = run('install') 36 | 37 | 38 | String artifactId = 'test' 39 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 40 | 41 | then: "task done" 42 | result.task(":install").outcome == TaskOutcome.SUCCESS 43 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 44 | 45 | then: "artifacts deployed, but without sources" 46 | deploy.exists() 47 | def baseName = artifactId + '-1.0' 48 | withoutModuleFile(deploy) == 49 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-javadoc.jar"] as Set 50 | } 51 | } -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/ReportsAggregationKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.testkit.runner.TaskOutcome 4 | 5 | /** 6 | * @author Vyacheslav Rusakov 7 | * @since 12.06.2021 8 | */ 9 | class ReportsAggregationKitTest extends AbstractKitTest { 10 | 11 | def "Check reports aggregation"() { 12 | setup: 13 | build """ 14 | plugins { 15 | id 'base' 16 | id 'jacoco' 17 | id 'project-report' 18 | id 'ru.vyarus.java-lib' 19 | } 20 | 21 | javaLib { 22 | aggregateReports() 23 | } 24 | 25 | allprojects { 26 | repositories { mavenCentral() } 27 | } 28 | 29 | subprojects { 30 | apply plugin: 'groovy' 31 | apply plugin: 'jacoco' 32 | apply plugin: 'project-report' 33 | apply plugin: 'ru.vyarus.java-lib' 34 | 35 | dependencies { 36 | testImplementation 'org.spockframework:spock-core:2.3-groovy-3.0' 37 | } 38 | 39 | test { 40 | useJUnitPlatform() 41 | } 42 | } 43 | """ 44 | file('settings.gradle') << "include 'sub1', 'sub2'" 45 | 46 | fileFromClasspath('sub1/src/main/java/sample/Sample.java', '/sample/Sample.java') 47 | fileFromClasspath('sub1/src/test/groovy/sample/SampleTest.groovy', '/sample/SampleTest.groovy') 48 | 49 | fileFromClasspath('sub2/src/main/java/sample/Sample2.java', '/sample/Sample2.java') 50 | fileFromClasspath('sub2/src/test/groovy/sample/SampleTest2.groovy', '/sample/SampleTest2.groovy') 51 | 52 | when: "run test task" 53 | def result = run('test') 54 | 55 | then: "task done" 56 | result.task(":test").outcome == TaskOutcome.SUCCESS 57 | 58 | then: "test report created" 59 | def test = file('build/reports/tests/test/index.html') 60 | test.exists() 61 | 62 | when: "run coverage task" 63 | result = run('clean', 'jacocoTestReport') 64 | 65 | then: "task done" 66 | result.task(":jacocoTestReport").outcome == TaskOutcome.SUCCESS 67 | 68 | then: "coverage aggregated" 69 | def cov = file('build/reports/jacoco/test/jacocoTestReport.xml') 70 | cov.exists() 71 | cov.length() > 0 72 | 73 | when: "run dependencies task" 74 | result = run('htmlDependencyReport') 75 | 76 | then: "task done" 77 | result.task(":htmlDependencyReport").outcome == TaskOutcome.SUCCESS 78 | 79 | then: "aggregated dependency report" 80 | file('build/reports/project/dependencies/root.sub1.html').exists() 81 | file('build/reports/project/dependencies/root.sub2.html').exists() 82 | file('build/reports/project/dependencies/root.html').exists() 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/ReportsAggregationTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.api.GradleException 4 | import org.gradle.api.Project 5 | import org.gradle.api.tasks.testing.TestReport 6 | import org.gradle.testing.jacoco.tasks.JacocoReport 7 | 8 | /** 9 | * @author Vyacheslav Rusakov 10 | * @since 12.06.2021 11 | */ 12 | class ReportsAggregationTest extends AbstractTest { 13 | 14 | def "Check aggregated reports"() { 15 | 16 | when: "apply plugin" 17 | file('sub1/src/main/java').mkdirs() 18 | file('sub1/src/test/java').mkdirs() 19 | file('sub2/src/main/java').mkdirs() 20 | file('sub2/src/test/java').mkdirs() 21 | 22 | file('sub1/src/main/java/Sample.java').createNewFile() 23 | file('sub1/src/test/java/SampleTest.java').createNewFile() 24 | file('sub2/src/main/java/Sample.java').createNewFile() 25 | file('sub2/src/test/java/SampleTest.java').createNewFile() 26 | 27 | Project project = projectBuilder { 28 | apply plugin: 'base' 29 | apply plugin: 'jacoco' 30 | apply plugin: 'project-report' 31 | apply plugin: 'ru.vyarus.java-lib' 32 | 33 | javaLib { 34 | aggregateReports() 35 | } 36 | } 37 | .child('sub1') { 38 | apply plugin: 'java' 39 | apply plugin: 'jacoco' 40 | apply plugin: 'project-report' 41 | apply plugin: 'ru.vyarus.java-lib' 42 | } 43 | .child('sub2') { 44 | apply plugin: 'java' 45 | apply plugin: 'jacoco' 46 | apply plugin: 'project-report' 47 | apply plugin: 'ru.vyarus.java-lib' 48 | } 49 | .build() 50 | 51 | then: "aggregation tasks created" 52 | JacocoReport cov = project.tasks.jacocoTestReport 53 | // execution data counts only existing files 54 | cov.executionData.size() == 0 55 | 56 | then: "tests aggregation task" 57 | TestReport test = project.tasks.test 58 | test 59 | // testResults contains not only test reports but also coverage 60 | test.testResults.files.findAll {it.name == 'binary'}.size() == 2 61 | 62 | then: "dependencies reports aggregated" 63 | project.htmlDependencyReport.projects.size() == 3 64 | } 65 | 66 | def "Check not same submodules case"() { 67 | 68 | when: "apply plugin" 69 | file('sub2/src/main/java').mkdirs() 70 | file('sub2/src/test/java').mkdirs() 71 | 72 | file('sub2/src/main/java/Sample.java').createNewFile() 73 | file('sub2/src/test/java/SampleTest.java').createNewFile() 74 | 75 | Project project = projectBuilder { 76 | apply plugin: 'base' 77 | apply plugin: 'jacoco' 78 | apply plugin: 'project-report' 79 | apply plugin: 'ru.vyarus.java-lib' 80 | 81 | javaLib { 82 | aggregateReports() 83 | } 84 | } 85 | .child('sub1') 86 | .child('sub2') { 87 | apply plugin: 'java' 88 | apply plugin: 'jacoco' 89 | apply plugin: 'project-report' 90 | apply plugin: 'ru.vyarus.java-lib' 91 | } 92 | .build() 93 | 94 | then: "aggregation tasks created" 95 | JacocoReport cov = project.tasks.jacocoTestReport 96 | // execution data counts only existing files 97 | cov.executionData.size() == 0 98 | 99 | then: "tests aggregation task" 100 | TestReport test = project.tasks.test 101 | test 102 | test.testResults.files.findAll {it.name == 'binary'}.size() == 1 103 | 104 | then: "dependencies reports aggregated" 105 | project.htmlDependencyReport.projects.size() == 3 106 | } 107 | 108 | def "Check aggregation on simple module"() { 109 | 110 | when: "activating plugin" 111 | file('src/main/java').mkdirs() 112 | project { 113 | apply plugin: 'base' 114 | apply plugin: 'jacoco' 115 | apply plugin: "ru.vyarus.java-lib" 116 | 117 | javaLib { 118 | aggregateReports() 119 | } 120 | } 121 | 122 | then: "xml report active" 123 | def ex = thrown(GradleException) 124 | ex.cause.message == 'javaLib.aggregateReports() could not be used on project \'test\' because does not contain subprojects' 125 | } 126 | 127 | def "Check aggregation on java module"() { 128 | 129 | when: "activating plugin" 130 | file('src/main/java').mkdirs() 131 | projectBuilder { 132 | apply plugin: 'java' 133 | apply plugin: 'jacoco' 134 | apply plugin: "ru.vyarus.java-lib" 135 | 136 | javaLib { 137 | aggregateReports() 138 | } 139 | }.child('sub') { 140 | apply plugin: 'java' 141 | } 142 | .build() 143 | 144 | then: "xml report active" 145 | def ex = thrown(GradleException) 146 | ex.cause.message == 'javaLib.aggregateReports() could not be used on project \'test\' because it contains java sources. If this is a root project use \'base\' plugin instead.' 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/SigningKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.testkit.runner.TaskOutcome 4 | 5 | /** 6 | * @author Vyacheslav Rusakov 7 | * @since 07.06.2021 8 | */ 9 | class SigningKitTest extends AbstractKitTest { 10 | 11 | def "Check automatic signing"() { 12 | setup: 13 | file('src/main/java').mkdirs() 14 | build """ 15 | plugins { 16 | id 'java' 17 | id 'signing' 18 | id 'ru.vyarus.java-lib' 19 | } 20 | 21 | javaLib { 22 | withoutGradleMetadata() 23 | withoutJavadoc() 24 | withoutSources() 25 | } 26 | 27 | group 'ru.vyarus' 28 | version 1.0 29 | 30 | ext['signing.keyId']='78065050' 31 | ext['signing.password']= 32 | ext['signing.secretKeyRingFile']='test.gpg' 33 | """ 34 | fileFromClasspath('test.gpg', '/cert/test.gpg') 35 | file('settings.gradle') << """ 36 | rootProject.name = "test" 37 | """ 38 | 39 | when: "run pom task" 40 | def result = run('install') 41 | 42 | 43 | String artifactId = 'test' 44 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 45 | 46 | then: "task done" 47 | result.task(":install").outcome == TaskOutcome.SUCCESS 48 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 49 | 50 | then: "artifacts deployed" 51 | deploy.exists() 52 | def baseName = artifactId + '-1.0' 53 | withoutModuleFile(deploy) == 54 | ["${baseName}.jar", "${baseName}.pom", "${baseName}.jar.asc", "${baseName}.pom.asc"] as Set 55 | } 56 | 57 | def "Check automatic BOM signing"() { 58 | setup: 59 | file('src/main/java').mkdirs() 60 | build """ 61 | plugins { 62 | id 'java-platform' 63 | id 'signing' 64 | id 'ru.vyarus.java-lib' 65 | } 66 | 67 | javaLib { 68 | withoutGradleMetadata() 69 | } 70 | 71 | group 'ru.vyarus' 72 | version 1.0 73 | 74 | ext['signing.keyId']='78065050' 75 | ext['signing.password']= 76 | ext['signing.secretKeyRingFile']='test.gpg' 77 | """ 78 | fileFromClasspath('test.gpg', '/cert/test.gpg') 79 | file('settings.gradle') << """ 80 | rootProject.name = "test" 81 | """ 82 | 83 | when: "run pom task" 84 | def result = run('install') 85 | 86 | 87 | String artifactId = 'test' 88 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 89 | 90 | then: "task done" 91 | result.task(":install").outcome == TaskOutcome.SUCCESS 92 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 93 | 94 | then: "artifacts deployed" 95 | deploy.exists() 96 | def baseName = artifactId + '-1.0' 97 | withoutModuleFile(deploy) == 98 | ["${baseName}.pom", "${baseName}.pom.asc"] as Set 99 | } 100 | 101 | def "Check all artifacts signing"() { 102 | setup: 103 | file('src/main/java').mkdirs() 104 | build """ 105 | plugins { 106 | id 'java' 107 | id 'signing' 108 | id 'ru.vyarus.java-lib' 109 | } 110 | 111 | group 'ru.vyarus' 112 | version 1.0 113 | 114 | ext['signing.keyId']='78065050' 115 | ext['signing.password']= 116 | ext['signing.secretKeyRingFile']='test.gpg' 117 | """ 118 | fileFromClasspath('test.gpg', '/cert/test.gpg') 119 | file('settings.gradle') << """ 120 | rootProject.name = "test" 121 | """ 122 | 123 | when: "run pom task" 124 | def result = run('install') 125 | 126 | 127 | String artifactId = 'test' 128 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 129 | 130 | then: "task done" 131 | result.task(":install").outcome == TaskOutcome.SUCCESS 132 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 133 | 134 | then: "artifacts deployed" 135 | deploy.exists() 136 | def baseName = artifactId + '-1.0' 137 | withoutModuleFile(deploy) == 138 | ["${baseName}.jar", "${baseName}.jar.asc", 139 | "${baseName}.pom", "${baseName}.pom.asc", 140 | "${baseName}-sources.jar", "${baseName}-sources.jar.asc", 141 | "${baseName}-javadoc.jar", "${baseName}-javadoc.jar.asc", 142 | "${baseName}.module.asc"] as Set 143 | } 144 | 145 | def "Check snapshots not signed"() { 146 | setup: 147 | file('src/main/java').mkdirs() 148 | build """ 149 | plugins { 150 | id 'java' 151 | id 'signing' 152 | id 'ru.vyarus.java-lib' 153 | } 154 | 155 | javaLib { 156 | withoutGradleMetadata() 157 | withoutJavadoc() 158 | withoutSources() 159 | } 160 | 161 | group 'ru.vyarus' 162 | version '1.0-SNAPSHOT' 163 | """ 164 | file('settings.gradle') << """ 165 | rootProject.name = "test" 166 | """ 167 | 168 | when: "run pom task" 169 | def result = run('install') 170 | 171 | 172 | String artifactId = 'test' 173 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0-SNAPSHOT/") 174 | 175 | then: "task done" 176 | result.task(":install").outcome == TaskOutcome.SUCCESS 177 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0-SNAPSHOT") 178 | 179 | then: "artifacts deployed" 180 | deploy.exists() 181 | def baseName = artifactId + '-1.0-SNAPSHOT' 182 | withoutModuleFile(deploy) == 183 | ["${baseName}.jar", "${baseName}.pom", 'maven-metadata-local.xml'] as Set 184 | } 185 | 186 | def "Check snapshots signed if cert configured"() { 187 | setup: 188 | file('src/main/java').mkdirs() 189 | build """ 190 | plugins { 191 | id 'java' 192 | id 'signing' 193 | id 'ru.vyarus.java-lib' 194 | } 195 | 196 | javaLib { 197 | withoutGradleMetadata() 198 | withoutJavadoc() 199 | withoutSources() 200 | } 201 | 202 | group 'ru.vyarus' 203 | version '1.0-SNAPSHOT' 204 | 205 | ext['signing.keyId']='78065050' 206 | ext['signing.password']= 207 | ext['signing.secretKeyRingFile']='test.gpg' 208 | """ 209 | fileFromClasspath('test.gpg', '/cert/test.gpg') 210 | file('settings.gradle') << """ 211 | rootProject.name = "test" 212 | """ 213 | 214 | when: "run pom task" 215 | def result = run('install') 216 | 217 | 218 | String artifactId = 'test' 219 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0-SNAPSHOT/") 220 | 221 | then: "task done" 222 | result.task(":install").outcome == TaskOutcome.SUCCESS 223 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0-SNAPSHOT") 224 | 225 | then: "artifacts deployed" 226 | deploy.exists() 227 | def baseName = artifactId + '-1.0-SNAPSHOT' 228 | withoutModuleFile(deploy) == 229 | ["${baseName}.jar", "${baseName}.jar.asc", "${baseName}.pom", "${baseName}.pom.asc", 'maven-metadata-local.xml'] as Set 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /src/test/groovy/ru/vyarus/gradle/plugin/lib/UpstreamKitTest.groovy: -------------------------------------------------------------------------------- 1 | package ru.vyarus.gradle.plugin.lib 2 | 3 | import org.gradle.testkit.runner.TaskOutcome 4 | 5 | import java.util.zip.ZipFile 6 | 7 | /** 8 | * @author Vyacheslav Rusakov 9 | * @since 13.11.2019 10 | */ 11 | class UpstreamKitTest extends AbstractKitTest { 12 | 13 | String GRADLE_VERSION = '8.6' 14 | 15 | def "Check install task"() { 16 | setup: 17 | file('src/main/java').mkdirs() 18 | build """ 19 | plugins { 20 | id 'java' 21 | id 'ru.vyarus.java-lib' 22 | } 23 | 24 | group 'ru.vyarus' 25 | version 1.0 26 | """ 27 | 28 | when: "run pom task" 29 | def result = runVer(GRADLE_VERSION, 'install', '--warning-mode', 'all') 30 | 31 | 32 | String artifactId = projectName() 33 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 34 | 35 | then: "task done" 36 | result.task(":install").outcome == TaskOutcome.SUCCESS 37 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 38 | 39 | then: "artifacts deployed" 40 | deploy.exists() 41 | def baseName = artifactId + '-1.0' 42 | withoutModuleFile(deploy) == 43 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 44 | } 45 | 46 | def "Check install task for groovy"() { 47 | setup: 48 | file('src/main/groovy').mkdirs() 49 | build """ 50 | plugins { 51 | id 'groovy' 52 | id 'ru.vyarus.java-lib' 53 | } 54 | 55 | group 'ru.vyarus' 56 | version 1.0 57 | """ 58 | 59 | when: "run pom task" 60 | def result = runVer(GRADLE_VERSION, 'install') 61 | 62 | 63 | String artifactId = projectName() 64 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 65 | 66 | then: "task done" 67 | result.task(":install").outcome == TaskOutcome.SUCCESS 68 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 69 | 70 | then: "artifacts deployed" 71 | deploy.exists() 72 | def baseName = artifactId + '-1.0' 73 | // javadoc will be produced instead of groovydoc! important for maven central 74 | withoutModuleFile(deploy) == 75 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 76 | } 77 | 78 | def "Check install for both sources"() { 79 | setup: 80 | file('src/main/java').mkdirs() 81 | file('src/main/groovy').mkdirs() 82 | build """ 83 | plugins { 84 | id 'groovy' 85 | id 'ru.vyarus.java-lib' 86 | } 87 | 88 | group 'ru.vyarus' 89 | version 1.0 90 | """ 91 | 92 | when: "run pom task" 93 | def result = runVer(GRADLE_VERSION, 'install') 94 | 95 | 96 | String artifactId = projectName() 97 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 98 | 99 | then: "task done" 100 | result.task(":install").outcome == TaskOutcome.SUCCESS 101 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 102 | 103 | then: "artifacts deployed" 104 | deploy.exists() 105 | def baseName = artifactId + '-1.0' 106 | withoutModuleFile(deploy) == 107 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 108 | } 109 | 110 | def "Check install for no sources"() { 111 | setup: 112 | build """ 113 | plugins { 114 | id 'groovy' 115 | id 'ru.vyarus.java-lib' 116 | } 117 | 118 | group 'ru.vyarus' 119 | version 1.0 120 | """ 121 | 122 | when: "run pom task" 123 | def result = runVer(GRADLE_VERSION, 'install') 124 | 125 | 126 | String artifactId = projectName() 127 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 128 | 129 | then: "task done" 130 | result.task(":install").outcome == TaskOutcome.SUCCESS 131 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 132 | 133 | then: "artifacts deployed" 134 | deploy.exists() 135 | def baseName = artifactId + '-1.0' 136 | withoutModuleFile(deploy) == 137 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 138 | } 139 | 140 | def "Check behaviour on test sources"() { 141 | setup: 142 | file('src/test/java').mkdirs() 143 | file('src/test/groovy').mkdirs() 144 | build """ 145 | plugins { 146 | id 'groovy' 147 | id 'ru.vyarus.java-lib' 148 | } 149 | 150 | group 'ru.vyarus' 151 | version 1.0 152 | """ 153 | 154 | when: "run pom task" 155 | def result = runVer(GRADLE_VERSION, 'install') 156 | 157 | 158 | String artifactId = projectName() 159 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 160 | 161 | then: "task done" 162 | result.task(":install").outcome == TaskOutcome.SUCCESS 163 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 164 | 165 | then: "artifacts deployed" 166 | deploy.exists() 167 | def baseName = artifactId + '-1.0' 168 | withoutModuleFile(deploy) == 169 | ["${baseName}.jar", "${baseName}.pom", "${baseName}-sources.jar", "${baseName}-javadoc.jar"] as Set 170 | } 171 | 172 | def "Check jar modification"() { 173 | 174 | setup: 175 | file('src/main/java').mkdirs() 176 | build """ 177 | plugins { 178 | id 'java' 179 | id 'ru.vyarus.java-lib' 180 | } 181 | 182 | group 'ru.vyarus' 183 | version 1.0 184 | """ 185 | file('settings.gradle') << """ 186 | rootProject.name = "test" 187 | """ 188 | 189 | when: "run pom task" 190 | def result = runVer(GRADLE_VERSION, 'install') 191 | 192 | 193 | String artifactId = 'test' 194 | String baseName = artifactId + '-1.0' 195 | ZipFile jar = new ZipFile(file("build/repo/ru/vyarus/$artifactId/1.0/${baseName}.jar")) 196 | 197 | then: "jar manifest correct" 198 | String manifest = jar.getInputStream(jar.getEntry('META-INF/MANIFEST.MF')).text 199 | println manifest 200 | manifest.contains("Implementation-Title: $artifactId") 201 | manifest.contains("Implementation-Version: 1.0") 202 | manifest.contains("Built-By: ${System.getProperty('user.name')}") 203 | manifest.contains("Built-Date:") 204 | manifest.contains("Built-JDK:") 205 | manifest.contains("Built-Gradle:") 206 | manifest.contains("Target-JDK:") 207 | 208 | then: "jar contains pom" 209 | String jarPom = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.xml")).text 210 | jarPom != null 211 | println jarPom 212 | 213 | then: "jar contains pom.properties" 214 | String props = jar.getInputStream(jar.getEntry("META-INF/maven/ru.vyarus/$artifactId/pom.properties")).text 215 | props != null 216 | println props 217 | props.contains('groupId: ru.vyarus') 218 | props.contains("artifactId: $artifactId") 219 | props.contains('version: 1.0') 220 | 221 | cleanup: 222 | jar?.close() 223 | } 224 | 225 | def "Check jar only publish"() { 226 | setup: 227 | file('src/main/java').mkdirs() 228 | build """ 229 | plugins { 230 | id 'java' 231 | id 'ru.vyarus.java-lib' 232 | } 233 | 234 | javaLib { 235 | withoutJavadoc() 236 | withoutSources() 237 | } 238 | 239 | group 'ru.vyarus' 240 | version 1.0 241 | """ 242 | 243 | when: "run pom task" 244 | def result = runVer(GRADLE_VERSION, 'install') 245 | 246 | 247 | String artifactId = projectName() 248 | File deploy = file("build/repo/ru/vyarus/$artifactId/1.0/") 249 | 250 | then: "task done" 251 | result.task(":install").outcome == TaskOutcome.SUCCESS 252 | result.output.contains("INSTALLED ru.vyarus:$artifactId:1.0") 253 | 254 | then: "artifacts deployed" 255 | deploy.exists() 256 | def baseName = artifactId + '-1.0' 257 | withoutModuleFile(deploy) == 258 | ["${baseName}.jar", "${baseName}.pom"] as Set 259 | } 260 | 261 | def "Check reports aggregation"() { 262 | setup: 263 | build """ 264 | plugins { 265 | id 'base' 266 | id 'jacoco' 267 | id 'project-report' 268 | id 'ru.vyarus.java-lib' 269 | } 270 | 271 | javaLib { 272 | aggregateReports() 273 | } 274 | 275 | allprojects { 276 | repositories { mavenCentral() } 277 | } 278 | 279 | subprojects { 280 | apply plugin: 'groovy' 281 | apply plugin: 'jacoco' 282 | apply plugin: 'project-report' 283 | apply plugin: 'ru.vyarus.java-lib' 284 | 285 | dependencies { 286 | testImplementation 'org.spockframework:spock-core:2.3-groovy-3.0' 287 | } 288 | 289 | test { 290 | useJUnitPlatform() 291 | } 292 | } 293 | """ 294 | file('settings.gradle') << "include 'sub1', 'sub2'" 295 | 296 | fileFromClasspath('sub1/src/main/java/sample/Sample.java', '/sample/Sample.java') 297 | fileFromClasspath('sub1/src/test/groovy/sample/SampleTest.groovy', '/sample/SampleTest.groovy') 298 | 299 | fileFromClasspath('sub2/src/main/java/sample/Sample2.java', '/sample/Sample2.java') 300 | fileFromClasspath('sub2/src/test/groovy/sample/SampleTest2.groovy', '/sample/SampleTest2.groovy') 301 | 302 | when: "run test task" 303 | def result = runVer(GRADLE_VERSION, 'test', '--warning-mode', 'all') 304 | 305 | then: "task done" 306 | result.task(":test").outcome == TaskOutcome.SUCCESS 307 | 308 | then: "test report created" 309 | def test = file('build/reports/tests/test/index.html') 310 | test.exists() 311 | 312 | when: "run coverage task" 313 | result = runVer(GRADLE_VERSION, 'clean', 'jacocoTestReport', '--warning-mode', 'all') 314 | 315 | then: "task done" 316 | result.task(":jacocoTestReport").outcome == TaskOutcome.SUCCESS 317 | 318 | then: "coverage aggregated" 319 | def cov = file('build/reports/jacoco/test/jacocoTestReport.xml') 320 | cov.exists() 321 | cov.length() > 0 322 | 323 | when: "run dependencies task" 324 | result = runVer(GRADLE_VERSION, 'htmlDependencyReport', '--warning-mode', 'all') 325 | 326 | then: "task done" 327 | result.task(":htmlDependencyReport").outcome == TaskOutcome.SUCCESS 328 | 329 | then: "aggregated dependency report" 330 | file('build/reports/project/dependencies/root.sub1.html').exists() 331 | file('build/reports/project/dependencies/root.sub2.html').exists() 332 | file('build/reports/project/dependencies/root.html').exists() 333 | } 334 | } 335 | -------------------------------------------------------------------------------- /src/test/resources/cert/test.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xvik/gradle-java-lib-plugin/59ad479c9e74ae110d3686d401511b8b45781835/src/test/resources/cert/test.gpg -------------------------------------------------------------------------------- /src/test/resources/sample/Sample.java: -------------------------------------------------------------------------------- 1 | package sample; 2 | 3 | public class Sample { 4 | 5 | public String foo() { 6 | return "test"; 7 | } 8 | } -------------------------------------------------------------------------------- /src/test/resources/sample/Sample2.java: -------------------------------------------------------------------------------- 1 | package sample; 2 | 3 | public class Sample2 { 4 | 5 | public String foo() { 6 | return "test"; 7 | } 8 | } -------------------------------------------------------------------------------- /src/test/resources/sample/SampleTest.groovy: -------------------------------------------------------------------------------- 1 | package sample 2 | 3 | import spock.lang.Specification 4 | 5 | class SampleTest extends Specification{ 6 | 7 | def "Check sample"() { 8 | 9 | expect: 10 | new Sample().foo() == 'test' 11 | } 12 | } -------------------------------------------------------------------------------- /src/test/resources/sample/SampleTest2.groovy: -------------------------------------------------------------------------------- 1 | package sample 2 | 3 | import spock.lang.Specification 4 | 5 | class SampleTest2 extends Specification{ 6 | 7 | def "Check sample"() { 8 | 9 | expect: 10 | new Sample2().foo() == 'test' 11 | } 12 | } -------------------------------------------------------------------------------- /src/test/resources/sample/TestPlugin.java: -------------------------------------------------------------------------------- 1 | package ru.vyarus; 2 | 3 | import org.gradle.api.Plugin; 4 | import org.gradle.api.Project; 5 | 6 | public class TestPlugin implements Plugin { 7 | 8 | @Override 9 | public void apply(Project target) { 10 | 11 | } 12 | } --------------------------------------------------------------------------------