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
111 changes: 111 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
name: CI
on:
push:
branches: [main]
pull_request:

# A second push to a PR makes the first run's answer worthless — the verifier job downloads
# IDEs, so letting both finish is minutes of runner time spent on a stale commit.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 21
- uses: gradle/actions/setup-gradle@v4

# :core holds the parser and its tests; :plugin has none by design (its test task is
# disabled in build.gradle.kts), so `gradlew test` alone reports success either way.
# Naming :core:test means a removed test suite shows up as a task that no longer exists.
- id: coretest
run: ./gradlew :core:test

- name: Test report
if: always()
run: |
set -euo pipefail
shopt -s nullglob
files=(core/build/test-results/test/TEST-*.xml)
if [ ${#files[@]} -eq 0 ]; then
# No results after a *failed* test step says nothing new — the job is already red
# for the real reason. It is only a finding when the step claimed success.
if [ "${{ steps.coretest.outcome }}" != "success" ]; then
echo "::notice::no test results, but the test step failed above — see it for the cause"
exit 0
fi
echo "::error:::core:test succeeded and produced no results — did the suite disappear?"
exit 1
fi
awk -F'"' '/<testsuite /{for(i=1;i<=NF;i++){
if($(i-1)~/tests=$/)t+=$i; if($(i-1)~/failures=$/)f+=$i; if($(i-1)~/errors=$/)e+=$i}}
END{printf ":core — %d tests, %d failures, %d errors\n", t, f, e}' "${files[@]}" \
>> "$GITHUB_STEP_SUMMARY"

- run: ./gradlew build verifyPluginProjectConfiguration verifyPluginStructure

- name: Build the distributable
run: ./gradlew buildPlugin

- uses: actions/upload-artifact@v4
with:
name: plugin-zip
path: plugin/build/distributions/*.zip
if-no-files-found: error

verify:
name: Plugin Verifier
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 21
- uses: gradle/actions/setup-gradle@v4

# Each IDE under test is a ~1GB download. Caching them separately from the Gradle cache
# keeps a dependency change from evicting them.
- uses: actions/cache@v4
with:
path: |
~/.gradle/caches/modules-2/files-2.1/com.jetbrains.intellij.idea
~/.pluginVerifier
key: ide-verifier-${{ hashFiles('plugin/build.gradle.kts') }}
restore-keys: ide-verifier-

- run: ./gradlew verifyPlugin

# The task passes when an IDE reports problems below the failure level, and it passes
# just as quietly when the ides {} block resolves to nothing. Assert on the reports:
# one directory per verified IDE, and the count has to match what is declared.
- name: Every declared IDE was actually verified
run: |
set -euo pipefail
shopt -s nullglob
reports=plugin/build/reports/pluginVerifier
declared=$(grep -c '^ *ide("' plugin/build.gradle.kts)
dirs=("$reports"/*/)
echo "declared=$declared verified=${#dirs[@]}"
if [ "${#dirs[@]}" -ne "$declared" ]; then
echo "::error::$declared IDEs declared in pluginVerification, ${#dirs[@]} verified"
for d in "${dirs[@]}"; do echo " $(basename "$d")"; done
exit 1
fi
for d in "${dirs[@]}"; do
echo "- verified against $(basename "$d")" >> "$GITHUB_STEP_SUMMARY"
done

- uses: actions/upload-artifact@v4
if: always()
with:
name: plugin-verifier-reports
path: plugin/build/reports/pluginVerifier
if-no-files-found: warn
Empty file modified gradlew
100644 → 100755
Empty file.
16 changes: 16 additions & 0 deletions plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ dependencies {
// installed IDE (no ~1GB SDK download); the default downloads Community for CI/others.
val localIde = providers.gradleProperty("localIdePath").orNull
if (localIde != null) local(localIde) else intellijIdeaCommunity("2024.3.5")

pluginVerifier() // the CLI the verifyPlugin task shells out to
}
}

Expand All @@ -35,6 +37,20 @@ intellijPlatform {
untilBuild = "261.*"
}
}

// sinceBuild above is a claim; this is what makes it true. 2024.2.5 is the oldest release
// in the 242 line, so it is where an API the plugin uses might not exist yet — the failure
// the compile target cannot show. untilBuild stays unverified on purpose: 261 has no
// release to check against, so it remains a forward-looking promise.
//
// Use the string notation. The ide(IntelliJPlatformType, String) overload accepts these
// versions and then schedules nothing, leaving a green run that verified one IDE.
pluginVerification {
ides {
ide("IC-2024.2.5") // the floor sinceBuild = 242 claims
ide("IC-2024.3.5") // what the plugin compiles against
}
}
}

// No test sources live here (the parser is tested in :core). Disable the platform test
Expand Down
Loading