diff --git a/.buildkite/pipeline.qodana.yml b/.buildkite/pipeline.qodana.yml new file mode 100644 index 0000000..4041fbd --- /dev/null +++ b/.buildkite/pipeline.qodana.yml @@ -0,0 +1,33 @@ +# Qodana code quality pipeline — replaces .github/workflows/qodana_code_quality.yml +# Triggered on pushes to main/releases/* and on pull requests. +# Skips documentation-only changes (CHANGELOG.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md, README.md, img/**). + +steps: + - label: ":qodana: Qodana Scan" + key: qodana + agents: + queue: default + env: + QODANA_TOKEN: $${QODANA_TOKEN?} + QODANA_ENDPOINT: "https://qodana.cloud" + commands: + - | + # Skip if all changed files are documentation-only + CHANGED="$$(git diff --name-only HEAD~1 HEAD 2>/dev/null || git diff --name-only origin/main...HEAD)" + NON_DOC="$$(echo "$$CHANGED" | grep -vE '^(CHANGELOG|CONTRIBUTING|CODE_OF_CONDUCT|README)\.md$$' | grep -v '^img/')" + if [ -z "$$NON_DOC" ]; then + echo "Only documentation changes detected — skipping Qodana scan." + exit 0 + fi + - | + # Run Qodana via Docker (mirrors the JetBrains/qodana-action behavior) + docker run --rm \ + -v "$$(pwd):/data/project" \ + -e QODANA_TOKEN="$$QODANA_TOKEN" \ + -e QODANA_ENDPOINT="$$QODANA_ENDPOINT" \ + jetbrains/qodana-jvm:2025.3 \ + --save-report \ + --results-dir /data/project/build/qodana/results \ + --report-dir /data/project/build/qodana/report + artifact_paths: + - "build/qodana/report/**/*" diff --git a/.buildkite/pipeline.release.yml b/.buildkite/pipeline.release.yml new file mode 100644 index 0000000..dbf1227 --- /dev/null +++ b/.buildkite/pipeline.release.yml @@ -0,0 +1,59 @@ +# Release pipeline — replaces .github/workflows/release.yml + +steps: + - label: ":rocket: Publish Plugin" + key: publish + env: + PUBLISH_TOKEN: $${PUBLISH_TOKEN?} + CERTIFICATE_CHAIN: $${CERTIFICATE_CHAIN?} + PRIVATE_KEY: $${PRIVATE_KEY?} + PRIVATE_KEY_PASSWORD: $${PRIVATE_KEY_PASSWORD?} + GITHUB_TOKEN: $${GITHUB_TOKEN?} + plugins: + - docker#v5.12.0: + image: "gradle:8-jdk21" + environment: + - PUBLISH_TOKEN + - CERTIFICATE_CHAIN + - PRIVATE_KEY + - PRIVATE_KEY_PASSWORD + commands: + - | + TAG="$$BUILDKITE_TAG" + + if [ -z "$$RELEASE_BODY" ]; then + RELEASE_BODY="$$(gh release view "$$TAG" --json body -q '.body')" + fi + + CHANGELOG="$$(echo "$$RELEASE_BODY" | sed -e 's/^[[:space:]]*$$//g' -e '/./,$$!d')" + + if [ -n "$$CHANGELOG" ]; then + gradle patchChangelog --release-note="$$CHANGELOG" + fi + + gradle publishPlugin + + gh release upload "$$TAG" ./build/distributions/* + + if [ -n "$$CHANGELOG" ]; then + BRANCH="changelog-update-$$TAG" + + git config user.email "buildkite@ci" + git config user.name "Buildkite" + git checkout -b "$$BRANCH" + git commit -am "Changelog update - $$TAG" + git push --set-upstream origin "$$BRANCH" + + gh label create "release changelog" \ + --description "Pull requests with release changelog update" \ + --force || true + + gh pr create \ + --title "Changelog update - \`$$TAG\`" \ + --body "Current pull request contains patched \`CHANGELOG.md\` file for the \`$$TAG\` version." \ + --label "release changelog" \ + --head "$$BRANCH" + fi + + artifact_paths: + - "build/distributions/*.zip" diff --git a/.buildkite/pipeline.ui-tests.yml b/.buildkite/pipeline.ui-tests.yml new file mode 100644 index 0000000..834b228 --- /dev/null +++ b/.buildkite/pipeline.ui-tests.yml @@ -0,0 +1,74 @@ +# UI test pipeline — replaces .github/workflows/run-ui-tests.yml +# Triggered manually via `buildkite-agent pipeline upload .buildkite/pipeline.ui-tests.yml` +# or by triggering the pipeline from the Buildkite UI. + +steps: + # ─── Linux ──────────────────────────────────────────────────────────────── + - label: ":linux: UI Tests (Linux)" + key: ui-test-linux + agents: + os: linux + queue: default + env: + JAVA_HOME: /usr/lib/jvm/zulu-21-amd64 + DISPLAY: ":99.0" + commands: + - Xvfb -ac :99 -screen 0 1920x1080x16 & + - ./gradlew runIdeForUiTests & + - | + # Wait for IDE to be ready (equivalent to url-health-check-action) + for i in $$(seq 1 15); do + if curl -sf http://127.0.0.1:8082 > /dev/null 2>&1; then + echo "IDE is ready" + break + fi + echo "Attempt $$i/15 — waiting 30s..." + sleep 30 + done + - ./gradlew test + artifact_paths: + - "build/reports/tests/**/*" + + # ─── macOS ──────────────────────────────────────────────────────────────── + - label: ":mac: UI Tests (macOS)" + key: ui-test-macos + agents: + os: macos + queue: default + env: + JAVA_HOME: /Library/Java/JavaVirtualMachines/zulu-21.jdk/Contents/Home + commands: + - ./gradlew runIdeForUiTests & + - | + for i in $$(seq 1 15); do + if curl -sf http://127.0.0.1:8082 > /dev/null 2>&1; then + echo "IDE is ready" + break + fi + echo "Attempt $$i/15 — waiting 30s..." + sleep 30 + done + - ./gradlew test + artifact_paths: + - "build/reports/tests/**/*" + + # ─── Windows ────────────────────────────────────────────────────────────── + - label: ":windows: UI Tests (Windows)" + key: ui-test-windows + agents: + os: windows + queue: default + env: + JAVA_HOME: "C:\\Program Files\\Zulu\\zulu-21" + commands: + - start gradlew.bat runIdeForUiTests + - | + for /L %%i in (1,1,15) do ( + curl -sf http://127.0.0.1:8082 >nul 2>&1 && (echo IDE is ready & goto :ready) + echo Attempt %%i/15 - waiting 30s... + timeout /t 30 /nobreak >nul + ) + :ready + - gradlew.bat test + artifact_paths: + - "build/reports/tests/**/*" diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml new file mode 100644 index 0000000..611a3c7 --- /dev/null +++ b/.buildkite/pipeline.yml @@ -0,0 +1,56 @@ +# Main CI pipeline — replaces .github/workflows/build.yml + +steps: + - label: ":test_tube: Test" + key: test + command: "gradle check" + plugins: + - docker#v5.12.0: + image: "gradle:9-jdk21" + artifact_paths: + - "build/reports/tests/**/*" + - "build/reports/kover/report.xml" + + - label: ":hammer: Build" + key: build + # buildSearchableOptions launches a full IntelliJ IDE process and requires ~4GB RAM. + # Skip it in CI; it only generates marketplace search indexes. + command: "gradle buildPlugin -x buildSearchableOptions" + plugins: + - docker#v5.12.0: + image: "gradle:9-jdk21" + artifact_paths: + - "build/distributions/*.zip" + + - label: ":shield: Verify Plugin" + key: verify + command: "gradle verifyPlugin -x buildSearchableOptions --no-daemon --max-workers 1" + plugins: + - docker#v5.12.0: + image: "gradle:9-jdk21" + artifact_paths: + - "build/reports/pluginVerifier/**/*" + + - wait: ~ + + - label: ":github: Create Release Draft" + key: release-draft + branches: "main" + agents: + queue: default + env: + GITHUB_TOKEN: $${GITHUB_TOKEN?} + commands: + - | + PROPERTIES="$$(gradle properties --console=plain -q)" + VERSION="$$(echo "$$PROPERTIES" | grep "^version:" | cut -f2- -d ' ')" + CHANGELOG="$$(gradle getChangelog --unreleased --no-header --console=plain -q)" + + gh api repos/{owner}/{repo}/releases \ + --jq '.[] | select(.draft == true) | .id' \ + | xargs -I '{}' gh api -X DELETE repos/{owner}/{repo}/releases/{} + + gh release create "v$$VERSION" \ + --draft \ + --title "v$$VERSION" \ + --notes "$$CHANGELOG" diff --git a/build.gradle.kts b/build.gradle.kts index f6cd998..29f5db4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -129,10 +129,6 @@ changelog { } tasks { - wrapper { - gradleVersion = providers.gradleProperty("gradleVersion").get() - } - publishPlugin { dependsOn(patchChangelog) } diff --git a/gradle.properties b/gradle.properties index 30f859a..ffee72f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,6 +11,7 @@ pluginSinceBuild = 261 # IntelliJ Platform Properties -> https://plugins.jetbrains.com/docs/intellij/tools-gradle-intellij-plugin.html#configuration-intellij-extension # Android Studio Quail 1 | 2026.1.1 Canary 1 (Released Apr 16, 2026) +platformType = AI platformVersion = 2026.1.1.1 # Plugin Dependencies -> https://plugins.jetbrains.com/docs/intellij/plugin-dependencies.html @@ -19,9 +20,6 @@ platformPlugins = # Example: platformBundledPlugins = com.intellij.java platformBundledPlugins = org.jetbrains.plugins.gradle,com.intellij.java,org.jetbrains.android -# Gradle Releases -> https://github.com/gradle/gradle/releases -gradleVersion = 8.14.3 - # Opt-out flag for bundling Kotlin standard library -> https://jb.gg/intellij-platform-kotlin-stdlib kotlin.stdlib.default.dependency = false