- Notifications
You must be signed in to change notification settings - Fork1
chore: add JetBrains auto-approval compliance linter#139
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
name: JetBrains Auto-Approval Compliance | ||
on: | ||
push: | ||
branches: [ main, develop ] | ||
pull_request: | ||
branches: [ main, develop ] | ||
jobs: | ||
compliance-check: | ||
runs-on: ubuntu-latest | ||
name: JetBrains Compliance Linting | ||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 | ||
- name: Set up JDK 21 | ||
uses: actions/setup-java@v4 | ||
with: | ||
java-version: '21' | ||
distribution: 'temurin' | ||
- name: Cache Gradle packages | ||
uses: actions/cache@v4 | ||
with: | ||
path: | | ||
~/.gradle/caches | ||
~/.gradle/wrapper | ||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} | ||
restore-keys: | | ||
${{ runner.os }}-gradle- | ||
- name: Make scripts executable | ||
run: chmod +x ./scripts/jetbrains-compliance-check.sh | ||
- name: Run JetBrains Compliance Checks | ||
run: | | ||
echo "Running JetBrains auto-approval compliance checks..." | ||
./scripts/jetbrains-compliance-check.sh | ||
- name: Comment PR with compliance status | ||
if: github.event_name == 'pull_request' && failure() | ||
uses: actions/github-script@v7 | ||
with: | ||
script: | | ||
github.rest.issues.createComment({ | ||
issue_number: context.issue.number, | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
body: '⚠️ **JetBrains Auto-Approval Compliance Check Failed**\n\n' + | ||
'This PR contains code that violates JetBrains auto-approval requirements:\n\n' + | ||
'- ❌ Do **not** use forbidden Kotlin experimental APIs\n' + | ||
'- ❌ Do **not** add lambdas, handlers, or class handles to Java runtime hooks\n' + | ||
'- ❌ Do **not** create threads manually (use coroutines or ensure cleanup in `CoderRemoteProvider#close()`)\n' + | ||
'- ❌ Do **not** bundle libraries already provided by Toolbox\n' + | ||
'- ❌ Do **not** perform ill-intentioned actions\n\n' + | ||
'Please check the workflow logs for detailed violations and fix them before merging.' | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
# JetBrains Auto-Approval Compliance | ||
This document describes the linting setup to ensure compliance with JetBrains auto-approval requirements for Toolbox plugins. | ||
## Overview | ||
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. | ||
## Requirements | ||
Based on communication with JetBrains team, the following requirements must be met: | ||
### ✅ Allowed | ||
- **Coroutines**: Use `coroutineScope.launch` for concurrent operations | ||
- **Library-managed threads**: Libraries like OkHttp with their own thread pools are acceptable | ||
- **Some experimental coroutines APIs**: `kotlinx.coroutines.selects.select` and `kotlinx.coroutines.selects.onTimeout` are acceptable | ||
- **Proper cleanup**: Ensure resources are released in `CoderRemoteProvider#close()` method | ||
### ❌ Forbidden | ||
- **Kotlin experimental APIs**: Core Kotlin experimental APIs (not coroutines-specific ones) | ||
- **Java runtime hooks**: No lambdas, handlers, or class handles to Java runtime hooks | ||
- **Manual thread creation**: Avoid `Thread()`, `Executors.new*()`, `ThreadPoolExecutor`, etc. | ||
- **Bundled libraries**: Don't bundle libraries already provided by Toolbox | ||
- **Ill-intentioned actions**: No malicious or harmful code | ||
## Linting Setup | ||
### JetBrains Compliance Check Script | ||
The primary compliance checking is done via a shell script: | ||
```bash | ||
./scripts/jetbrains-compliance-check.sh | ||
``` | ||
This script checks for: | ||
- Forbidden experimental API usage | ||
- Manual thread creation patterns | ||
- Java runtime hooks | ||
- Potentially bundled libraries | ||
- Coroutines best practices | ||
### Standard Code Quality (Detekt) | ||
Standard Kotlin code quality is checked using Detekt: | ||
```bash | ||
./gradlew detekt | ||
``` | ||
## CI/CD Integration | ||
The GitHub Actions workflow `.github/workflows/jetbrains-compliance.yml` runs compliance checks on every PR and push. | ||
## Running Locally | ||
### Quick Compliance Check | ||
```bash | ||
# Run JetBrains compliance check | ||
./scripts/jetbrains-compliance-check.sh | ||
``` | ||
### Full Code Quality Check | ||
```bash | ||
# Run detekt for code quality | ||
./gradlew detekt | ||
# View HTML report | ||
open build/reports/detekt/detekt.html | ||
``` | ||
## Understanding Results | ||
### Compliance Check Results | ||
- **✅ No critical violations**: Code complies with JetBrains requirements | ||
- **❌ Critical violations**: Must be fixed before auto-approval | ||
- **⚠️ Warnings**: Should be reviewed but may be acceptable | ||
### Common Warnings | ||
1. **Manual thread creation**: If you see warnings about thread creation: | ||
- Prefer coroutines: `coroutineScope.launch { ... }` | ||
- If using libraries with threads, ensure cleanup in `close()` | ||
2. **Library imports**: If you see warnings about library imports: | ||
- Verify the library isn't bundled in the final plugin | ||
- Check that Toolbox doesn't already provide the library | ||
3. **GlobalScope usage**: If you see warnings about `GlobalScope`: | ||
- Use the coroutine scope provided by Toolbox instead | ||
## Resources | ||
- [JetBrains Toolbox Plugin Development](https://plugins.jetbrains.com/docs/toolbox/) | ||
- [Detekt Documentation](https://detekt.dev/) | ||
- [Kotlin Coroutines Guide](https://kotlinlang.org/docs/coroutines-guide.html) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -22,6 +22,7 @@ plugins { | ||
alias(libs.plugins.gradle.wrapper) | ||
alias(libs.plugins.changelog) | ||
alias(libs.plugins.gettext) | ||
alias(libs.plugins.detekt) | ||
} | ||
@@ -110,6 +111,23 @@ tasks.test { | ||
useJUnitPlatform() | ||
} | ||
// Detekt configuration for code quality | ||
detekt { | ||
buildUponDefaultConfig = true | ||
allRules = false | ||
} | ||
// Configure detekt for code quality reporting | ||
tasks.withType<io.gitlab.arturbosch.detekt.Detekt>().configureEach { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Minor: we can do a static import here. | ||
jvmTarget = "21" | ||
reports { | ||
html.required.set(true) | ||
xml.required.set(true) | ||
} | ||
// Don't fail build on detekt issues - just report them | ||
ignoreFailures = true | ||
} | ||
tasks.jar { | ||
archiveBaseName.set(extension.id) | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
#!/bin/bash | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. any reason for not configuring the rules in a detekt.yml? | ||
# JetBrains Auto-Approval Compliance Check Script | ||
# This script checks for violations of JetBrains auto-approval requirements | ||
set -e | ||
echo "🔍 JetBrains Auto-Approval Compliance Check" | ||
echo "===========================================" | ||
echo | ||
VIOLATIONS=0 | ||
SOURCE_DIR="src/main/kotlin" | ||
# Function to report violations | ||
report_violation() { | ||
echo "❌ VIOLATION: $1" | ||
echo " File: $2" | ||
echo " Line: $3" | ||
echo " Context: $4" | ||
echo | ||
VIOLATIONS=$((VIOLATIONS + 1)) | ||
} | ||
# Function to report warnings | ||
report_warning() { | ||
echo "⚠️ WARNING: $1" | ||
echo " File: $2" | ||
echo " Line: $3" | ||
echo " Context: $4" | ||
echo | ||
} | ||
echo "1. Checking for experimental API usage..." | ||
# Check for forbidden experimental annotations (excluding acceptable coroutines ones) | ||
grep -rn "@ExperimentalApi\|@ExperimentalStdlibApi\|@ExperimentalUnsignedTypes\|@ExperimentalContracts\|@ExperimentalTypeInference\|@InternalCoroutinesApi\|@ExperimentalTime" $SOURCE_DIR 2>/dev/null | while IFS=: read -r file line content; do | ||
report_violation "Forbidden experimental API usage" "$file" "$line" "$content" | ||
done | ||
# Check for @OptIn with forbidden experimental APIs | ||
grep -rn "@OptIn.*ExperimentalApi\|@OptIn.*ExperimentalStdlibApi\|@OptIn.*InternalCoroutinesApi" $SOURCE_DIR 2>/dev/null | while IFS=: read -r file line content; do | ||
report_violation "@OptIn with forbidden experimental API" "$file" "$line" "$content" | ||
done | ||
echo "2. Checking for manual thread creation..." | ||
# Check for direct thread creation | ||
grep -rn "Thread(\|ThreadPoolExecutor\|ScheduledThreadPoolExecutor\|ForkJoinPool\|Timer(\|TimerTask" $SOURCE_DIR 2>/dev/null | while IFS=: read -r file line content; do | ||
report_warning "Manual thread creation detected - ensure proper cleanup in CoderRemoteProvider#close()" "$file" "$line" "$content" | ||
done | ||
# Check for Executors usage | ||
grep -rn "Executors\.new\|CompletableFuture\.runAsync\|CompletableFuture\.supplyAsync" $SOURCE_DIR 2>/dev/null | while IFS=: read -r file line content; do | ||
report_warning "Executor/CompletableFuture usage detected - ensure proper cleanup in CoderRemoteProvider#close()" "$file" "$line" "$content" | ||
done | ||
# Check for classes extending Thread or implementing Runnable | ||
grep -rn "class.*extends Thread\|class.*implements Runnable\|: Thread\|: Runnable" $SOURCE_DIR 2>/dev/null | while IFS=: read -r file line content; do | ||
report_warning "Class extending Thread or implementing Runnable - consider using coroutines" "$file" "$line" "$content" | ||
done | ||
echo "3. Checking for Java runtime hooks..." | ||
# Check for runtime hooks | ||
grep -rn "Runtime\..*addShutdownHook\|System\.setSecurityManager\|setUncaughtExceptionHandler\|setDefaultUncaughtExceptionHandler" $SOURCE_DIR 2>/dev/null | while IFS=: read -r file line content; do | ||
report_violation "Java runtime hook usage forbidden" "$file" "$line" "$content" | ||
done | ||
# Check for suspicious system property modifications | ||
grep -rn "System\.setProperty.*java\.security\|System\.setProperty.*java\.awt\.headless\|System\.setProperty.*file\.encoding" $SOURCE_DIR 2>/dev/null | while IFS=: read -r file line content; do | ||
report_violation "Suspicious system property modification" "$file" "$line" "$content" | ||
done | ||
echo "4. Checking for bundled libraries..." | ||
# Check for imports that might indicate bundled libraries | ||
grep -rn "import org\.slf4j\|import org\.jetbrains\.annotations" $SOURCE_DIR 2>/dev/null | while IFS=: read -r file line content; do | ||
report_warning "Import of potentially bundled library - ensure it's not bundled" "$file" "$line" "$content" | ||
done | ||
echo "5. Checking for coroutines best practices..." | ||
# Check for GlobalScope usage (should use provided scope) | ||
grep -rn "GlobalScope\.launch\|GlobalScope\.async" $SOURCE_DIR 2>/dev/null | while IFS=: read -r file line content; do | ||
report_warning "GlobalScope usage detected - consider using provided coroutine scope" "$file" "$line" "$content" | ||
done | ||
echo "===========================================" | ||
if [ $VIOLATIONS -eq 0 ]; then | ||
echo "✅ No critical violations found!" | ||
echo " Your code appears to comply with JetBrains auto-approval requirements." | ||
echo | ||
echo "📋 Summary of requirements:" | ||
echo " ✓ No forbidden Kotlin experimental APIs" | ||
echo " ✓ No Java runtime hooks" | ||
echo " ✓ No suspicious system modifications" | ||
echo " ⚠️ Manual thread creation warnings (if any) - ensure cleanup in close()" | ||
echo " ⚠️ Library bundling warnings (if any) - verify not bundling Toolbox libs" | ||
echo | ||
exit 0 | ||
else | ||
echo "❌ Found $VIOLATIONS critical violations!" | ||
echo " Please fix these issues before submitting for auto-approval." | ||
echo | ||
exit 1 | ||
fi |
Uh oh!
There was an error while loading.Please reload this page.