Configuration
Konture’s behavior can be customized to match your project’s specific conventions. This guide details plugin configuration parameters and pattern-matching rules. For managing technical debt in legacy codebases, see our dedicated Architecture Baselines guide.
🛠️ Plugin Customization
You can configure the Konture plugin inside your build files to exclude legacy directories, ignore external packages, and set custom trace outputs.
🐘 Gradle Configuration
Add the konture { ... } block inside your root build.gradle.kts or inside your dedicated architecture test project:
konture {
// Exclude subprojects from analysis
excludeModules(":legacy-app", ":experimental:*")
// Exclude specific packages from being parsed
excludePackages("com.acme.generated..", "..databinding..")
// Exclude specific classes or patterns
excludeClasses("ExcludedService", "*Helper")
// Exclude certain Gradle dependency configurations from being traversed
excludeConfigurations("test*", "profile")
// Set the target file name for architecture baselines (default is "konture-baseline.json")
baselinePath("custom-baseline.json")
// Set the task execution log level
logLevel("INFO")
// Set translation language for violation messages (default is "en")
language("fr")
// Tune analysis performance, parallel execution, and persistent caching
analysis {
incremental = true // incremental AST analysis (default: true)
cache = true // persistent disk cache in .konture/cache (default: false)
// cacheDir = "custom/cache/path" // optional override
parallel = true // evaluate architecture rule suites concurrently (default: false)
// maxWorkers = 4 // max worker coroutines for parallel evaluation (default: 0 = unconstrained)
}
}
⚡ Persistent Analysis Cache & Gradle Build Cache
When analysis { cache = true } is enabled, parsed AST snapshots are persisted to a disk cache (.konture/cache/<module-path>/<fingerprint>/ast/v1/ by default) and reused across test executions, so unchanged Kotlin files skip re-parsing entirely — even between separate JVM runs.
- Source changes invalidate automatically: cache entries are keyed by the SHA-256 content hash of each analyzed file, so editing a file always re-parses it.
- Rule/config changes invalidate automatically: the cache directory is namespaced by a fingerprint derived from the effective
analysis { }configuration (and the rest of thekonture { }block). Changing any rule-affecting setting selects a fresh cache namespace, leaving stale entries unused. - Gradle build cache integration: the cache directory is declared as an output of each test task, so Gradle’s up-to-date checks and build cache can snapshot, restore, and skip evaluation entirely for unchanged inputs.
- Library-level control: the same flags are available programmatically via
Konture.cacheEnabled,Konture.cacheDir, andKonture.cacheFingerprint, or via the system propertieskonture.cache.enabled,konture.cache.dir,konture.cache.fingerprint, andkonture.incremental.enabled. Corruption is never fatal: unreadable cache entries are treated as misses and re-parsed.
🚀 Parallel Rule Evaluation
When analysis { parallel = true } is enabled, rule suites grouped within an architecture { } block (e.g., classes { }, files { }, modules { }, slices { }) are evaluated concurrently across coroutine workers using kotlinx.coroutines.
- Deterministic Failure Ordering: Regardless of which rule suite finishes first, evaluation results are collected and sorted deterministically based on rule definition order.
- Thread-Safe State & PSI: Thread-local runtime state (such as rule metadata, severity thresholds, and baselines) is replicated to each worker coroutine, while shared PSI parsing environments and baseline caches are protected by internal concurrency synchronization.
- Worker Limits: Configure
analysis { maxWorkers = 4 }(or-Dkonture.parallel.maxWorkers=4) to cap the concurrency pool on resource-constrained CI agents. Default0uses unconstrained parallelism sized to the host’s available processors. - Library-level control: Can be enabled via
Konture.parallel = trueandKonture.parallelMaxWorkers = 4, or system propertieskonture.parallel.enabledandkonture.parallel.maxWorkers.
Automatic test inputs
The Gradle plugin generates and copies layout_v2.json before Konture test resources are processed, so normal architecture tests do not need a separate layout task. The plugin detects direct calls to notDependOnExternalLibraries and onlyDependOnExternalLibraries in Kotlin sources below a Konture consumer’s src/ directory—including custom, KMP, and Android test source-set conventions. It generates dependencies.json only when at least one consumer needs those rules.
Adding or removing a direct assertion automatically changes the detector input and therefore enables or skips dependency-graph generation on the next test run. Indirect wrapper functions are intentionally fail-closed: if the graph was not prepared, the assertion reports that dependencies.json is required rather than passing with an empty dependency set.
📦 Maven Configuration
Declare your plugin configurations inside the <configuration> block of the konture-maven-plugin inside your dedicated konture-test/pom.xml:
<plugin>
<groupId>io.github.baole.konture</groupId>
<artifactId>konture-maven-plugin</artifactId>
<version>1.0.1</version>
<executions>
<execution>
<phase>process-test-resources</phase>
<goals>
<goal>generate-layout</goal>
</goals>
</execution>
</executions>
<configuration>
<!-- Exclude subprojects from analysis -->
<excludeModules>
<module>legacy-app</module>
</excludeModules>
<!-- Exclude specific packages from being parsed -->
<excludePackages>
<package>com.acme.generated..</package>
<package>..databinding..</package>
</excludePackages>
<!-- Exclude specific classes or patterns -->
<excludeClasses>
<class>ExcludedService</class>
<class>*Helper</class>
</excludeClasses>
<!-- Exclude certain dependency configurations from being traversed -->
<excludeConfigurations>
<configuration>test</configuration>
<configuration>profile</configuration>
</excludeConfigurations>
<!-- Set the task execution log level -->
<logLevel>INFO</logLevel>
</configuration>
</plugin>
📋 Available Settings & Matching Rules
| Parameter | Default Value | Description & Matching Rules |
|---|---|---|
excludeModules | emptyList() | Excludes matching Gradle subprojects from the layout graph. • Supports Module Glob Patterns (e.g., :feature:* or :feature:**). |
excludePackages | emptyList() | Excludes class files in matching packages from being parsed. • Supports Package Segment Wildcards ( ..). |
excludeClasses | emptyList() | Excludes matching classes from the analysis. Fully qualified names and simple class names are checked. • Supports Package Wildcards ( ..) and Simple Globs (*). |
excludeConfigurations | listOf("test", "benchmark", "profile") | Excludes specific dependency configurations from being traversed. • Supports simple glob matching ( *). E.g., test* matches testImplementation. |
logLevel | "INFO" | Configures logging level of the Konture plugin execution. • Supported levels: "INFO", "DEBUG", "WARNING", "TRACE". |
language | "en" | Configures translation language for architectural violation messages. • Supported languages: "en" (English), "fr" (French), "es" (Spanish), "it" (Italian), "vi" (Vietnamese), "zh" / "zh-CN" (Simplified Chinese), "zh-TW" (Traditional Chinese). |
failOnSeverity | Severity.ERROR | Configures the minimum severity threshold required to fail the build with an AssertionError.• Supported values: Severity.ERROR (default, only ERROR violations fail the build), Severity.WARNING (ERROR and WARNING violations fail), Severity.INFO (all violations fail), or null (audit/dry-run mode, no violations fail the build). Can also be overridden via system property -Dkonture.fail.on.severity=error|warning|info|none or programmatically via Konture.failOnSeverity. |
outputFormat | "HUMAN" | Configures output formatting for architectural rule violations. • Supported formats: "HUMAN" (default multi-line console output), "PROBLEM_MATCHER" (single-line IDE/CI problem matcher format path:line:col: Konture [ruleId]: message), "HTML" (standalone HTML report), "JSON" (schema-validated JSON report), "SARIF" (OASIS SARIF v2.1.0 standard for GitHub Code Scanning / SonarQube). Can also be overridden via system property -Dkonture.output.format=json or programmatically via Konture.outputFormat. |
reportPath | "build/reports/konture/konture-report.html" | Configures destination file path for standalone output report files. • Can be overridden via system property -Dkonture.report.path=build/reports/custom-report.html or programmatically via Konture.reportPath. Format-specific paths can also be set via konture.report.html.path, konture.report.json.path, or konture.report.sarif.path. |
incremental | true | Enables incremental AST analysis and SHA-256 source content hashing to skip re-parsing unchanged Kotlin files. • Can be overridden via system property -Dkonture.incremental.enabled=false or programmatically via Konture.incremental. |
analysis.incremental | true | Gradle DSL equivalent of incremental inside the analysis { } block. |
analysis.cache | false | Enables the persistent disk analysis cache (.konture/cache) so unchanged Kotlin files skip re-parsing across test executions.• The cache directory is declared as a test-task output for Gradle build cache / up-to-date checks. • Can be overridden via system property -Dkonture.cache.enabled=false or programmatically via Konture.cacheEnabled. |
analysis.cacheDir | "" (auto) | Optional override of the persistent cache directory. The plugin always appends the module path to the resolved value, so the effective directory is <cacheDir>/<module-path>/ (default <rootProject>/.konture/cache/<module-path>/) and consumer test tasks never share or overwrite the same directory. |
analysis.parallel | false | Enables parallel evaluation of independent architecture rule suites within architecture { } blocks.• Can be overridden via system property -Dkonture.parallel.enabled=true or programmatically via Konture.parallel = true. |
analysis.maxWorkers | 0 | Limits the maximum number of worker coroutines for parallel rule evaluation (0 uses unconstrained parallelism).• Can be overridden via system property -Dkonture.parallel.maxWorkers=4 or programmatically via Konture.parallelMaxWorkers = 4. |
📊 Machine-Readable Reports (JSON & SARIF)
Konture exports comprehensive reports of architecture evaluations, including rule metadata, violation details, source locations, and baseline suppressions.
Supported Output Formats
- JSON (
OutputFormat.JSON):- Default path:
build/reports/konture/konture-report.json - Configurable via
-Dkonture.report.json.path=path/to/report.jsonorKonture.jsonReportPath - Includes full tool info, summary statistics, evaluations, and violations with suppressed flags.
- Default path:
- SARIF v2.1.0 (
OutputFormat.SARIF):- Default path:
build/reports/konture/konture-report.sarif - Configurable via
-Dkonture.report.sarif.path=path/to/report.sariforKonture.sarifReportPath - Compatible with GitHub Code Scanning (
github/codeql-action/upload-sarif), SonarQube, and GitLab SAST. - Suppressed baseline violations are encoded with SARIF suppression objects (
kind: "external",status: "accepted").
- Default path:
- HTML (
OutputFormat.HTML):- Default path:
build/reports/konture/konture-report.html - Configurable via
-Dkonture.report.html.path=path/to/report.htmlorKonture.htmlReportPath
- Default path:
Generating Reports in CI
You can enable machine-readable reports during CI test runs using system properties:
./gradlew test -Dkonture.output.format=sarif
In GitHub Actions, you can upload the resulting SARIF file directly to GitHub Code Scanning:
- name: Run Architecture Tests
run: ./gradlew test -Dkonture.output.format=sarif
- name: Upload SARIF to GitHub Code Scanning
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: build/reports/konture/konture-report.sarif
🧩 Wildcard & Pattern Matching in Depth
Konture utilizes high-performance, lightweight matching engines optimized specifically for Kotlin package hierarchies and Gradle module structures, making them significantly faster than regex parsers.
1. Package Matching (..)
Package paths are dot-separated (e.g., com.acme.feature.payment.service).
- Double Dot (
..): Represents zero or more package segments. - Single Dot (
.): Separates explicit segments.
| Pattern | Matches | Does NOT Match | Why? |
|---|---|---|---|
com.acme.domain.. | com.acme.domaincom.acme.domain.repository | com.acme.apiorg.acme.domain | Matches any package starting with com.acme.domain followed by any depth. |
..generated.. | com.acme.generatedcom.acme.feature.generated.service | com.acme.generatecom.acme.regenerated | Matches any package path where generated appears as a complete segment. |
.. | Matches everything | None | Matches any package sequence. |
2. Module Glob Matching (* vs **)
Gradle subprojects are colon-separated (e.g., :feature:checkout:impl).
- Single Star (
*): Matches exactly one module segment (all characters except the colon:). - Double Star (
**): Matches zero or more module segments (any depth sequence).
| Pattern | Matches | Does NOT Match | Why? |
|---|---|---|---|
:feature:* | :feature:checkout:feature:catalog | :feature:checkout:impl:feature | * matches exactly one levels deep under :feature. |
:feature:** | :feature:checkout:feature:checkout:impl | :core:network | ** matches any depth of subprojects under :feature. |
:*-api | :payment-api:auth-api | :feature:payment-api | Matches any root-level module ending with -api. |
3. Simple Glob Matching (*)
Used for configuration matching (excludeConfigurations) and simple class name matching (excludeClasses).
- Single Star (
*): Matches zero or more characters of any kind.
| Pattern | Matches | Does NOT Match |
|---|---|---|
*Helper | AuthHelperHelpercom.acme.MyHelper | HelpersHelperClass |
test* | testtestImplementationtestRuntimeOnly | latest |
🌐 Internationalization & Localization (I18n)
Konture supports multi-language localization for guardrail assertion violation messages, allowing diverse and distributed teams to run architecture tests in their native languages.
🗺️ Supported Languages
- English (Default):
"en" - French:
"fr" - Spanish:
"es" - Italian:
"it" - Vietnamese:
"vi" - Simplified Chinese:
"zh"or"zh-CN" - Traditional Chinese:
"zh-TW"
⚙️ How to Configure Language
You can configure the target language at multiple levels:
1. Via Gradle Plugin Configuration
Set the language parameter in your konture build block:
konture {
language("fr") // Configure French for violation messages
}
2. Via CLI / Build Arguments
Override the configured language at test-execution time using the JVM system property konture.locale:
./gradlew test -Dkonture.locale=es
3. Programmatic Thread-Isolated Customization
You can programmatically change the locale in your Kotlin test class using Konture.locale. Because Konture uses a thread-isolated context, different test nodes can run on separate threads with distinct locales concurrently without cross-talk or race conditions:
import io.github.baole.konture.Konture
import java.util.Locale
import org.junit.jupiter.api.BeforeEach
class ArchitectureTest {
@BeforeEach
fun setUp() {
Konture.locale = Locale.FRENCH // Isolated to the calling test thread
}
}
🛡️ Fallback Behavior
If a specific translation key is missing from a localized resource bundle, Konture automatically falls back to English (messages.properties) to ensure error message delivery. If a key is completely missing from all resource bundles, Konture returns a safe placeholder fallback string of the form [key: arguments].
🛡️ Architecture Baselines
When integrating architecture tests into large, established codebases, you will often encounter thousands of pre-existing violations. Forcing developers to fix all historical violations immediately is a massive blocker.
Konture solves this with Architecture Baselines, allowing you to record all existing violations to localized, distributed files, ignore them in subsequent runs, and focus entirely on preventing new architectural erosion!
Dedicated Guide: Because managing baselines is critical to scaling architecture tests in enterprise teams, we have split this feature into its own dedicated guide.
🏃 Read the Architecture Baselines Guide to learn about Distributed Baselines, recording existing technical debt, configuration references, and serialization schemas.
Layout generation
Konture’s current Gradle plugin generates build/konture/layout_v2.json. Architecture-test tasks generate and copy this file automatically through processTestResources; running :konture-test:test does not require a separate generation command. If the file is missing outside the Gradle test lifecycle, run ./gradlew generateArchitectureLayout.