diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 42e9b45..d40cfaf 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,6 +10,9 @@ on: jobs: release: name: Release + permissions: + contents: write + packages: write runs-on: ubuntu-latest steps: - name: Checkout @@ -46,5 +49,5 @@ jobs: - name: Release env: - GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: npm exec semantic-release diff --git a/.releaserc b/.releaserc index 5c5b86a..a91a300 100644 --- a/.releaserc +++ b/.releaserc @@ -25,7 +25,8 @@ "CHANGELOG.md", "gradle.properties", "patches.json" - ] + ], + "message": "chore: Release v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" } ], [ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..e22dc8f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,57 @@ +# [1.0.0-dev.8](https://github.com/ReVanced/revanced-patches-gradle-plugin/compare/v1.0.0-dev.7...v1.0.0-dev.8) (2025-03-22) + + +### Bug Fixes + +* Configure patches project on extensions projects absence ([#5](https://github.com/ReVanced/revanced-patches-gradle-plugin/issues/5)) ([2aa7f6f](https://github.com/ReVanced/revanced-patches-gradle-plugin/commit/2aa7f6f9f1e94e05fa28501878e8dd067361404e)) + +# [1.0.0-dev.7](https://github.com/ReVanced/revanced-patches-gradle-plugin/compare/v1.0.0-dev.6...v1.0.0-dev.7) (2024-11-26) + + +### Features + +* Add ability to globally configure extension projects ([9f18768](https://github.com/ReVanced/revanced-patches-gradle-plugin/commit/9f18768042d7b85fa3bb93246571bdff8a5f9615)) +* Allow creating extensions in packages ([c0ef614](https://github.com/ReVanced/revanced-patches-gradle-plugin/commit/c0ef614cb33400087f677ead2b257fcf177d9672)) +* Bump source and target compatibility to Java 17 ([0f42166](https://github.com/ReVanced/revanced-patches-gradle-plugin/commit/0f421669b31d9d669690825a8fdb37c23ad4f802)) + + +### Performance Improvements + +* Use task to build required DEX only instead of entire APK ([16ee9e0](https://github.com/ReVanced/revanced-patches-gradle-plugin/commit/16ee9e03d46ef465681a3e530a925eb19bfb5604)) + +# [1.0.0-dev.6](https://github.com/ReVanced/revanced-patches-gradle-plugin/compare/v1.0.0-dev.5...v1.0.0-dev.6) (2024-10-01) + +# [1.0.0-dev.5](https://github.com/ReVanced/revanced-patches-gradle-plugin/compare/v1.0.0-dev.4...v1.0.0-dev.5) (2024-09-08) + + +### Bug Fixes + +* Create a dummy publishing repository to fix publications & signing ([397b7b3](https://github.com/ReVanced/revanced-patches-gradle-plugin/commit/397b7b3393fc06f0002536486096fff100abe7ad)) + +# [1.0.0-dev.4](https://github.com/ReVanced/revanced-patches-gradle-plugin/compare/v1.0.0-dev.3...v1.0.0-dev.4) (2024-08-08) + + +### Bug Fixes + +* Create working directory before trying to use it ([715fb96](https://github.com/ReVanced/revanced-patches-gradle-plugin/commit/715fb96382037fd66351e5735e39a3dd512b1346)) + +# [1.0.0-dev.3](https://github.com/ReVanced/revanced-patches-gradle-plugin/compare/v1.0.0-dev.2...v1.0.0-dev.3) (2024-08-08) + + +### Bug Fixes + +* Build DEX from patches file by using internal APIs instead of CLIs ([2597efe](https://github.com/ReVanced/revanced-patches-gradle-plugin/commit/2597efe474f24c93b68e0683bc0e9622e48623d1)) + +# [1.0.0-dev.2](https://github.com/ReVanced/revanced-patches-gradle-plugin/compare/v1.0.0-dev.1...v1.0.0-dev.2) (2024-08-06) + + +### Bug Fixes + +* Do not raise an exception when environment variables are not set for repository credentials ([ea6bfe0](https://github.com/ReVanced/revanced-patches-gradle-plugin/commit/ea6bfe0c86b7b1c114bfa520753e6b53c501b0b7)) + +# 1.0.0-dev.1 (2024-07-22) + + +### Features + +* Initialize project ([705b448](https://github.com/ReVanced/revanced-patches-gradle-plugin/commit/705b4483dbd33352e79cff289786ef26cad977cf)) diff --git a/README.md b/README.md index 0a7dbbf..92fe2dd 100644 --- a/README.md +++ b/README.md @@ -71,12 +71,12 @@ ReVanced Patches Gradle plugin configures a project to develop ReVanced Patches. For that, the plugin provides: -- The [settings plugin](plugin/src/main/kotlin/app/revanced/patches/gradle/SettingsPlugin.kt): -Applied to the `settings.gradle.kts` file, configures the project repositories and subprojects -- The [patches plugin](plugin/src/main/kotlin/app/revanced/patches/gradle/PatchesPlugin.kt): -Applied to the patches subproject by the settings plugin -- The [extension plugin](plugin/src/main/kotlin/app/revanced/patches/gradle/ExtensionPlugin.kt): -Applied to extension subprojects by the settings plugin +- The [settings plugin](src/main/kotlin/app/revanced/patches/gradle/SettingsPlugin.kt): + Applied to the `settings.gradle.kts` file, configures the project repositories and subprojects +- The [patches plugin](src/main/kotlin/app/revanced/patches/gradle/PatchesPlugin.kt): + Applied to the patches subproject by the settings plugin +- The [extension plugin](src/main/kotlin/app/revanced/patches/gradle/ExtensionPlugin.kt): + Applied to extension subprojects by the settings plugin > [!CAUTION] > This plugin is not stable yet and likely to change due to lacking experience with Gradle plugins. @@ -97,18 +97,36 @@ pluginManagement { gradlePluginPortal() google() maven { - name = "GitHubPackages" - url = uri("https://maven.pkg.github.com/revanced/registry") - credentials { - username = providers.gradleProperty("gpr.user") - password = providers.gradleProperty("gpr.key") - } + name = "GitHubPackages" + url = uri("https://maven.pkg.github.com/revanced/registry") + credentials { + username = providers.gradleProperty("gpr.user") + password = providers.gradleProperty("gpr.key") + } } } } plugins { - id("app.revanced.patches") version "" + id("app.revanced.patches") version "" +} + +// This block is optional and can be used to configure the patches and extension projects. +settings { + // "patches" is the default. + patchesProjectPath = "patches" + + extensions { + // The path containing the extension projects. "extensions" is the default. + projectsPath = "extensions" + + // A default namespace for extension projects. null is the default. + defaultNamespace = "app.revanced.extension" + + // Proguard files relative to the extension project. + // By default, isMinifyEnabled is false, unless a ProGuard file is added. + proguardFiles("../proguard-rules.pro") + } } ``` @@ -132,15 +150,15 @@ patches { > [!NOTE] > By default, the plugin expects the patches project to be in the `patches` directory. -Create the extension project and configure the `build.gradle.kts` file: +Create the extension project and add an empty `build.gradle.kts` file. +Unless the `build.gradle.kts` file is empty, the plugin will not recognize the extension project. +By default, the extension name will be inferred from the relative path to the extension project. +For example, the extension name for the `extensions/extension` project will be `extensions/extension.rve`. +To set an extension name explicitly, add the following to the `build.gradle.kts` file: ```kotlin extension { - name = "extensions/extension.rve" -} - -android { - namespace = "app.revanced.extension" + name = "extensions/extension.rve" } ``` @@ -162,7 +180,9 @@ To build ReVanced Patches Gradle plugin, follow these steps: ## 📜 Licence ReVanced Patches Gradle plugin is licensed under the GPLv3 license. -Please see the [license file](LICENSE) for more information. [tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and modify +Please see the [license file](LICENSE) for more +information. [tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and +modify ReVanced Patches Gradle plugin as long as you track changes/dates in source files. Any modifications to ReVanced Patches Gradle plugin must also be made available under the GPL, along with build & install instructions. \ No newline at end of file diff --git a/api/revanced-patches-gradle-plugin.api b/api/revanced-patches-gradle-plugin.api index 3974dc6..88411b9 100644 --- a/api/revanced-patches-gradle-plugin.api +++ b/api/revanced-patches-gradle-plugin.api @@ -1,6 +1,7 @@ -public abstract class app/revanced/patches/gradle/ExtensionExtension { +public class app/revanced/patches/gradle/ExtensionExtension { public fun ()V - public abstract fun getName ()Lorg/gradle/api/provider/Property; + public final fun getName ()Ljava/lang/String; + public final fun setName (Ljava/lang/String;)V } public abstract class app/revanced/patches/gradle/ExtensionPlugin : org/gradle/api/Plugin { @@ -9,21 +10,35 @@ public abstract class app/revanced/patches/gradle/ExtensionPlugin : org/gradle/a public fun apply (Lorg/gradle/api/Project;)V } -public abstract class app/revanced/patches/gradle/PatchesExtension { - public fun (Lorg/gradle/api/model/ObjectFactory;)V +public final class app/revanced/patches/gradle/ExtensionPlugin$inlined$sam$i$org_gradle_api_Action$0 : org/gradle/api/Action { + public fun (Lkotlin/jvm/functions/Function1;)V + public final synthetic fun execute (Ljava/lang/Object;)V +} + +public class app/revanced/patches/gradle/PatchesExtension { + public fun ()V public final fun about (Lkotlin/jvm/functions/Function1;)V - public abstract fun getExtensionsProjectPath ()Lorg/gradle/api/provider/Property; + public final fun getAbout ()Lapp/revanced/patches/gradle/PatchesExtension$About; + public final fun getExtensionsProjectPath ()Ljava/lang/String; + public final fun setExtensionsProjectPath (Ljava/lang/String;)V } -public abstract class app/revanced/patches/gradle/PatchesExtension$About { - public fun (Lorg/gradle/api/Project;)V - public abstract fun getAuthor ()Lorg/gradle/api/provider/Property; - public abstract fun getContact ()Lorg/gradle/api/provider/Property; - public abstract fun getDescription ()Lorg/gradle/api/provider/Property; - public abstract fun getLicense ()Lorg/gradle/api/provider/Property; - public abstract fun getName ()Lorg/gradle/api/provider/Property; - public abstract fun getSource ()Lorg/gradle/api/provider/Property; - public abstract fun getWebsite ()Lorg/gradle/api/provider/Property; +public final class app/revanced/patches/gradle/PatchesExtension$About { + public fun ()V + public final fun getAuthor ()Ljava/lang/String; + public final fun getContact ()Ljava/lang/String; + public final fun getDescription ()Ljava/lang/String; + public final fun getLicense ()Ljava/lang/String; + public final fun getName ()Ljava/lang/String; + public final fun getSource ()Ljava/lang/String; + public final fun getWebsite ()Ljava/lang/String; + public final fun setAuthor (Ljava/lang/String;)V + public final fun setContact (Ljava/lang/String;)V + public final fun setDescription (Ljava/lang/String;)V + public final fun setLicense (Ljava/lang/String;)V + public final fun setName (Ljava/lang/String;)V + public final fun setSource (Ljava/lang/String;)V + public final fun setWebsite (Ljava/lang/String;)V } public abstract class app/revanced/patches/gradle/PatchesPlugin : org/gradle/api/Plugin { @@ -32,10 +47,32 @@ public abstract class app/revanced/patches/gradle/PatchesPlugin : org/gradle/api public fun apply (Lorg/gradle/api/Project;)V } -public abstract class app/revanced/patches/gradle/SettingsExtension { +public class app/revanced/patches/gradle/SettingsExtension { public fun ()V - public abstract fun getExtensionsProjectPath ()Lorg/gradle/api/provider/Property; - public abstract fun getPatchesProjectPath ()Lorg/gradle/api/provider/Property; + public final fun extensions (Lkotlin/jvm/functions/Function1;)V + public final fun getExtensionsExtension ()Lapp/revanced/patches/gradle/SettingsExtension$ExtensionsExtension; + public final fun getPatchesProjectPath ()Ljava/lang/String; + public final fun setPatchesProjectPath (Ljava/lang/String;)V +} + +public final class app/revanced/patches/gradle/SettingsExtension$ExtensionsExtension { + public fun ()V + public final fun getDefaultNamespace ()Ljava/lang/String; + public final fun getProjectsPath ()Ljava/lang/String; + public final fun proguardFiles ([Ljava/lang/String;)V + public final fun setDefaultNamespace (Ljava/lang/String;)V + public final fun setProjectsPath (Ljava/lang/String;)V +} + +public abstract class app/revanced/patches/gradle/SettingsExtensionProvider : org/gradle/api/services/BuildService, org/gradle/api/services/BuildServiceParameters { + public fun ()V +} + +public abstract interface class app/revanced/patches/gradle/SettingsExtensionProvider$Params : org/gradle/api/services/BuildServiceParameters { + public abstract fun getDefaultNamespace ()Ljava/lang/String; + public abstract fun getProguardFiles ()Ljava/util/Set; + public abstract fun setDefaultNamespace (Ljava/lang/String;)V + public abstract fun setProguardFiles (Ljava/util/Set;)V } public abstract class app/revanced/patches/gradle/SettingsPlugin : org/gradle/api/Plugin { diff --git a/build.gradle.kts b/build.gradle.kts index e2a6afe..cb5bcf8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,12 +16,14 @@ repositories { } dependencies { - implementation(gradleApi()) - implementation(gradleKotlinDsl()) + implementation(libs.android.application) implementation(libs.binary.compatibility.validator) + implementation(libs.guava) implementation(libs.kotlin) implementation(libs.kotlin.android) - implementation(libs.android.application) + + implementation(gradleApi()) + implementation(gradleKotlinDsl()) } java { diff --git a/gradle.properties b/gradle.properties index 6e97117..e471ea2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -org.gradle.parallel=true +org.gradle.parallel = true org.gradle.caching = true -kotlin.code.style=official -version=1.0.0 \ No newline at end of file +kotlin.code.style = official +version = 1.0.0-dev.8 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 77d7070..f040071 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,12 +4,14 @@ pluginPublish = "1.2.1" binary-compatibility-validator = "0.15.1" #noinspection GradleDependency agp = "8.2.2" # 8.3.0 causes Java verifier error: https://github.com/ReVanced/revanced-patches/issues/2818 +guava = "33.2.1-jre" [libraries] binary-compatibility-validator = { module = "org.jetbrains.kotlinx.binary-compatibility-validator:org.jetbrains.kotlinx.binary-compatibility-validator.gradle.plugin", version.ref = "binary-compatibility-validator" } kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } kotlin-android = { module = "org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin", version.ref = "kotlin" } android-application = { module = "com.android.application:com.android.application.gradle.plugin", version.ref = "agp" } +guava = { module = "com.google.guava:guava", version.ref = "guava" } [plugins] kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin"} diff --git a/package-lock.json b/package-lock.json index f281023..34df102 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,8 @@ "@saithodev/semantic-release-backmerge": "^4.0.1", "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", - "gradle-semantic-release-plugin": "^1.9.2", - "semantic-release": "^24.0.0" + "gradle-semantic-release-plugin": "^1.10.1", + "semantic-release": "^24.1.2" } }, "node_modules/@babel/code-frame": { @@ -235,13 +235,13 @@ "license": "MIT" }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.3.tgz", - "integrity": "sha512-o4WRoOJZlKqEEgj+i9CpcmnByvtzoUYC6I8PD2SA95M+BJ2x8h7oLcVOg9qcowWXBOdcTRsMZiwvM3EyLm9AfA==", + "version": "11.3.5", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.3.5.tgz", + "integrity": "sha512-cgwIRtKrpwhLoBi0CUNuY83DPGRMaWVjqVI/bGKsLJ4PzyWZNaEmhHroI2xlrVXkk6nFv0IsZpOp+ZWSWUS2AQ==", "dev": true, "license": "MIT", "dependencies": { - "@octokit/types": "^13.5.0" + "@octokit/types": "^13.6.0" }, "engines": { "node": ">= 18" @@ -251,9 +251,9 @@ } }, "node_modules/@octokit/plugin-retry": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.1.1.tgz", - "integrity": "sha512-G9Ue+x2odcb8E1XIPhaFBnTTIrrUDfXN05iFXiqhR+SeeeDMMILcAnysOsxUpEWcQp2e5Ft397FCXTcPkiPkLw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.1.2.tgz", + "integrity": "sha512-XOWnPpH2kJ5VTwozsxGurw+svB2e61aWlmk5EVIYZPwFK5F9h4cyPyj9CIKRyMXMHSwpIsI3mPOdpMmrRhe7UQ==", "dev": true, "license": "MIT", "dependencies": { @@ -302,9 +302,9 @@ } }, "node_modules/@octokit/request-error": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.4.tgz", - "integrity": "sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg==", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.5.tgz", + "integrity": "sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ==", "dev": true, "license": "MIT", "dependencies": { @@ -315,9 +315,9 @@ } }, "node_modules/@octokit/types": { - "version": "13.5.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.5.0.tgz", - "integrity": "sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==", + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.6.0.tgz", + "integrity": "sha512-CrooV/vKCXqwLa+osmHLIMUb87brpgUqlqkPGc6iE2wCkUvTrHiXFMhAKoDDaAAYJrtKtrFTgSQTg5nObBEaew==", "dev": true, "license": "MIT", "dependencies": { @@ -355,9 +355,9 @@ "license": "ISC" }, "node_modules/@pnpm/npm-conf": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.2.2.tgz", - "integrity": "sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", + "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", "dev": true, "license": "MIT", "dependencies": { @@ -977,6 +977,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@saithodev/semantic-release-backmerge/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/@saithodev/semantic-release-backmerge/node_modules/human-signals": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", @@ -1372,9 +1385,9 @@ } }, "node_modules/@semantic-release/github": { - "version": "10.1.1", - "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-10.1.1.tgz", - "integrity": "sha512-sSmsBKGpAlTtXf9rUJf/si16p+FwPEsvsJRjl3KCwFP0WywaSpynvUhlYvE18n5rzkQNbGJnObAKIoo3xFMSjA==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@semantic-release/github/-/github-11.0.0.tgz", + "integrity": "sha512-Uon6G6gJD8U1JNvPm7X0j46yxNRJ8Ui6SgK4Zw5Ktu8RgjEft3BGn+l/RX1TTzhhO3/uUcKuqM+/9/ETFxWS/Q==", "dev": true, "license": "MIT", "dependencies": { @@ -1399,7 +1412,7 @@ "node": ">=20.8.1" }, "peerDependencies": { - "semantic-release": ">=20.1.0" + "semantic-release": ">=24.1.0" } }, "node_modules/@semantic-release/github/node_modules/@semantic-release/error": { @@ -1569,9 +1582,9 @@ } }, "node_modules/@semantic-release/npm/node_modules/execa": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.3.0.tgz", - "integrity": "sha512-l6JFbqnHEadBoVAVpN5dl2yCyfX28WoBAGaoQcNmLLSedOxTxcn2Qa83s8I/PA5i56vWru2OHOtrwF7Om2vqlg==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.4.0.tgz", + "integrity": "sha512-yKHlle2YGxZE842MERVIplWwNH5VYmqqcPFgtnlU//K8gxuFFXu0pwd/CrfXTumFpeEiufsP7+opT/bPJa1yVw==", "dev": true, "license": "MIT", "dependencies": { @@ -1579,10 +1592,10 @@ "cross-spawn": "^7.0.3", "figures": "^6.1.0", "get-stream": "^9.0.0", - "human-signals": "^7.0.0", + "human-signals": "^8.0.0", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", - "npm-run-path": "^5.2.0", + "npm-run-path": "^6.0.0", "pretty-ms": "^9.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", @@ -1613,9 +1626,9 @@ } }, "node_modules/@semantic-release/npm/node_modules/human-signals": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-7.0.0.tgz", - "integrity": "sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.0.tgz", + "integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -1649,16 +1662,17 @@ } }, "node_modules/@semantic-release/npm/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^4.0.0" + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1703,6 +1717,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@semantic-release/npm/node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@semantic-release/release-notes-generator": { "version": "14.0.1", "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-14.0.1.tgz", @@ -2273,13 +2300,13 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "dev": true, "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -2358,9 +2385,9 @@ "license": "MIT" }, "node_modules/env-ci": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.0.0.tgz", - "integrity": "sha512-apikxMgkipkgTvMdRT9MNqWx5VLOci79F4VBd7Op/7OPjjoanjdAvn6fglMCCEf/1bAh8eOiuEVCUs4V3qP3nQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.1.0.tgz", + "integrity": "sha512-Z8dnwSDbV1XYM9SBF2J0GcNVvmfmfh3a49qddGIROhBoVro6MZVTji15z/sJbQ2ko2ei8n988EU1wzoLU/tF+g==", "dev": true, "license": "MIT", "dependencies": { @@ -2549,9 +2576,9 @@ } }, "node_modules/escalade": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", - "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -2847,9 +2874,9 @@ "license": "ISC" }, "node_modules/gradle-semantic-release-plugin": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/gradle-semantic-release-plugin/-/gradle-semantic-release-plugin-1.9.2.tgz", - "integrity": "sha512-8qpf4GYFPQ+UMUymYBy/VchOOwLILAWzZMrZX1R0RR3JMgJBMN2R0tJn92R/3rXmxx4OAqwUFH6Np51eFoxr3w==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/gradle-semantic-release-plugin/-/gradle-semantic-release-plugin-1.10.1.tgz", + "integrity": "sha512-Q4dLAFICjPouUyRRHEKK8cXNB75nraXoioYZDZlVQOg4sYKudnTDZ3ohLmV3k4cPGiiMCh1ckXETkx9JnuyKmA==", "dev": true, "funding": [ { @@ -2925,16 +2952,16 @@ } }, "node_modules/hosted-git-info": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", - "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-8.0.0.tgz", + "integrity": "sha512-4nw3vOVR+vHUOT8+U4giwe2tcGv+R3pwwRidUe67DoMBTjhrfr6rZYJVVwdkBE+Um050SG+X9tf0Jo4fOpn01w==", "dev": true, "license": "ISC", "dependencies": { "lru-cache": "^10.0.1" }, "engines": { - "node": "^16.14.0 || >=18.0.0" + "node": "^18.17.0 || >=20.5.0" } }, "node_modules/http-proxy-agent": { @@ -2976,9 +3003,9 @@ } }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { @@ -3191,9 +3218,9 @@ } }, "node_modules/is-unicode-supported": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", - "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz", + "integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==", "dev": true, "license": "MIT", "engines": { @@ -3497,9 +3524,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { @@ -3547,9 +3574,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, "license": "MIT" }, @@ -3610,6 +3637,19 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/normalize-package-data/node_modules/hosted-git-info": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz", + "integrity": "sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/normalize-url": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", @@ -3624,9 +3664,9 @@ } }, "node_modules/npm": { - "version": "10.8.2", - "resolved": "https://registry.npmjs.org/npm/-/npm-10.8.2.tgz", - "integrity": "sha512-x/AIjFIKRllrhcb48dqUNAAZl0ig9+qMuN91RpZo3Cb2+zuibfh+KISl6+kVVyktDz230JKc208UkQwwMqyB+w==", + "version": "10.8.3", + "resolved": "https://registry.npmjs.org/npm/-/npm-10.8.3.tgz", + "integrity": "sha512-0IQlyAYvVtQ7uOhDFYZCGK8kkut2nh8cpAdA9E6FvRSJaTgtZRZgNjlC5ZCct//L73ygrpY93CxXpRJDtNqPVg==", "bundleDependencies": [ "@isaacs/string-locale-compare", "@npmcli/arborist", @@ -3719,13 +3759,13 @@ "@sigstore/tuf": "^2.3.4", "abbrev": "^2.0.0", "archy": "~1.0.0", - "cacache": "^18.0.3", + "cacache": "^18.0.4", "chalk": "^5.3.0", "ci-info": "^4.0.0", "cli-columns": "^4.0.0", "fastest-levenshtein": "^1.0.16", "fs-minipass": "^3.0.3", - "glob": "^10.4.2", + "glob": "^10.4.5", "graceful-fs": "^4.2.11", "hosted-git-info": "^7.0.2", "ini": "^4.1.3", @@ -3734,7 +3774,7 @@ "json-parse-even-better-errors": "^3.0.2", "libnpmaccess": "^8.0.6", "libnpmdiff": "^6.1.4", - "libnpmexec": "^8.1.3", + "libnpmexec": "^8.1.4", "libnpmfund": "^5.0.12", "libnpmhook": "^10.0.5", "libnpmorg": "^6.0.6", @@ -3748,12 +3788,12 @@ "minipass": "^7.1.1", "minipass-pipeline": "^1.2.4", "ms": "^2.1.2", - "node-gyp": "^10.1.0", + "node-gyp": "^10.2.0", "nopt": "^7.2.1", "normalize-package-data": "^6.0.2", "npm-audit-report": "^5.0.0", "npm-install-checks": "^6.3.0", - "npm-package-arg": "^11.0.2", + "npm-package-arg": "^11.0.3", "npm-pick-manifest": "^9.1.0", "npm-profile": "^10.0.0", "npm-registry-fetch": "^17.1.0", @@ -3764,7 +3804,7 @@ "proc-log": "^4.2.0", "qrcode-terminal": "^0.12.0", "read": "^3.0.1", - "semver": "^7.6.2", + "semver": "^7.6.3", "spdx-expression-parse": "^4.0.0", "ssri": "^10.0.6", "supports-color": "^9.4.0", @@ -4335,7 +4375,7 @@ } }, "node_modules/npm/node_modules/cacache": { - "version": "18.0.3", + "version": "18.0.4", "dev": true, "inBundle": true, "license": "ISC", @@ -4502,7 +4542,7 @@ } }, "node_modules/npm/node_modules/debug": { - "version": "4.3.5", + "version": "4.3.6", "dev": true, "inBundle": true, "license": "MIT", @@ -4586,7 +4626,7 @@ } }, "node_modules/npm/node_modules/foreground-child": { - "version": "3.2.1", + "version": "3.3.0", "dev": true, "inBundle": true, "license": "ISC", @@ -4614,7 +4654,7 @@ } }, "node_modules/npm/node_modules/glob": { - "version": "10.4.2", + "version": "10.4.5", "dev": true, "inBundle": true, "license": "ISC", @@ -4629,9 +4669,6 @@ "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -4815,16 +4852,13 @@ "license": "ISC" }, "node_modules/npm/node_modules/jackspeak": { - "version": "3.4.0", + "version": "3.4.3", "dev": true, "inBundle": true, "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -4910,7 +4944,7 @@ } }, "node_modules/npm/node_modules/libnpmexec": { - "version": "8.1.3", + "version": "8.1.4", "dev": true, "inBundle": true, "license": "ISC", @@ -5044,13 +5078,10 @@ } }, "node_modules/npm/node_modules/lru-cache": { - "version": "10.2.2", + "version": "10.4.3", "dev": true, "inBundle": true, - "license": "ISC", - "engines": { - "node": "14 || >=16.14" - } + "license": "ISC" }, "node_modules/npm/node_modules/make-fetch-happen": { "version": "13.0.1", @@ -5262,7 +5293,7 @@ } }, "node_modules/npm/node_modules/node-gyp": { - "version": "10.1.0", + "version": "10.2.0", "dev": true, "inBundle": true, "license": "MIT", @@ -5273,9 +5304,9 @@ "graceful-fs": "^4.2.6", "make-fetch-happen": "^13.0.0", "nopt": "^7.0.0", - "proc-log": "^3.0.0", + "proc-log": "^4.1.0", "semver": "^7.3.5", - "tar": "^6.1.2", + "tar": "^6.2.1", "which": "^4.0.0" }, "bin": { @@ -5285,15 +5316,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/npm/node_modules/node-gyp/node_modules/proc-log": { - "version": "3.0.0", - "dev": true, - "inBundle": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/npm/node_modules/nopt": { "version": "7.2.1", "dev": true, @@ -5366,7 +5388,7 @@ } }, "node_modules/npm/node_modules/npm-package-arg": { - "version": "11.0.2", + "version": "11.0.3", "dev": true, "inBundle": true, "license": "ISC", @@ -5540,7 +5562,7 @@ } }, "node_modules/npm/node_modules/postcss-selector-parser": { - "version": "6.1.0", + "version": "6.1.2", "dev": true, "inBundle": true, "license": "MIT", @@ -5678,7 +5700,7 @@ "optional": true }, "node_modules/npm/node_modules/semver": { - "version": "7.6.2", + "version": "7.6.3", "dev": true, "inBundle": true, "license": "ISC", @@ -6437,9 +6459,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", - "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true, "license": "ISC" }, @@ -6481,9 +6503,9 @@ } }, "node_modules/pretty-ms": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.0.0.tgz", - "integrity": "sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.1.0.tgz", + "integrity": "sha512-o1piW0n3tgKIKCwk2vpM/vOV13zjJzvP37Ioze54YlTHE06m4tjEbzg9WsKkvTuyYln2DHjo5pY4qrZGI0otpw==", "dev": true, "license": "MIT", "dependencies": { @@ -6738,15 +6760,15 @@ "license": "MIT" }, "node_modules/semantic-release": { - "version": "24.0.0", - "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.0.0.tgz", - "integrity": "sha512-v46CRPw+9eI3ZuYGF2oAjqPqsfbnfFTwLBgQsv/lch4goD09ytwOTESMN4QIrx/wPLxUGey60/NMx+ANQtWRsA==", + "version": "24.1.2", + "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.1.2.tgz", + "integrity": "sha512-hvEJ7yI97pzJuLsDZCYzJgmRxF8kiEJvNZhf0oiZQcexw+Ycjy4wbdsn/sVMURgNCu8rwbAXJdBRyIxM4pe32g==", "dev": true, "license": "MIT", "dependencies": { "@semantic-release/commit-analyzer": "^13.0.0-beta.1", "@semantic-release/error": "^4.0.0", - "@semantic-release/github": "^10.0.0", + "@semantic-release/github": "^11.0.0", "@semantic-release/npm": "^12.0.0", "@semantic-release/release-notes-generator": "^14.0.0-beta.1", "aggregate-error": "^5.0.0", @@ -6759,7 +6781,7 @@ "get-stream": "^6.0.0", "git-log-parser": "^1.2.0", "hook-std": "^3.0.0", - "hosted-git-info": "^7.0.0", + "hosted-git-info": "^8.0.0", "import-from-esm": "^1.3.1", "lodash-es": "^4.17.21", "marked": "^12.0.0", @@ -6851,9 +6873,9 @@ } }, "node_modules/semantic-release/node_modules/execa": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-9.3.0.tgz", - "integrity": "sha512-l6JFbqnHEadBoVAVpN5dl2yCyfX28WoBAGaoQcNmLLSedOxTxcn2Qa83s8I/PA5i56vWru2OHOtrwF7Om2vqlg==", + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-9.4.0.tgz", + "integrity": "sha512-yKHlle2YGxZE842MERVIplWwNH5VYmqqcPFgtnlU//K8gxuFFXu0pwd/CrfXTumFpeEiufsP7+opT/bPJa1yVw==", "dev": true, "license": "MIT", "dependencies": { @@ -6861,10 +6883,10 @@ "cross-spawn": "^7.0.3", "figures": "^6.1.0", "get-stream": "^9.0.0", - "human-signals": "^7.0.0", + "human-signals": "^8.0.0", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", - "npm-run-path": "^5.2.0", + "npm-run-path": "^6.0.0", "pretty-ms": "^9.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", @@ -6895,9 +6917,9 @@ } }, "node_modules/semantic-release/node_modules/human-signals": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-7.0.0.tgz", - "integrity": "sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.0.tgz", + "integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -6931,16 +6953,17 @@ } }, "node_modules/semantic-release/node_modules/npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", + "integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^4.0.0" + "path-key": "^4.0.0", + "unicorn-magic": "^0.3.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -6998,6 +7021,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/semantic-release/node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -7239,9 +7275,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.18", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz", - "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==", + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.20.tgz", + "integrity": "sha512-jg25NiDV/1fLtSgEgyvVyDunvaNHbuwF9lfNV17gSmPFAlYzdfNBlLtLzXTevwkPj7DhGbmN9VnmJIgLnhvaBw==", "dev": true, "license": "CC0-1.0" }, @@ -7365,9 +7401,9 @@ } }, "node_modules/supports-hyperlinks": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.0.0.tgz", - "integrity": "sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.1.0.tgz", + "integrity": "sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==", "dev": true, "license": "MIT", "dependencies": { @@ -7376,6 +7412,9 @@ }, "engines": { "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/temp-dir": { @@ -7530,9 +7569,9 @@ } }, "node_modules/type-fest": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.22.1.tgz", - "integrity": "sha512-9tHNEa0Ov81YOopiVkcCJVz5TM6AEQ+CHHjFIktqPnE3NV0AHIkx+gh9tiCl58m/66wWxkOC9eltpa75J4lQPA==", + "version": "4.26.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz", + "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -7543,9 +7582,9 @@ } }, "node_modules/uglify-js": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.0.tgz", - "integrity": "sha512-wNKHUY2hYYkf6oSFfhwwiHo4WCHzHmzcXsqXYTN9ja3iApYIFbb2U6ics9hBcYLHcYGQoAlwnZlTrf3oF+BL/Q==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, "license": "BSD-2-Clause", "optional": true, diff --git a/package.json b/package.json index 5977269..105a5ca 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "@saithodev/semantic-release-backmerge": "^4.0.1", "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", - "gradle-semantic-release-plugin": "^1.9.2", - "semantic-release": "^24.0.0" + "gradle-semantic-release-plugin": "^1.10.1", + "semantic-release": "^24.1.2" } } diff --git a/src/main/kotlin/app/revanced/patches/gradle/ExtensionExtension.kt b/src/main/kotlin/app/revanced/patches/gradle/ExtensionExtension.kt index 5ce16c3..e6811e6 100644 --- a/src/main/kotlin/app/revanced/patches/gradle/ExtensionExtension.kt +++ b/src/main/kotlin/app/revanced/patches/gradle/ExtensionExtension.kt @@ -1,13 +1,11 @@ package app.revanced.patches.gradle -import org.gradle.api.provider.Property - -abstract class ExtensionExtension { +open class ExtensionExtension { /** * The name of the extension. * * The name is the full resource path of the extension in the final patches file. * Example: `extensions/extension.rve`. */ - abstract val name: Property + var name: String? = null } diff --git a/src/main/kotlin/app/revanced/patches/gradle/ExtensionPlugin.kt b/src/main/kotlin/app/revanced/patches/gradle/ExtensionPlugin.kt index 2038423..4bdd1d8 100644 --- a/src/main/kotlin/app/revanced/patches/gradle/ExtensionPlugin.kt +++ b/src/main/kotlin/app/revanced/patches/gradle/ExtensionPlugin.kt @@ -7,6 +7,8 @@ import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.ExtensionAware import org.gradle.api.tasks.Sync +import org.gradle.kotlin.dsl.getByType +import org.gradle.kotlin.dsl.register import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper import kotlin.io.path.Path @@ -17,7 +19,10 @@ abstract class ExtensionPlugin : Plugin { override fun apply(project: Project) { val extension = project.extensions.create("extension", ExtensionExtension::class.java) - project.configureAndroid() + val settingsExtensionProvider = project.gradle.sharedServices.registrations + .findByName("settingsExtensionProvider")!!.service.get() as SettingsExtensionProvider + + project.configureAndroid(settingsExtensionProvider) project.configureArtifactSharing(extension) } @@ -25,37 +30,44 @@ abstract class ExtensionPlugin : Plugin { * Setup sharing the extension dex file with the consuming patches project. */ private fun Project.configureArtifactSharing(extension: ExtensionExtension) { - val syncExtensionTask = tasks.register("syncExtension", Sync::class.java) { - it.apply { - dependsOn("assembleRelease") + val androidExtension = extensions.getByType() + val syncExtensionTask = tasks.register("syncExtension") { + val dexTaskName = if (androidExtension.buildTypes.getByName("release").isMinifyEnabled) { + "minifyReleaseWithR8" + } else { + "mergeDexRelease" + } - val apk = layout.buildDirectory.dir("outputs/apk/release").map { dir -> - dir.asFile.listFiles { _, name -> name.endsWith(".apk") }!!.first() - } + val dexTask = tasks.getByName(dexTaskName) - from(zipTree(apk).matching { include("classes.dex") }) - into( - layout.buildDirectory.zip(extension.name) { buildDirectory, extensionName -> - buildDirectory.dir("revanced/${Path(extensionName).parent.pathString}") - }, - ) + dependsOn(dexTask) - rename { "${Path(extension.name.get()).fileName}" } + val extensionName = if (extension.name != null) { + Path(extension.name!!) + } else { + projectDir.resolveSibling(project.name + ".rve").relativeTo(rootDir).toPath() } + + from(dexTask.outputs.files.asFileTree.matching { include("**/*.dex") }) + into(layout.buildDirectory.dir("revanced/${extensionName.parent.pathString}")) + + rename { extensionName.fileName.toString() } } - configurations.consumable("extensionConfiguration").also { configuration -> - artifacts.add( - configuration.name, - layout.buildDirectory.dir("revanced"), - ) { artifact -> artifact.builtBy(syncExtensionTask) } + configurations.create("extensionConfiguration").apply { + isCanBeResolved = false + isCanBeConsumed = true + + outgoing.artifact(layout.buildDirectory.dir("revanced")) { + it.builtBy(syncExtensionTask) + } } } /** * Set up the Android plugin for the extension project. */ - private fun Project.configureAndroid() { + private fun Project.configureAndroid(settingsExtensionProvider: SettingsExtensionProvider) { pluginManager.apply { apply(AppPlugin::class.java) apply(KotlinAndroidPluginWrapper::class.java) @@ -63,7 +75,8 @@ abstract class ExtensionPlugin : Plugin { extensions.configure(BaseAppModuleExtension::class.java) { it.apply { - compileSdk = 33 + compileSdk = 34 + namespace = settingsExtensionProvider.parameters.defaultNamespace defaultConfig { minSdk = 23 @@ -72,25 +85,23 @@ abstract class ExtensionPlugin : Plugin { buildTypes { release { - // If this were true by default, and no proguard files would be present, - // no dex file would be generated. - isMinifyEnabled = false + isMinifyEnabled = settingsExtensionProvider.parameters.proguardFiles.isNotEmpty() proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro", + *settingsExtensionProvider.parameters.proguardFiles.toTypedArray(), ) } } compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } this as ExtensionAware this.extensions.configure("kotlinOptions") { options -> - options.jvmTarget = JavaVersion.VERSION_11.toString() + options.jvmTarget = JavaVersion.VERSION_17.toString() } } } diff --git a/src/main/kotlin/app/revanced/patches/gradle/PatchesExtension.kt b/src/main/kotlin/app/revanced/patches/gradle/PatchesExtension.kt index 4470d62..74a8037 100644 --- a/src/main/kotlin/app/revanced/patches/gradle/PatchesExtension.kt +++ b/src/main/kotlin/app/revanced/patches/gradle/PatchesExtension.kt @@ -1,12 +1,6 @@ package app.revanced.patches.gradle -import org.gradle.api.Project -import org.gradle.api.model.ObjectFactory -import org.gradle.api.provider.Property -import javax.inject.Inject - -@Suppress("unused") -abstract class PatchesExtension @Inject constructor(objectFactory: ObjectFactory) { +open class PatchesExtension { /** * The path to the extensions project relative to the root project. * @@ -14,37 +8,29 @@ abstract class PatchesExtension @Inject constructor(objectFactory: ObjectFactory * * Defaults to `:extensions`. */ - abstract val extensionsProjectPath: Property + var extensionsProjectPath: String? = ":extensions" - internal val about = objectFactory.newInstance(About::class.java) + /** + * About information for the project. + */ + val about = About() fun about(block: About.() -> Unit) { about.block() } - init { - extensionsProjectPath.convention(":extensions") - } - /** * About information for the project. * * Used by the patches plugin to create the manifest file and set up the publication of the patches project. */ - abstract class About @Inject constructor(project: Project) { - abstract val name: Property - abstract val description: Property - abstract val source: Property - abstract val author: Property - abstract val contact: Property - abstract val website: Property - abstract val license: Property - internal abstract val version: Property - internal abstract val timestamp: Property - - init { - version.convention(project.version.toString()) - timestamp.convention(System.currentTimeMillis()) - } + class About { + var name: String? = null + var description: String? = null + var source: String? = null + var author: String? = null + var contact: String? = null + var website: String? = null + var license: String? = null } } diff --git a/src/main/kotlin/app/revanced/patches/gradle/PatchesPlugin.kt b/src/main/kotlin/app/revanced/patches/gradle/PatchesPlugin.kt index 754bb3e..4fe9a4d 100644 --- a/src/main/kotlin/app/revanced/patches/gradle/PatchesPlugin.kt +++ b/src/main/kotlin/app/revanced/patches/gradle/PatchesPlugin.kt @@ -1,5 +1,11 @@ package app.revanced.patches.gradle +import com.android.tools.build.apkzlib.zip.ZFile +import com.android.tools.r8.CompilationMode +import com.android.tools.r8.D8 +import com.android.tools.r8.D8Command +import com.android.tools.r8.OutputMode +import com.android.tools.r8.utils.ArchiveResourceProvider import kotlinx.validation.BinaryCompatibilityValidatorPlugin import org.gradle.api.JavaVersion import org.gradle.api.Plugin @@ -12,7 +18,6 @@ import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.tasks.SourceSetContainer import org.gradle.jvm.tasks.Jar import org.gradle.kotlin.dsl.get -import org.gradle.kotlin.dsl.support.listFilesOrdered import org.gradle.plugins.signing.SigningExtension import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension @@ -95,39 +100,38 @@ abstract class PatchesPlugin : Plugin { extensions.configure("signing") { it.useGpgCmd() - extensions.getByType(PublishingExtension::class.java).publications.named { - it == "revanced-patches-publication" - }.configureEach(it::sign) + extensions.getByType(PublishingExtension::class.java).publications + .named("ReVancedPatches").configure(it::sign) } } /** - * Adds a task to build the DEX file of the patches and add it to the patches file to use on Android, + * Adds a task to build the DEX file of the patches and adds it to the patches file to use on Android, * adds the publishing plugin to the project to publish the patches API and * configures the publication with the "about" information from the extension. */ private fun Project.configurePublishing(patchesExtension: PatchesExtension) { - tasks.register("buildDexJar") { - it.description = "Build and add a DEX to the JAR file" - it.group = "build" + val buildAndroid = tasks.register("buildAndroid") { task -> + task.description = "Builds the project for Android by compiling to DEX and adding it to the patches file." + task.group = "build" - it.dependsOn(tasks["build"]) + task.dependsOn(tasks["jar"]) - it.doLast { - val d8 = File(System.getenv("ANDROID_HOME")).resolve("build-tools") - .listFilesOrdered().last().resolve("d8").absolutePath + task.doLast { + val workingDirectory = layout.buildDirectory.dir("revanced").get().asFile.also(File::mkdirs) - val patchesJar = configurations["archives"].allArtifacts.files.files.first().absolutePath - val workingDirectory = layout.buildDirectory.dir("libs").get().asFile + val patchesFile = tasks["jar"].outputs.files.first() + val classesZipFile = workingDirectory.resolve("classes.zip") - exec { execSpec -> - execSpec.workingDir = workingDirectory - execSpec.commandLine = listOf(d8, "--release", patchesJar) - } + D8Command.builder() + .addProgramResourceProvider(ArchiveResourceProvider.fromArchive(patchesFile.toPath(), true)) + .setMode(CompilationMode.RELEASE) + .setOutput(classesZipFile.toPath(), OutputMode.DexIndexed) + .build() + .let(D8::run) - exec { execSpec -> - execSpec.workingDir = workingDirectory - execSpec.commandLine = listOf("zip", "-u", patchesJar, "classes.dex") + ZFile.openReadWrite(patchesFile).use { zFile -> + zFile.mergeFrom(ZFile.openReadOnly(classesZipFile)) { false } } } } @@ -135,8 +139,14 @@ abstract class PatchesPlugin : Plugin { pluginManager.apply("maven-publish") extensions.configure(PublishingExtension::class.java) { extension -> + // Necessary for the signing plugin for a publication to be created + // and the signing plugin to sign the publication, when no repositories are defined. + extension.repositories.mavenLocal { + it.name = "DummyMavenLocal" + } + extension.publications { container -> - container.create("revanced-patches-publication", MavenPublication::class.java) { + container.create("ReVancedPatches", MavenPublication::class.java) { it.from(components["java"]) val about = patchesExtension.about @@ -167,7 +177,7 @@ abstract class PatchesPlugin : Plugin { // Used by gradle-semantic-release-plugin. // Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435 tasks["publish"].apply { - dependsOn("buildDexJar") + dependsOn(buildAndroid) } } @@ -176,13 +186,13 @@ abstract class PatchesPlugin : Plugin { */ private fun Project.configureConsumeExtensions(patchesExtension: PatchesExtension) { val extensionsProject = try { - project(patchesExtension.extensionsProjectPath.get()) + project(patchesExtension.extensionsProjectPath ?: return) } catch (e: UnknownProjectException) { return } - val extensionProjects = extensionsProject.subprojects.filter { - it.parent == extensionsProject + val extensionProjects = extensionsProject.subprojects.filter { extensionProject -> + extensionProject.plugins.hasPlugin(ExtensionPlugin::class.java) } val extensionsDependencyScopeConfiguration = @@ -222,8 +232,8 @@ private fun Project.configureJarTask(patchesExtension: PatchesExtension) { it.manifest.apply { attributes["Name"] = patchesExtension.about.name attributes["Description"] = patchesExtension.about.description - attributes["Version"] = patchesExtension.about.version - attributes["Timestamp"] = patchesExtension.about.timestamp + attributes["Version"] = project.version.toString() + attributes["Timestamp"] = System.currentTimeMillis().toString() attributes["Source"] = patchesExtension.about.source attributes["Author"] = patchesExtension.about.author attributes["Contact"] = patchesExtension.about.contact @@ -232,4 +242,3 @@ private fun Project.configureJarTask(patchesExtension: PatchesExtension) { } } } - diff --git a/src/main/kotlin/app/revanced/patches/gradle/SettingsExtension.kt b/src/main/kotlin/app/revanced/patches/gradle/SettingsExtension.kt index 6692fda..5eff529 100644 --- a/src/main/kotlin/app/revanced/patches/gradle/SettingsExtension.kt +++ b/src/main/kotlin/app/revanced/patches/gradle/SettingsExtension.kt @@ -1,30 +1,40 @@ package app.revanced.patches.gradle -import org.gradle.api.provider.Property - -abstract class SettingsExtension { +open class SettingsExtension { /** - * The path to the patches project relative to the root project. - * - * Used by the settings plugin to include the patches project - * and apply the patches plugin to the patches project. - * - * Defaults to `patches`. + * The path to the patches project. */ - abstract val patchesProjectPath: Property + var patchesProjectPath = "patches" - /** - * The path to the extensions project relative to the root project. - * - * Used by the settings plugin to include the extensions project - * and apply the extensions plugin to the extensions project. - * - * Defaults to `extensions`. - */ - abstract val extensionsProjectPath: Property + // Need to rename, otherwise it will conflict with the `getExtensions` property from ExtensionAware. + @get:JvmName("getExtensionsExtension") + val extensions = ExtensionsExtension() + + fun extensions(block: ExtensionsExtension.() -> Unit) { + extensions.apply(block) + } + + class ExtensionsExtension { + /** + * The path containing the extension projects. + */ + var projectsPath: String? = "extensions" + + /** + * The default namespace for the extension projects. + */ + var defaultNamespace: String? = null + + internal val proguardFiles = mutableSetOf() - init { - patchesProjectPath.convention("patches") - extensionsProjectPath.convention("extensions") + /** + * Add proguard files to the extension projects relative to the project root. + * Minification will be enabled if at least one file is provided. + * + * @param files The proguard files to add. + */ + fun proguardFiles(vararg files: String) { + proguardFiles += files + } } } diff --git a/src/main/kotlin/app/revanced/patches/gradle/SettingsExtensionProvider.kt b/src/main/kotlin/app/revanced/patches/gradle/SettingsExtensionProvider.kt new file mode 100644 index 0000000..4e09e07 --- /dev/null +++ b/src/main/kotlin/app/revanced/patches/gradle/SettingsExtensionProvider.kt @@ -0,0 +1,13 @@ +package app.revanced.patches.gradle + +import org.gradle.api.services.BuildService +import org.gradle.api.services.BuildServiceParameters + +abstract class SettingsExtensionProvider : + BuildService, + BuildServiceParameters { + interface Params : BuildServiceParameters { + var defaultNamespace: String? + var proguardFiles: Set + } +} diff --git a/src/main/kotlin/app/revanced/patches/gradle/SettingsPlugin.kt b/src/main/kotlin/app/revanced/patches/gradle/SettingsPlugin.kt index 59250c9..2c4e0eb 100644 --- a/src/main/kotlin/app/revanced/patches/gradle/SettingsPlugin.kt +++ b/src/main/kotlin/app/revanced/patches/gradle/SettingsPlugin.kt @@ -14,9 +14,20 @@ abstract class SettingsPlugin @Inject constructor( override fun apply(settings: Settings) { val extension = settings.extensions.create("settings", SettingsExtension::class.java) + settings.gradle.settingsEvaluated { + settings.gradle.sharedServices.registerIfAbsent( + "settingsExtensionProvider", + SettingsExtensionProvider::class.java, + ) { + it.parameters.apply { + defaultNamespace = extension.extensions.defaultNamespace + proguardFiles = extension.extensions.proguardFiles + } + } + } + settings.configureDependencies() - settings.configureIncludeProjects(extension) - settings.configurePlugins(extension) + settings.configureProjects(extension) } /** @@ -31,46 +42,58 @@ abstract class SettingsPlugin @Inject constructor( // A repository must be specified. "registry" is a dummy. repository.url = URI("https://maven.pkg.github.com/revanced/registry") repository.credentials { - it.username = providers.gradleProperty("gpr.user") - .orElse(System.getenv("GITHUB_ACTOR")).get() - it.password = providers.gradleProperty("gpr.key") - .orElse(System.getenv("GITHUB_TOKEN")).get() + it.username = providers.gradleProperty("gpr.user").orNull ?: System.getenv("GITHUB_ACTOR") + it.password = providers.gradleProperty("gpr.key").orNull ?: System.getenv("GITHUB_TOKEN") } } } } /** - * Add the patches and extension projects to the root project. + * Adds the required plugins to the patches and extension projects. */ - private fun Settings.configureIncludeProjects(extension: SettingsExtension) { - include(extension.patchesProjectPath.get()) + private fun Settings.configureProjects(extension: SettingsExtension) { + // region Include the projects - objectFactory.fileTree().from(settingsDir.resolve(extension.extensionsProjectPath.get())).matching { - it.include("**/build.gradle.kts") - }.forEach { - include(it.relativeTo(settingsDir).toPath().joinToString(":")) + val extensionsProjectPath = extension.extensions.projectsPath + + if (extensionsProjectPath != null) { + objectFactory.fileTree().from(rootDir.resolve(extensionsProjectPath)).matching { + it.include("**/build.gradle.kts") + }.forEach { + include(it.relativeTo(rootDir).toPath().joinToString(":")) + } } - } - /** - * Adds the required plugins to the patches and extension projects. - */ - private fun Settings.configurePlugins(extension: SettingsExtension) { - gradle.rootProject { rootProject -> - rootProject.project(extension.patchesProjectPath.get()).pluginManager.apply(PatchesPlugin::class.java) + include(extension.patchesProjectPath) - try { - rootProject.project(extension.extensionsProjectPath.get()) - } catch (e: UnknownProjectException) { - return@rootProject - }.let { extensionsProject -> - extensionsProject.subprojects { extensionProject -> - if (extensionProject.parent != extensionsProject) return@subprojects + // endregion - extensionProject.pluginManager.apply(ExtensionPlugin::class.java) + // region Apply the plugins + + gradle.rootProject { rootProject -> + if (extensionsProjectPath != null) { + val extensionsProject = try { + rootProject.project(extensionsProjectPath) + } catch (e: UnknownProjectException) { + null + } + + extensionsProject?.subprojects { extensionProject -> + if ( + extensionProject.buildFile.exists() && + !extensionProject.parent!!.plugins.hasPlugin(ExtensionPlugin::class.java) + ) { + extensionProject.pluginManager.apply(ExtensionPlugin::class.java) + } } } + + // Needs to be applied after the extension plugin + // so that their extensionConfiguration is available for consumption. + rootProject.project(extension.patchesProjectPath).pluginManager.apply(PatchesPlugin::class.java) } + + // endregion } }