Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions .github/workflows/installers.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Builds the Windows installers (installer/build-installer.ps1): the self-contained
# install-intellij-ib-plugin.ps1 and the intellij-ib-plugin.exe self-extracting installer.
# Windows-only: the .exe needs csc.exe and 7-Zip, and the standalone script is run with Windows
# PowerShell, which is also what assembles it here (see installer/README.md).
#
# - Called by the Release workflow with the release's tag: packages the exact plugin zip that
# release published and attaches both installers to it.
# - Run by hand (Actions > Installers > Run workflow) to try it out before a release:
# - with no tag, it builds the plugin from the selected branch and only uploads the installers
# as a workflow artifact - no release is touched;
# - with an existing release's tag, it does exactly what the Release workflow does for that
# release, e.g. to re-attach installers after a failed run.
# (GitHub only offers "Run workflow" once this file is on the default branch.)
# - On pull requests that change the installers, the same as a manual run without a tag - so a
# change to them is exercised before it ever reaches a release.

name: Installers
on:
workflow_call:
inputs:
tag:
description: Release tag whose plugin zip to package, and to attach the installers to.
required: true
type: string
pull_request:
paths:
- installer/**
- .github/workflows/installers.yml
workflow_dispatch:
inputs:
tag:
description: Release tag to package and attach to. Leave empty to build from this branch and upload a workflow artifact only.
required: false
type: string

jobs:
installers:
name: Build Installers
runs-on: windows-latest
permissions:
contents: write
env:
TAG: ${{ inputs.tag }}
GITHUB_TOKEN: ${{ github.token }}
steps:

# Check out the release's tag, or the branch the workflow was run from
- name: Fetch Sources
uses: actions/checkout@v7
with:
ref: ${{ inputs.tag || github.ref }}

# Only needed to build the plugin from source (no tag)
- name: Setup Java
if: ${{ !inputs.tag }}
uses: actions/setup-java@v5
with:
distribution: zulu
java-version: 21

- name: Setup Gradle
if: ${{ !inputs.tag }}
uses: gradle/actions/setup-gradle@v6.2.0
with:
cache-read-only: true

# The zip the release's "Upload Release Asset" step attached, not a fresh build
- name: Download Published Plugin
if: ${{ inputs.tag }}
shell: powershell
run: gh release download "$env:TAG" --repo "${{ github.repository }}" --pattern intellij-ib-plugin.zip --dir build/published

- name: Build Installers
shell: powershell
run: |
if ($env:TAG) {
.\installer\build-installer.ps1 -PluginZip build\published\intellij-ib-plugin.zip
} else {
# Runs gradlew buildPlugin itself first
.\installer\build-installer.ps1
}

- name: Upload Installers to Release
if: ${{ inputs.tag }}
shell: powershell
run: gh release upload "$env:TAG" --repo "${{ github.repository }}" --clobber build/distributions/install-intellij-ib-plugin.ps1 build/distributions/intellij-ib-plugin.exe

# Always kept as an artifact too, so a manual run's output can be downloaded and tried
- name: Upload Installers Artifact
uses: actions/upload-artifact@v7
with:
name: installers
path: |
build/distributions/install-intellij-ib-plugin.ps1
build/distributions/intellij-ib-plugin.exe
12 changes: 12 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,15 @@ jobs:
--body "Current pull request contains patched \`CHANGELOG.md\` file for the \`$VERSION\` version." \
--label "$LABEL" \
--head $BRANCH

# Build the Windows installers from the exact plugin zip the job above just published, and attach
# them to the same release - so they're reproducible from CI rather than built locally and
# committed. Its own workflow so it can also be run by hand - see installers.yml.
installers:
name: Build Installers

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This job only runs when a release is published, so CI hasn't exercised it yet. Does the uploaded asset really match intellij-ib-plugin.zip (and not a versioned name)? Consider adding workflow_dispatch so it can be tried before 1.1.0. Also, does anything (README, wiki, download links) still point to the deleted scripts/install-intellij-ib-plugin.ps1?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Asset name: yes. build.gradle.kts pins buildPlugin's output to intellij-ib-plugin.zip, unversioned, and "Upload Release Asset" uploads build/distributions/*. A signed archive, if signing is configured, gets its own name, so the exact-name download still picks the plain zip.

Trying it early: I moved the job into a reusable installers.yml, which release.yml calls with the tag, so release behaviour is unchanged. It also has workflow_dispatch: without a tag it builds from the branch and uploads the installers as an artifact only; with a tag it re-runs the release step for that release. Since dispatch only appears once the file is on main, it also runs on PRs touching installer/** or the workflow, which exercises it on this PR.

Links: nothing in the repo, on any branch, points to the old scripts/ path. I couldn't check the wiki or external download pages from here; could you check those? I also added a README line pointing to the installers on the release page.

needs: [ release ]
permissions:
contents: write
uses: ./.github/workflows/installers.yml
with:
tag: ${{ github.event.release.tag_name }}
32 changes: 32 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,38 @@

## [Unreleased]

## [1.1.0]

### Added

- CLion support for CMake projects: **Build**, **Rebuild** and **Build All** in the **Incredibuild** menu run

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plugin.xml already described CLion support before this PR. Was this entry already released? If so, it shouldn't be under [Unreleased].

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With new version all of it was moved out of unreleased and under 1.1.0

`cmake --build` through Incredibuild, against the build directory, toolchain and generator the active CMake profile
is already configured with.
- Rider support for .NET solutions: **Build Solution with Incredibuild**, **Rebuild Solution with Incredibuild** and
**Build Selected Projects with Incredibuild** in the **Build** menu, the Solution Explorer context menu and the
**Incredibuild** menu, bindable to shortcuts in **Settings/Preferences > Keymap**. They build the solution as it is
configured, in its active configuration and platform, through MSBuild accelerated by Incredibuild. While one runs,
the status bar shows the accelerated build in progress, and a notification reports the result.
- **Settings/Preferences > Tools > Incredibuild** can set the MSBuild that Rider builds use, when the automatically
detected one isn't the right one.
- The installers now also install the plugin into CLion and Rider.

### Changed

- Only one Incredibuild build runs at a time, in every IDE. Starting a build - from the **Incredibuild** menu or,
with IDE build acceleration on, from the IDE's own build actions - while another is still running offers to stop
the running one, then starts the new build as soon as it has stopped. Previously a second build started alongside
the first, replacing its output in the **Incredibuild** tool window.
- The Windows installers (`install-intellij-ib-plugin.ps1` and `intellij-ib-plugin.exe`) are now attached to each
GitHub release, built by the release workflow from the published plugin, instead of the script being committed to
the repository.

### Fixed

- With **Accelerate the IDE's own build actions** on, **Build Project** in RustRover 2026.1 (and IntelliJ IDEA / CLion
2026.1 with the Rust plugin) failed with `NoSuchMethodError` instead of building, because it relied on a Rust plugin
API that only exists from 2026.2. The plugin is now verified against both 2026.1 and 2026.2 of every supported IDE.

## [1.0.3]

### Added
Expand Down
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,35 @@ The setting is off by default. While it is off - or if Incredibuild isn't instal
those actions behave exactly as they do without this plugin. The actions in the **Incredibuild** menu
always use Incredibuild, whichever way the setting is set.

### Rider (.NET)

In Rider, the **Build** menu gets dedicated Incredibuild actions right after the standard ones (they are
also in the **Incredibuild** menu):

- **Build Solution with Incredibuild** - builds the solution in its active configuration and platform
- **Rebuild Solution with Incredibuild** - cleans and rebuilds it
- **Build Selected Projects with Incredibuild** - builds the projects selected in the Solution Explorer,
along with the projects they reference

The same actions are in the Solution Explorer's context menu on the solution, solution folders and
projects, and each can be bound to a shortcut under **Settings/Preferences > Keymap** (search for
"Incredibuild"). They have no default shortcuts, so none of Rider's own are taken over.

They run MSBuild on the solution exactly as it is configured: the active configuration and platform
are respected (for selected projects, through the solution's own project configuration mapping), and
an open solution filter (`.slnf`) limits the build the same way it limits Rider's own. Nothing about the
solution or its projects is changed. While an accelerated build runs, the status bar shows
*Building <solution> with Incredibuild*, the **Incredibuild** tool window shows its output under a banner
naming the configuration and MSBuild used, and a notification reports the result.

MSBuild is detected automatically: the newest Visual Studio / Build Tools `MSBuild.exe` with the .NET SDK component on Windows,
otherwise the .NET SDK's `dotnet msbuild`. Rider's own MSBuild selection lives in its backend settings,
which plugins can't read, so a different one can be set under **Settings/Preferences > Tools > Incredibuild**.

### Settings

**Settings/Preferences > Tools > Incredibuild** configures the number of parallel jobs (`-j`)
accelerated builds request, and the opt-in above.
accelerated Cargo/CMake builds request, the opt-in above, and (in Rider) the MSBuild to use.

If Incredibuild isn't installed on the machine, the menu commands offer to open
[incredibuild.com](https://www.incredibuild.com/) to download it.
Expand All @@ -46,6 +71,8 @@ If Incredibuild isn't installed on the machine, the menu commands offer to open
- RustRover, or IntelliJ IDEA Ultimate with the Rust plugin - 2026.1 or 2026.2 (builds 261-262).
The Rust plugin is released for one IDE line at a time, and this plugin depends on it, so support
for a newer line follows a Rust plugin release for it.
- Or CLion 2026.1 or 2026.2, with a CMake project.
- Or Rider 2026.1 or 2026.2, with MSBuild (Visual Studio / Build Tools) or the .NET SDK installed.
- [Incredibuild](https://www.incredibuild.com/) installed, on Windows or Linux:
- Windows: 10.37.1 or later
- Linux: 4.29.3 or later, installed under `/opt/incredibuild`
Expand All @@ -69,6 +96,12 @@ If Incredibuild isn't installed on the machine, the menu commands offer to open
Download the [latest release](https://github.com/Incredibuild-RND/intellij-ib-plugin/releases/latest) and install it manually using
<kbd>Settings/Preferences</kbd> > <kbd>Plugins</kbd> > <kbd>⚙️</kbd> > <kbd>Install plugin from disk...</kbd>

- On Windows, with an installer:

The same [release page](https://github.com/Incredibuild-RND/intellij-ib-plugin/releases/latest) also has
`intellij-ib-plugin.exe` and `install-intellij-ib-plugin.ps1`, which install the plugin into every supported
JetBrains IDE found on the machine. Close those IDEs first.

## License

Licensed under the [Apache License, Version 2.0](./LICENSE). See [CONTRIBUTING.md](./CONTRIBUTING.md) for contribution terms.
106 changes: 96 additions & 10 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.gradle.api.tasks.bundling.Zip
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
import org.jetbrains.intellij.platform.gradle.TestFrameworkType
import org.jetbrains.intellij.platform.gradle.tasks.VerifyPluginTask

plugins {
id("org.jetbrains.kotlin.jvm")
Expand Down Expand Up @@ -52,6 +53,9 @@ dependencies {
// Verifier against a plain 2026.2 target (only 262.8665+ builds have it).
plugin("com.intellij.nativeDebug", "262.8665.176")
bundledPlugin("intellij.testRunner.plugin")
// The Rider-only .NET adapter (see rider/build.gradle.kts), merged into this plugin's
// own jar rather than shipped as a separate one - still a single plugin to install.
pluginComposedModule(implementation(project(":rider")))
testFramework(TestFrameworkType.Platform)
}
}
Expand All @@ -69,10 +73,11 @@ tasks.withType<AbstractArchiveTask>().configureEach {
isPreserveFileTimestamps = true
}

// Compiled against com.jetbrains.rust 262.8665.323 (2026.2 line), but the specific APIs this
// plugin uses (CargoCommandConfiguration.parametersHolder, RustProjectSettingsService.toolchain,
// RsToolchainBase.pathToCargoExecutable, etc.) are verified identical in the 261.x (2026.1) line
// too, so declare compatibility down to build 261 rather than the auto-derived 262.
// Compiled against com.jetbrains.rust 262.8665.323 (2026.2 line), but declares compatibility down
// to build 261 rather than the auto-derived 262: the APIs this plugin uses are the same in the
// 261.x (2026.1) line, except CargoBuildAdapter's attach API, which IncredibuildProjectTaskRunner
// resolves for whichever version is loaded. The Plugin Verifier checks both lines (see
// pluginVerification below), so a 262-only API used directly fails the build.
intellijPlatform {
pluginConfiguration {
ideaVersion {
Expand Down Expand Up @@ -107,21 +112,93 @@ intellijPlatform {
// resolve CMake-only classes - not a bug. Rather than dropping COMPATIBILITY_PROBLEMS
// from failureLevel entirely (which would also hide a real, future compatibility
// break, e.g. a 2026.x IDE removing an API this plugin uses), those 4 specific,
// already-reviewed problems are listed in ignoredProblemsFile instead - everything
// already-reviewed problems are listed in an ignored-problems file instead - everything
// else in that category still fails the task. failureLevel is left at its default
// (COMPATIBILITY_PROBLEMS + INTERNAL_API_USAGES; confirmed by observing which
// categories actually failed the task even though deprecated/experimental/missing-
// optional-dependency problems were also present and reported) - it already caught a
// real, fixable internal-API usage (PluginManagerCore.getPlugin(), replaced with the
// public isLoaded() instead) and should keep gating future ones the same way.
ignoredProblemsFile.set(rootProject.layout.projectDirectory.file("gradle/pluginVerifier-ignoredProblems.txt"))
//
// The ignored-problems file is set per IDE, not here - see the per-IDE verification
// tasks below.
//
// Both ends of the declared sinceBuild..untilBuild range (261-262), not just the 262 line
// everything is compiled against - otherwise 2026.1 would accept the plugin without ever
// having been verified, which matters most for the Rider half (rider/ is compiled against
// Rider 2026.2 only, and leans on Rider's own solution-model APIs).
ides {
create(IntelliJPlatformType.CLion, "2026.2")
create(IntelliJPlatformType.RustRover, "2026.2")
for (version in listOf("2026.1", "2026.2")) {
create(IntelliJPlatformType.CLion, version)
create(IntelliJPlatformType.RustRover, version)
// The only IDE that ever loads the .NET half (rider-support.xml).
// Rider is only published as a Maven artifact, not a regular installer - see
// https://github.com/JetBrains/intellij-platform-gradle-plugin/issues/1852.
create(IntelliJPlatformType.Rider, version) {
useInstaller = false
}
}
}
}
}

// One verification run per IDE, each with only the ignored problems that IDE is expected to
// report. A Plugin Verifier ignored-problems file applies to every IDE in a run - its conditions
// can name a plugin but not an IDE - so a single shared file would also hide those same messages
// where they *would* be real problems: "Package 'org.rust' is not found" is expected against
// Rider (no Rust plugin) but would mean a broken build against RustRover, and the CMake-only
// symbols are expected against RustRover but never against CLion. Splitting the runs keeps that
// coverage.
//
// All three take the IDEs pluginVerification.ides resolves above and keep only their own, by the
// productCode in each IDE's product-info.json. `verifyPlugin` itself verifies CLion and runs the
// other two, so CI's `./gradlew verifyPlugin` still covers all three. Reports go to one
// subdirectory each of build/reports/pluginVerifier, which CI uploads as a whole.
data class PerIdeVerification(val productCode: String, val reportsSubdirectory: String, val ignoredProblems: String?)

val perIdeVerifications = mapOf(
"verifyPlugin" to PerIdeVerification("CL", "clion", null),
"verifyPluginRustRover" to PerIdeVerification("RR", "rustrover", "gradle/pluginVerifier-ignoredProblems-rustrover.txt"),
"verifyPluginRider" to PerIdeVerification("RD", "rider", "gradle/pluginVerifier-ignoredProblems-rider.txt"),
)

for ((taskName, verification) in perIdeVerifications) {
val configure: VerifyPluginTask.() -> Unit = {
// A snapshot of the sources the plugin wired in, not `ides` itself - filtering a
// collection into its own sources would make it depend on itself.
val allIdes = files(ides.from.toList())
val productCode = verification.productCode
ides.setFrom(allIdes.filter { ide ->
val productInfo = ide.resolve("product-info.json")
productInfo.isFile &&
Regex(""""productCode"\s*:\s*"([A-Z]+)"""").find(productInfo.readText())?.groupValues?.get(1) == productCode
})
verification.ignoredProblems?.let { ignoredProblemsFile.set(layout.projectDirectory.file(it)) }
verificationReportsDirectory.set(layout.buildDirectory.dir("reports/pluginVerifier/${verification.reportsSubdirectory}"))
// A home directory of its own for each run. These tasks can run in parallel (the
// configuration cache allows it), and every Plugin Verifier run starts by deleting and
// recreating <home>/extracted-plugins - with the shared default home (~/.pluginVerifier),
// one run deleting it while another walks it fails that run with NoSuchFileException.
systemProperty(
"plugin.verifier.home.dir",
layout.buildDirectory.dir("pluginVerifier/${verification.reportsSubdirectory}").get().asFile.absolutePath
)
}
if (taskName == "verifyPlugin") {
tasks.named<VerifyPluginTask>(taskName, configure)
} else {
tasks.register<VerifyPluginTask>(taskName) {
group = "intellij platform"
description = "Verifies the plugin against ${verification.reportsSubdirectory} only - see build.gradle.kts."
configure()
}
}
}

tasks.named("verifyPlugin") {
dependsOn("verifyPluginRustRover", "verifyPluginRider")
}

// Plain `runIde` launches intellijIdeaUltimate (the platform this plugin's dependencies block
// above declares), which never loads the CMake half at all (see plugin.xml's optional
// <depends config-file="cmake-support.xml">) - there's nothing to manually exercise there. Add a
Expand All @@ -132,12 +209,21 @@ intellijPlatformTesting {
type = IntelliJPlatformType.CLion
version = "2026.2"
}
// Likewise for the .NET/Rider actions (rider-support.xml).
register("runIdeForRider") {
type = IntelliJPlatformType.Rider
version = "2026.2"
useInstaller = false
}
}
}

// buildSearchableOptions launches a sandboxed IDE to index Settings UI labels for search.
// That launcher doesn't support ARM64 hosts ("Unsupported JVM architecture: aarch64") - it's a
// build-time search-indexing convenience only, not required for the plugin to function.
tasks.named("buildSearchableOptions") {
enabled = false
// Switched off through the plugin's own flag rather than by disabling just that one task: the
// follow-up prepareJarSearchableOptions task still expects the output folder buildSearchableOptions
// would have created, so after a `clean` the task-only approach fails the build.
intellijPlatform {
buildSearchableOptions = false
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group = com.incredibuild.ibplugin
version = 1.0.3
version = 1.1.0

pluginRepositoryUrl = https://github.com/Incredibuild-RND/intellij-ib-plugin

Expand Down
Loading
Loading