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
9 changes: 6 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:

jobs:
generator-tests:
name: Verify JsonExtractor tests
name: Verify JSON policies and tests
runs-on: ubuntu-latest

steps:
Expand All @@ -28,5 +28,8 @@ jobs:
restore-keys: |
${{ runner.os }}-gradle-

- name: Run cleanJvmTest and JsonExtractorTest
run: ./gradlew :generator:cleanJvmTest :generator:jvmTest --tests "io.github.kdroidfilter.database.generator.JsonExtractorTest"
- name: Validate JSON policies
run: ./gradlew :generators:policies:validateJson

- name: Run JsonExtractor tests
run: ./gradlew :generators:policies:cleanJvmTest :generators:policies:jvmTest --tests "io.github.kdroidfilter.database.generator.JsonExtractorTest"
23 changes: 22 additions & 1 deletion README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ Use when each user mode has multiple variants, each with its own rules and optio

## ✅ Checklist Before Submitting

1. 🔎 **Validate JSON** with a linter (e.g., [jsonlint.com](https://jsonlint.com/)).
1. 🔎 **Validate JSON** with a linter (e.g., [jsonlint.com](https://jsonlint.com/)) or use the project's built-in validation task (see below).
2. 📂 **Place** your file under the correct category folder.
3. 📜 **Commit only** the JSON file—no code or docs changes.
4. 📝 **PR title** should clearly state the app package.
Expand All @@ -217,6 +217,27 @@ CI will reject invalid JSON or misplaced files. Good luck! 🙌

---

## 🛠️ Gradle Tasks

The project includes several Gradle tasks to help with development and validation:

### Validating JSON Files

To validate all JSON policy files for correctness:

```bash
./gradlew :generators:policies:validateJson
```

This task checks all JSON files in the `app-policies` directory to ensure they:
- Have valid JSON syntax
- Conform to the expected policy structure
- Can be properly parsed by the application

The task will report any validation errors found, making it easier to identify and fix issues before submitting.

---

## ❓ Questions & Answers

### What is the difference between `LOCAL_ONLY` and `OFFLINE`?
Expand Down
12 changes: 12 additions & 0 deletions generators/policies/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,15 @@ tasks.register<JavaExec>("runPolicyExtractor") {
mainClass.set("SqlitePolicyExtractorKt")

}

tasks.register<JavaExec>("validateJson") {
group = "validation"
description = "Validates all JSON policy files for correctness"

dependsOn(kotlin.jvm().compilations["main"].compileTaskProvider)
classpath = files(
kotlin.jvm().compilations["main"].output.allOutputs,
kotlin.jvm().compilations["main"].runtimeDependencyFiles
)
mainClass.set("JsonValidatorKt")
}
82 changes: 82 additions & 0 deletions generators/policies/src/jvmMain/kotlin/JsonValidator.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import io.github.kdroidfilter.database.core.policies.AppPolicy
import kotlinx.serialization.SerializationException
import java.nio.file.Files
import java.nio.file.Path
import kotlin.io.path.extension
import kotlin.io.path.isRegularFile
import kotlin.io.path.name

/**
* Utility to validate JSON policy files
*/
object JsonValidator {
/**
* Validates all JSON files under the given root directory
* @param root The root directory containing JSON files to validate
* @return A list of validation results (file path and error message if any)
*/
fun validateAll(root: Path): List<ValidationResult> {
println("Validating JSON files in: $root")

return Files.walk(root)
.filter { it.isRegularFile() && it.extension == "json" }
.map { path ->
try {
val content = Files.newBufferedReader(path).use { it.readText() }
try {
// Try to parse the JSON using the PolicyRepository's JSON configuration
PolicyRepository.json.decodeFromString(AppPolicy.serializer(), content)
ValidationResult(path, null) // No error
} catch (e: SerializationException) {
ValidationResult(path, e.message ?: "Unknown serialization error")
}
} catch (e: Exception) {
ValidationResult(path, "Error reading file: ${e.message}")
}
}
.toList()
}

/**
* Prints validation results to the console
* @param results The validation results to print
* @return true if all files are valid, false otherwise
*/
fun printResults(results: List<ValidationResult>): Boolean {
val validCount = results.count { it.error == null }
val invalidCount = results.size - validCount

println("Validation complete: $validCount valid, $invalidCount invalid")

if (invalidCount > 0) {
println("\nInvalid files:")
results.filter { it.error != null }
.forEach { result ->
println("- ${result.path.name}: ${result.error}")
}
return false
}

return true
}

/**
* Data class to hold validation result for a single file
*/
data class ValidationResult(val path: Path, val error: String?)
}

/**
* Main function to run the JSON validator
*/
fun main() {
val projectDir = java.nio.file.Paths.get("").toAbsolutePath()
val root = projectDir.parent.resolve("../app-policies")

val results = JsonValidator.validateAll(root)
val isValid = JsonValidator.printResults(results)

if (!isValid) {
System.exit(1)
}
}
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
Loading