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 the konture { } 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, and Konture.cacheFingerprint, or via the system properties konture.cache.enabled, konture.cache.dir, konture.cache.fingerprint, and konture.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. Default 0 uses unconstrained parallelism sized to the host’s available processors.
  • Library-level control: Can be enabled via Konture.parallel = true and Konture.parallelMaxWorkers = 4, or system properties konture.parallel.enabled and konture.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

  1. JSON (OutputFormat.JSON):
    • Default path: build/reports/konture/konture-report.json
    • Configurable via -Dkonture.report.json.path=path/to/report.json or Konture.jsonReportPath
    • Includes full tool info, summary statistics, evaluations, and violations with suppressed flags.
  2. SARIF v2.1.0 (OutputFormat.SARIF):
    • Default path: build/reports/konture/konture-report.sarif
    • Configurable via -Dkonture.report.sarif.path=path/to/report.sarif or Konture.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").
  3. HTML (OutputFormat.HTML):
    • Default path: build/reports/konture/konture-report.html
    • Configurable via -Dkonture.report.html.path=path/to/report.html or Konture.htmlReportPath

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.domain
com.acme.domain.repository
com.acme.api
org.acme.domain
Matches any package starting with com.acme.domain followed by any depth.
..generated.. com.acme.generated
com.acme.feature.generated.service
com.acme.generate
com.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 AuthHelper
Helper
com.acme.MyHelper
Helpers
HelperClass
test* test
testImplementation
testRuntimeOnly
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.


This site uses Just the Docs, a documentation theme for Jekyll.