Skip to content

Commit 6ca08df

Browse files
chore: add JetBrains auto-approval compliance linter (#139)
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com> Co-authored-by: matifali <10648092+matifali@users.noreply.github.com>
1 parent abdf6d8 commit 6ca08df

File tree

5 files changed

+379
-1
lines changed

5 files changed

+379
-1
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: JetBrains Auto-Approval Compliance
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main, develop ]
8+
9+
jobs:
10+
compliance-check:
11+
runs-on: ubuntu-latest
12+
name: JetBrains Compliance Linting
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
18+
- name: Set up JDK 21
19+
uses: actions/setup-java@v4
20+
with:
21+
java-version: '21'
22+
distribution: 'temurin'
23+
24+
- name: Cache Gradle packages
25+
uses: actions/cache@v4
26+
with:
27+
path: |
28+
~/.gradle/caches
29+
~/.gradle/wrapper
30+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
31+
restore-keys: |
32+
${{ runner.os }}-gradle-
33+
34+
- name: Make gradlew executable
35+
run: chmod +x ./gradlew
36+
37+
- name: Run JetBrains Compliance Checks
38+
run: |
39+
echo "Running JetBrains auto-approval compliance checks with detekt..."
40+
./gradlew detekt
41+
42+
- name: Upload detekt reports
43+
uses: actions/upload-artifact@v4
44+
if: always()
45+
with:
46+
name: detekt-reports
47+
path: |
48+
build/reports/detekt/
49+
retention-days: 30
50+
51+
- name: Comment PR with compliance status
52+
if: github.event_name == 'pull_request' && failure()
53+
uses: actions/github-script@v7
54+
with:
55+
script: |
56+
github.rest.issues.createComment({
57+
issue_number: context.issue.number,
58+
owner: context.repo.owner,
59+
repo: context.repo.repo,
60+
body: '⚠️ **JetBrains Auto-Approval Compliance Check Failed**\n\n' +
61+
'This PR contains code that violates JetBrains auto-approval requirements:\n\n' +
62+
'- ❌ Do **not** use forbidden Kotlin experimental APIs\n' +
63+
'- ❌ Do **not** add lambdas, handlers, or class handles to Java runtime hooks\n' +
64+
'- ❌ Do **not** create threads manually (use coroutines or ensure cleanup in `CoderRemoteProvider#close()`)\n' +
65+
'- ❌ Do **not** bundle libraries already provided by Toolbox\n' +
66+
'- ❌ Do **not** perform ill-intentioned actions\n\n' +
67+
'Please check the workflow logs for detailed violations and fix them before merging.'
68+
})

JETBRAINS_COMPLIANCE.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# JetBrains Auto-Approval Compliance
2+
3+
This document describes the linting setup to ensure compliance with JetBrains auto-approval requirements for Toolbox plugins.
4+
5+
## Overview
6+
7+
JetBrains has enabled auto-approval for this plugin, which requires following specific guidelines to maintain the approval status. This repository includes automated checks to ensure compliance.
8+
9+
## Requirements
10+
11+
Based on communication with JetBrains team, the following requirements must be met:
12+
13+
### ✅ Allowed
14+
- **Coroutines**: Use `coroutineScope.launch` for concurrent operations
15+
- **Library-managed threads**: Libraries like OkHttp with their own thread pools are acceptable
16+
- **Some experimental coroutines APIs**: `kotlinx.coroutines.selects.select` and `kotlinx.coroutines.selects.onTimeout` are acceptable
17+
- **Proper cleanup**: Ensure resources are released in `CoderRemoteProvider#close()` method
18+
19+
### ❌ Forbidden
20+
- **Kotlin experimental APIs**: Core Kotlin experimental APIs (not coroutines-specific ones)
21+
- **Java runtime hooks**: No lambdas, handlers, or class handles to Java runtime hooks
22+
- **Manual thread creation**: Avoid `Thread()`, `Executors.new*()`, `ThreadPoolExecutor`, etc.
23+
- **Bundled libraries**: Don't bundle libraries already provided by Toolbox
24+
- **Ill-intentioned actions**: No malicious or harmful code
25+
26+
## Linting Setup
27+
28+
### JetBrains Compliance with Detekt
29+
30+
The primary compliance checking is done using Detekt with custom configuration in `detekt.yml`:
31+
32+
```bash
33+
./gradlew detekt
34+
```
35+
36+
This configuration includes JetBrains-specific rules that check for:
37+
- **ForbiddenAnnotation**: Detects forbidden experimental API usage
38+
- **ForbiddenMethodCall**: Detects Java runtime hooks and manual thread creation
39+
- **ForbiddenImport**: Detects potentially bundled libraries
40+
- **Standard code quality rules**: Complexity, naming, performance, etc.
41+
42+
43+
44+
## CI/CD Integration
45+
46+
The GitHub Actions workflow `.github/workflows/jetbrains-compliance.yml` runs compliance checks on every PR and push.
47+
48+
## Running Locally
49+
50+
```bash
51+
# Run JetBrains compliance and code quality check
52+
./gradlew detekt
53+
54+
# View HTML report
55+
open build/reports/detekt/detekt.html
56+
```
57+
58+
59+
60+
## Understanding Results
61+
62+
### Compliance Check Results
63+
64+
- **✅ No critical violations**: Code complies with JetBrains requirements
65+
- **❌ Critical violations**: Must be fixed before auto-approval
66+
- **⚠️ Warnings**: Should be reviewed but may be acceptable
67+
68+
### Common Warnings
69+
70+
1. **Manual thread creation**: If you see warnings about thread creation:
71+
- Prefer coroutines: `coroutineScope.launch { ... }`
72+
- If using libraries with threads, ensure cleanup in `close()`
73+
74+
2. **Library imports**: If you see warnings about library imports:
75+
- Verify the library isn't bundled in the final plugin
76+
- Check that Toolbox doesn't already provide the library
77+
78+
3. **GlobalScope usage**: If you see warnings about `GlobalScope`:
79+
- Use the coroutine scope provided by Toolbox instead
80+
81+
## Resources
82+
83+
- [JetBrains Toolbox Plugin Development](https://plugins.jetbrains.com/docs/toolbox/)
84+
- [Detekt Documentation](https://detekt.dev/)
85+
- [Kotlin Coroutines Guide](https://kotlinlang.org/docs/coroutines-guide.html)

build.gradle.kts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ plugins {
2222
alias(libs.plugins.gradle.wrapper)
2323
alias(libs.plugins.changelog)
2424
alias(libs.plugins.gettext)
25+
alias(libs.plugins.detekt)
2526
}
2627

2728

@@ -110,6 +111,24 @@ tasks.test {
110111
useJUnitPlatform()
111112
}
112113

114+
// Detekt configuration for JetBrains compliance and code quality
115+
detekt {
116+
config.setFrom("$projectDir/detekt.yml")
117+
buildUponDefaultConfig = true
118+
allRules = false
119+
}
120+
121+
// Configure detekt for JetBrains compliance and code quality
122+
tasks.withType<io.gitlab.arturbosch.detekt.Detekt>().configureEach {
123+
jvmTarget = "21"
124+
reports {
125+
html.required.set(true)
126+
xml.required.set(true)
127+
}
128+
// Fail build on detekt issues for JetBrains compliance
129+
ignoreFailures = false
130+
}
131+
113132

114133
tasks.jar {
115134
archiveBaseName.set(extension.id)

detekt.yml

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# Detekt configuration for JetBrains Toolbox Plugin Auto-Approval Compliance
2+
# Based on clarified requirements from JetBrains team
3+
4+
build:
5+
maxIssues: 1000 # Allow many issues for code quality reporting
6+
excludeCorrectable: false
7+
8+
config:
9+
validation: true
10+
warningsAsErrors: false # Don't treat warnings as errors
11+
checkExhaustiveness: false
12+
13+
# CRITICAL: JetBrains Compliance Rules using detekt built-in rules
14+
style:
15+
active: true
16+
17+
# JetBrains Auto-Approval Compliance: Forbidden experimental annotations
18+
ForbiddenAnnotation:
19+
active: true
20+
annotations:
21+
- reason: 'Forbidden for JetBrains auto-approval: Core Kotlin experimental APIs are not allowed'
22+
value: 'kotlin.ExperimentalStdlibApi'
23+
- reason: 'Forbidden for JetBrains auto-approval: Core Kotlin experimental APIs are not allowed'
24+
value: 'kotlin.ExperimentalUnsignedTypes'
25+
- reason: 'Forbidden for JetBrains auto-approval: Core Kotlin experimental APIs are not allowed'
26+
value: 'kotlin.contracts.ExperimentalContracts'
27+
- reason: 'Forbidden for JetBrains auto-approval: Core Kotlin experimental APIs are not allowed'
28+
value: 'kotlin.experimental.ExperimentalTypeInference'
29+
- reason: 'Forbidden for JetBrains auto-approval: Internal coroutines APIs should be avoided'
30+
value: 'kotlinx.coroutines.InternalCoroutinesApi'
31+
- reason: 'Forbidden for JetBrains auto-approval: Experimental time APIs are not allowed'
32+
value: 'kotlin.time.ExperimentalTime'
33+
# Note: ExperimentalCoroutinesApi, DelicateCoroutinesApi, FlowPreview are acceptable
34+
# based on JetBrains feedback about select/onTimeout being OK
35+
36+
# JetBrains Auto-Approval Compliance: Forbidden method calls
37+
ForbiddenMethodCall:
38+
active: true
39+
methods:
40+
# Java runtime hooks - forbidden
41+
- reason: 'Forbidden for JetBrains auto-approval: Java runtime hooks are not allowed'
42+
value: 'java.lang.Runtime.addShutdownHook'
43+
- reason: 'Forbidden for JetBrains auto-approval: Java runtime hooks are not allowed'
44+
value: 'java.lang.System.setSecurityManager'
45+
- reason: 'Forbidden for JetBrains auto-approval: Java runtime hooks are not allowed'
46+
value: 'java.lang.Thread.setUncaughtExceptionHandler'
47+
- reason: 'Forbidden for JetBrains auto-approval: Java runtime hooks are not allowed'
48+
value: 'java.lang.Thread.setDefaultUncaughtExceptionHandler'
49+
# Manual thread creation - warnings (allowed with proper cleanup)
50+
- reason: 'Warning for JetBrains auto-approval: Manual thread creation detected. Consider using coroutineScope.launch or ensure proper cleanup in CoderRemoteProvider#close()'
51+
value: 'java.lang.Thread.<init>'
52+
- reason: 'Warning for JetBrains auto-approval: Manual thread creation detected. Consider using coroutineScope.launch or ensure proper cleanup in CoderRemoteProvider#close()'
53+
value: 'java.util.concurrent.Executors.newFixedThreadPool'
54+
- reason: 'Warning for JetBrains auto-approval: Manual thread creation detected. Consider using coroutineScope.launch or ensure proper cleanup in CoderRemoteProvider#close()'
55+
value: 'java.util.concurrent.Executors.newCachedThreadPool'
56+
- reason: 'Warning for JetBrains auto-approval: Manual thread creation detected. Consider using coroutineScope.launch or ensure proper cleanup in CoderRemoteProvider#close()'
57+
value: 'java.util.concurrent.Executors.newSingleThreadExecutor'
58+
- reason: 'Warning for JetBrains auto-approval: Manual thread creation detected. Consider using coroutineScope.launch or ensure proper cleanup in CoderRemoteProvider#close()'
59+
value: 'java.util.concurrent.CompletableFuture.runAsync'
60+
- reason: 'Warning for JetBrains auto-approval: Manual thread creation detected. Consider using coroutineScope.launch or ensure proper cleanup in CoderRemoteProvider#close()'
61+
value: 'java.util.concurrent.CompletableFuture.supplyAsync'
62+
63+
# JetBrains Auto-Approval Compliance: Forbidden imports
64+
ForbiddenImport:
65+
active: true
66+
imports:
67+
# Potentially bundled libraries - warnings
68+
- reason: 'Warning for JetBrains auto-approval: Ensure slf4j is not bundled - it is provided by Toolbox'
69+
value: 'org.slf4j.*'
70+
- reason: 'Warning for JetBrains auto-approval: Ensure annotations library is not bundled - it is provided by Toolbox'
71+
value: 'org.jetbrains.annotations.*'
72+
# Runtime hook classes - forbidden
73+
- reason: 'Forbidden for JetBrains auto-approval: Runtime hook classes are not allowed'
74+
value: 'java.lang.Runtime'
75+
- reason: 'Forbidden for JetBrains auto-approval: Security manager modifications are not allowed'
76+
value: 'java.security.SecurityManager'
77+
78+
# Other important style rules
79+
MagicNumber:
80+
active: true
81+
ignoreNumbers:
82+
- '-1'
83+
- '0'
84+
- '1'
85+
- '2'
86+
ignoreHashCodeFunction: true
87+
ignorePropertyDeclaration: false
88+
ignoreLocalVariableDeclaration: false
89+
ignoreConstantDeclaration: true
90+
ignoreCompanionObjectPropertyDeclaration: true
91+
ignoreAnnotation: false
92+
ignoreNamedArgument: true
93+
ignoreEnums: false
94+
ignoreRanges: false
95+
ignoreExtensionFunctions: true
96+
97+
MaxLineLength:
98+
active: true
99+
maxLineLength: 120
100+
excludePackageStatements: true
101+
excludeImportStatements: true
102+
excludeCommentStatements: false
103+
104+
NewLineAtEndOfFile:
105+
active: true
106+
107+
WildcardImport:
108+
active: true
109+
110+
# Essential built-in rules for basic code quality
111+
complexity:
112+
active: true
113+
CyclomaticComplexMethod:
114+
active: true
115+
threshold: 15
116+
LongMethod:
117+
active: true
118+
threshold: 60
119+
LongParameterList:
120+
active: true
121+
functionThreshold: 6
122+
constructorThreshold: 7
123+
NestedBlockDepth:
124+
active: true
125+
threshold: 4
126+
127+
coroutines:
128+
active: true
129+
GlobalCoroutineUsage:
130+
active: true
131+
RedundantSuspendModifier:
132+
active: true
133+
SleepInsteadOfDelay:
134+
active: true
135+
136+
exceptions:
137+
active: true
138+
ExceptionRaisedInUnexpectedLocation:
139+
active: true
140+
ObjectExtendsThrowable:
141+
active: true
142+
PrintStackTrace:
143+
active: true
144+
ReturnFromFinally:
145+
active: true
146+
SwallowedException:
147+
active: true
148+
ThrowingExceptionFromFinally:
149+
active: true
150+
ThrowingExceptionsWithoutMessageOrCause:
151+
active: true
152+
TooGenericExceptionCaught:
153+
active: true
154+
TooGenericExceptionThrown:
155+
active: true
156+
157+
naming:
158+
active: true
159+
ClassNaming:
160+
active: true
161+
classPattern: '[A-Z][a-zA-Z0-9]*'
162+
FunctionNaming:
163+
active: true
164+
functionPattern: '[a-z][a-zA-Z0-9]*'
165+
PackageNaming:
166+
active: true
167+
packagePattern: '[a-z]+(\.?[a-z][A-Za-z0-9]*)*'
168+
VariableNaming:
169+
active: true
170+
variablePattern: '[a-z][A-Za-z0-9]*'
171+
172+
performance:
173+
active: true
174+
ArrayPrimitive:
175+
active: true
176+
ForEachOnRange:
177+
active: true
178+
SpreadOperator:
179+
active: true
180+
UnnecessaryTemporaryInstantiation:
181+
active: true
182+
183+
potential-bugs:
184+
active: true
185+
EqualsAlwaysReturnsTrueOrFalse:
186+
active: true
187+
EqualsWithHashCodeExist:
188+
active: true
189+
ExplicitGarbageCollectionCall:
190+
active: true
191+
HasPlatformType:
192+
active: true
193+
InvalidRange:
194+
active: true
195+
UnreachableCatchBlock:
196+
active: true
197+
UnreachableCode:
198+
active: true
199+
UnsafeCallOnNullableType:
200+
active: true
201+
UnsafeCast:
202+
active: true
203+
WrongEqualsTypeParameter:
204+
active: true

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy