Skip to content

Commit

Permalink
rework build and license management
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathanlermitage committed Dec 31, 2023
1 parent 32aca2f commit 63fbc4a
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 46 deletions.
8 changes: 5 additions & 3 deletions CHANGELOG.md
@@ -1,8 +1,9 @@
# Extra Icons Change Log

## 2024.1.1 (planned for 2024/01/02)
## 2024.1.1 (2024/01/02)
* **INFO**: JetBrains will introduce a new business model for paid/freemium plugins. This model will offer a perpetual license, **allowing users to make a one-time payment for the plugin and use it for a lifetime**. [Get more information here](https://github.com/jonathanlermitage/intellij-extra-icons-plugin/blob/master/docs/LICENSE_FAQ.md#how-to-get-a-lifetime-license). There is no ETA yet.
* build script: prepare the work for the introduction of lifetime licenses.
* fix [#175](https://github.com/jonathanlermitage/intellij-extra-icons-plugin/issues/175): ` java.lang.Throwable: Must be precomputed`. UI Scale detection could fail at startup. It should be fixed now.
* initial support of [Flutter](https://flutter.dev) icons.
* improve Prettier support.
* improve Gradle support.
Expand All @@ -12,7 +13,8 @@
* support `(.)log(s)`folders.
* support `.noai` files (which tell the AI Assistant plugin to block AI features for the containing project).
* support [Detekt](https://detekt.dev/docs/introduction/configurations/) files ending by `detekt-config.yml` or `detekt.yml` (I may try to pick the configured Detekt filename from the `build.gradle(.kts)` file later).
* plugin's license is now verified occasionally, in addition the verification done by IDE at startup.
* support Qodana `qodana.yaml` files.
* plugin's license is now verified occasionally, in addition to the verification done by IDE at startup.
* starting from 2024, I will occasionally send some [coupons](https://github.com/jonathanlermitage/intellij-extra-icons-plugin/blob/master/docs/LICENSE_FAQ.md#i-received-a-coupon-for-a-free-license-how-does-it-work) for Free licenses on [Twitter](https://twitter.com/JLermitage) and [Bluesky](https://bsky.app/profile/jonathanlermitage.bsky.social). Stay tuned.

## 2023.4.2 (2023/12/03)
Expand Down Expand Up @@ -936,7 +938,7 @@ This way, you simply have to download the latest version offered by the plugin m
* support `jenkins`, `NOTICE`, `CONTACT` files (with `.md`, `.adoc`, `.txt` or no extension).

## 0.4 (2018/08/26)
* enabled compatibility with all products (WebStorm, etc).
* enabled compatibility with all products (WebStorm, etc.).
* rework Maven wrapper `mvnw`, Gradle wrapper `gradlew` files.
* support `README`, `CHANGELOG`, `CHANGES`, `LICENSE`, `COPYING`, `CONTRIBUTING`, `AUTHORS` files (with `.md`, `.adoc`, `.txt` or no extension).

Expand Down
19 changes: 10 additions & 9 deletions Makefile
Expand Up @@ -59,46 +59,47 @@ runold: intro ## run plugin in oldest supported IntelliJ Community version

.PHONY: build
build: intro ## build and package a plugin which asks for a paid subscription license to build/distribution/ (see generated ZIP file)
${gradlew_cmd} clean buildPlugin test modernizer biz-lermitage-oga-gradle-check verifyPlugin showGeneratedPlugin --warning-mode all -PpluginLicenseType=subscription
${gradlew_cmd} clean buildPlugin test modernizer biz-lermitage-oga-gradle-check verifyPlugin showGeneratedPlugin -PpluginLicenseType=subscription


.PHONY: buildfree
buildfree: intro ## build and package a plugin which doesn't ask for a paid license to build/distribution/ (see generated ZIP file)
${gradlew_cmd} clean buildPlugin test modernizer biz-lermitage-oga-gradle-check verifyPlugin showGeneratedPlugin --warning-mode all -PpluginLicenseType=free
${gradlew_cmd} clean buildPlugin test modernizer biz-lermitage-oga-gradle-check verifyPlugin showGeneratedPlugin -PpluginLicenseType=free


.PHONY: buildlifetime
buildlifetime: intro ## build and package a plugin which asks for a paid lifetime license to build/distribution/ (see generated ZIP file)
${gradlew_cmd} clean buildPlugin test modernizer biz-lermitage-oga-gradle-check verifyPlugin showGeneratedPlugin --warning-mode all -PpluginLicenseType=lifetime
${gradlew_cmd} clean buildPlugin test modernizer biz-lermitage-oga-gradle-check verifyPlugin showGeneratedPlugin -PpluginLicenseType=lifetime


.PHONY: lint
lint: intro ## run linter(s), for now Modernizer
${gradlew_cmd} modernizer --warning-mode all
${gradlew_cmd} modernizer


.PHONY: test
test: intro ## run unit tests
${gradlew_cmd} cleanTest test verifyPlugin --warning-mode all
${gradlew_cmd} cleanTest test verifyPlugin


.PHONY: cv
cv: intro ## check dependencies and Gradle updates
${gradlew_cmd} dependencyUpdates --warning-mode all --console=plain
${gradlew_cmd} dependencyUpdates


.PHONY: cvnd
cvnd: intro ## check dependencies and Gradle updates (use a single-use Gradle daemon process by using --no-daemon)
${gradlew_cmd} dependencyUpdates --warning-mode all --no-daemon --console=plain
${gradlew_cmd} dependencyUpdates --no-daemon


.PHONY: oga
oga: intro ## check for deprecated groupId and artifactId coordinates
${gradlew_cmd} biz-lermitage-oga-gradle-check --console=plain
${gradlew_cmd} biz-lermitage-oga-gradle-check


.PHONY: svgo
svgo: intro ## optimize SVG icons with SVGO (SVGO must be present, type "npm install -g svgo" if needed)
svgo --folder=misc/ --recursive
svgo --folder=src/main/resources/ --recursive


Expand All @@ -114,7 +115,7 @@ dt: intro ## show dependencies graph

.PHONY: publish
publish: intro ## publish package to the JetBrains marketplace
${gradlew_cmd} clean buildPlugin test verifyPlugin publishPlugin --warning-mode all
${gradlew_cmd} clean buildPlugin test verifyPlugin publishPlugin


.PHONY: help
Expand Down
103 changes: 96 additions & 7 deletions build.gradle.kts
Expand Up @@ -31,6 +31,11 @@ plugins {
val pluginXmlFile = projectDir.resolve("src/main/resources/META-INF/plugin.xml")
val pluginXmlFileBackup = projectDir.resolve("plugin.backup.xml")

val pluginLogoFile = projectDir.resolve("src/main/resources/META-INF/pluginIcon.svg")
val pluginLogoFileBackup = projectDir.resolve("pluginIcon.backup.svg")
val pluginLogoLifetimeFile = projectDir.resolve("misc/pluginIcon.lifetime.svg")
val pluginLogoFreeFile = projectDir.resolve("misc/pluginIcon.free.svg")

// Import variables from gradle.properties file
val pluginDownloadIdeaSources: String by project
val pluginVersion: String by project
Expand Down Expand Up @@ -88,9 +93,21 @@ dependencies {
}

intellij {
when (pluginLicenseType) {
"free" -> {
pluginName.set("Extra Icons Free")
}

"lifetime" -> {
pluginName.set("Extra Icons Lifetime")
}

else -> {
pluginName.set("Extra Icons")
}
}
downloadSources.set(pluginDownloadIdeaSources.toBoolean() && !System.getenv().containsKey("CI"))
instrumentCode.set(true)
pluginName.set("Extra Icons")
sandboxDir.set("${rootProject.projectDir}/.idea-sandbox/${shortenIdeVersion(pluginIdeaVersion)}")
updateSinceUntilBuild.set(false)
version.set(pluginIdeaVersion)
Expand Down Expand Up @@ -132,6 +149,75 @@ tasks {
}
}

register("updatePluginCompatibilityRulesFromPluginXml") {
doLast {
var pluginXmlStr = pluginXmlFile.readText()
when (pluginLicenseType) {
"free" -> {
pluginXmlStr = pluginXmlStr.replace("<incompatible-with>REPLACED_BY_GRADLE</incompatible-with>",
"<!-- none -->")
}

"lifetime" -> {
pluginXmlStr = pluginXmlStr.replace("<incompatible-with>REPLACED_BY_GRADLE</incompatible-with>",
"<incompatible-with>lermitage.extra.icons.free</incompatible-with>")
}

else -> {
pluginXmlStr = pluginXmlStr.replace("<incompatible-with>REPLACED_BY_GRADLE</incompatible-with>",
"<incompatible-with>lermitage.extra.icons.lifetime</incompatible-with>" +
"<incompatible-with>lermitage.extra.icons.free</incompatible-with>")
}
}
FileUtils.delete(pluginXmlFile)
FileUtils.write(pluginXmlFile, pluginXmlStr, "UTF-8")
}
}

register("backupPluginLogo") {
doLast {
if (pluginLogoFileBackup.exists()) {
if (!pluginLogoFileBackup.delete()) {
throw GradleException("Failed to remove existing plugin logo file backup '${pluginLogoFileBackup}'")
}
}
FileUtils.copyFile(pluginLogoFile, pluginLogoFileBackup)
}
}
register("restorePluginLogoFromBackup") {
doLast {
if (!pluginLogoFileBackup.exists()) {
throw GradleException("Plugin logo file backup '${pluginLogoFileBackup}' is missing")
}
if (pluginLogoFile.exists()) {
if (!pluginLogoFile.delete()) {
throw GradleException("Failed to remove non-original plugin logo file backup '${pluginLogoFile}'")
}
}
FileUtils.moveFile(pluginLogoFileBackup, pluginLogoFile)
}
}
register("usePluginLogoFree") {
doLast {
if (pluginLogoFile.exists()) {
if (!pluginLogoFile.delete()) {
throw GradleException("Failed to remove existing plugin logo file backup '${pluginLogoFile}'")
}
}
FileUtils.copyFile(pluginLogoFreeFile, pluginLogoFile)
}
}
register("usePluginLogoLifetime") {
doLast {
if (pluginLogoFile.exists()) {
if (!pluginLogoFile.delete()) {
throw GradleException("Failed to remove existing plugin logo file backup '${pluginLogoFile}'")
}
}
FileUtils.copyFile(pluginLogoLifetimeFile, pluginLogoFile)
}
}

register("backupPluginXml") {
doLast {
if (pluginXmlFileBackup.exists()) {
Expand Down Expand Up @@ -239,7 +325,6 @@ tasks {
}
withType<Test> {
useJUnitPlatform()
maxParallelForks = Runtime.getRuntime().availableProcessors()

// avoid JBUIScale "Must be precomputed" error, because IDE is not started (LoadingState.APP_STARTED.isOccurred is false)
jvmArgs("-Djava.awt.headless=true")
Expand Down Expand Up @@ -307,15 +392,15 @@ tasks {
patchPluginXml {
when (pluginLicenseType) {
"free" -> {
dependsOn("backupPluginXml", "removeLicenseRestrictionFromPluginXml")
dependsOn("backupPluginLogo", "usePluginLogoFree", "backupPluginXml", "removeLicenseRestrictionFromPluginXml", "updatePluginCompatibilityRulesFromPluginXml")
}

"lifetime" -> {
dependsOn("backupPluginXml", "renamePluginInfoToLifetimeInPluginXml", "verifyProductDescriptor")
dependsOn("backupPluginLogo", "usePluginLogoLifetime", "backupPluginXml", "renamePluginInfoToLifetimeInPluginXml", "updatePluginCompatibilityRulesFromPluginXml", "verifyProductDescriptor")
}

else -> {
dependsOn("verifyProductDescriptor")
dependsOn("backupPluginXml", "updatePluginCompatibilityRulesFromPluginXml", "verifyProductDescriptor")
}
}
changeNotes.set(provider {
Expand All @@ -327,11 +412,15 @@ tasks {
buildPlugin {
when (pluginLicenseType) {
"free" -> {
finalizedBy("restorePluginXmlFromBackup", "renameDistributionNoLicense")
finalizedBy("restorePluginLogoFromBackup", "restorePluginXmlFromBackup", "renameDistributionNoLicense")
}

"lifetime" -> {
finalizedBy("restorePluginXmlFromBackup", "renameDistributionLifetimeLicense")
finalizedBy("restorePluginLogoFromBackup", "restorePluginXmlFromBackup", "renameDistributionLifetimeLicense")
}

else -> {
finalizedBy("restorePluginXmlFromBackup")
}
}
}
Expand Down
1 change: 1 addition & 0 deletions misc/pluginIcon.free.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 63fbc4a

Please sign in to comment.