Change Log¶
0.8.8 (2026-11-08)¶
- Stop disabling unit tests for the release build type of Android modules. AGP 9.5 registers a
generate<Variant>ComposePreviewRunfilestask for every variant of a module with Compose on, and the task fails during configuration when the variant has no unit test component, so Android Studio sync and./gradlew tasks --allfailed in every Compose module with "Compose Preview failed ... Unit tests are disabled for this variant". AGP has no switch for the task, and since AGP 9 it creates unit tests only for the tested build type by default, so a build on AGP 9.5 also needsandroid.onlyEnableUnitTestForTheTestedBuildType=falseingradle.properties. Release unit test tasks exist again;linuxTeststill runs only the debug ones.
0.8.7 (2026-10-26)¶
- Support Gradle's isolated projects. Every plugin in the suite now reads and configures only the project it is applied to, so a build can set
org.gradle.isolated-projects=true. Before, the plugins reached files, tasks and extensions through the root project, and the build failed during configuration as soon as the flag was on. The functional tests now run with the flag on, and Android lint'sGradleProjectIsolationcheck, which was switched off, is back on, so a plugin that reaches into another project fails the build. - Register
linuxTest,iosTestandciTestin every module instead of on the root project (breaking). Each module plugin attaches the module's tests to the module's own copies../gradlew linuxTeststill runs every module's tests, because Gradle runs a task name in every project that has it, but./gradlew :linuxTestno longer exists. - Remove the check that the root plugin is applied (breaking). A module can no longer see which plugins the root project applied, so a module plugin applied without the root plugin no longer fails at once. Keep applying the root plugin, which still sets up dependency analysis for the whole build.
- Point
ignoreUnusedDependenciesandignoreAllat the module's owndependencyAnalysisblock rather than the root project's.ignoreAllno longer takes project paths (breaking), because a module can only configure itself. CallignoreAll()from the module it should silence. - Remove the
io.github.thomaskioko.gradle.plugins.lintplugin (breaking). It wrote thelint-rulescoordinate into every module from the root project. Setapp.enableLintRules=trueingradle.propertiesinstead, and the Spotless plugin adds the rules, at its own version, to every module it formats. Spotless now reads further rule sets from the module's ownapp.spotless.customRuleSetsextra property only, not from the root project or fromgradle.properties. - Build each module's dependency diagram from files the modules it depends on publish, rather than by walking every project from the root. A new
graphNodetask writes the module's plugin type and direct dependencies, the modules that depend on it resolve that file through a dedicated configuration, andgraphDumpdraws the same diagram as before. With isolated projects on, the root plugin used to skip the graph tasks altogether. Remove themoduleGraph {}block (breaking), because a module cannot read the root project's settings. Its defaults are now fixed: the diagram leaves out modules whose path ends in:testingand countscommonMainApi,commonMainImplementation,apiandimplementation. Every module a diagram reaches has to apply one of the suite's plugins. - List the license and the developer once in each published POM. The build scripts declared both in their
pom {}blocks, and the publish plugin added them again from thePOM_*properties, so the POMs of the plugins, their plugin markers andlint-ruleslisted each twice.
0.8.6 (2026-08-01)¶
- Read string and plural keys from the accessor files Moko Resources 0.27.0 generates. Moko 0.27.0 no longer declares each key inside
MR.stringsandMR.plurals; it writes every key as an extension property in batch files such asCommonMainStrings0.commonMain.kt, leaving theMRobject empty.generateMokoStringsonly readMR.kt, so it found no keys, wrote emptyStringResourceKeyandPluralsResourceKeyclasses, and every reference to a key failed to compile. The task now reads every file Moko generates forcommonMainand sorts the keys, so the output does not depend on the order of the batch files. This needs Moko Resources 0.27.0 or later; a project on an earlier version gets empty classes. - Open the
java.basepackages Robolectric reads through reflection on every test task, following the JVM flags Robolectric documents for JDK 17 and later. Robolectric 4.17 sets the raw file descriptor by reflection when an Android 16 or later SDK boots, and JDK 17 and later refuse that access unless the package is opened, so every module running Robolectric on those SDKs failed before its first test. A consumer no longer needs asubprojectsblock in the root build script to pass the flags itself. - Update the API visibility and make internal calls internal:
ScaffoldProperties,Versioning, the classes behind thebumpVersion,release,generateMokoStringsandgenerateBuildConfigtasks, and the companion objects on the ktlint rules. You configure the plugins throughscaffold {}, so nothing a build script is meant to use has changed. If yours did call one of these, please open an issue. - Stop Android lint failing a module that does not use Compose. The suite turns every lint warning into an error, and it switches off two Compose checks by name. In a module without the Compose checks on its classpath those names mean nothing, so lint reported them as unknown, and the warning became an error that failed the build. Unknown names are now ignored, so a module that does use Compose is unaffected and one that does not builds.
- Turn on core library desugaring in a multiplatform module only when the desugaring library is declared, matching what an Android module already did. The multiplatform path turned it on either way, so a module that added an Android target failed to build with a message asking for a dependency it never said it needed.
- Read an environment variable through Gradle rather than directly, so
buildConfigFieldbehaves. Gradle could not see the read, so it did not know the value was an input. Changing the variable left the previous value compiled in until something else forced the build to reconfigure. - Stop using the lint report settings that the Android Gradle plugin retired. Reports are written either way now, so the settings did nothing except emit a deprecation warning on every build. They wrote reports to a shared folder rather than the module's own; nothing referred to that folder.
- Publish a documentation site at https://thomaskioko.github.io/app-gradle-plugins/, carrying the API reference, the change log and the release guide. It is rebuilt and published each time a release is tagged, and every pull request rebuilds it and fails if a link or a menu entry points at a page that is not there.
- Add an installing page to the site, covering what a project needs before the first module builds: the Google repository, the version catalog entries the plugins read, and naming every plugin on the root project so a module can apply one without a version. Each step was pasted into an empty project and built, in the order it appears. The version in the snippets comes from the release being published, so it can never fall behind the way the one in the README did.
- Add a page for each of the eleven plugins to the site, naming every option in
scaffold {}. Twenty of them had never been written down anywhere, among themuseCodegen,useFeatureFlagCodegen,useDependencyGuard,useFirebase,manifestPlaceholdersand the wholemoduleGraph {}block. Each identifier and each parameter was read from the source rather than carried over, and every sample was pasted into an empty project and built. - Move the code generation guides and the lint rule list onto the site, so everything is in one place and searchable rather than split across three folders. The two module readme files and the comments in the source now point at the pages rather than at file paths, and the root readme is trimmed to what it should have been: what the project is, where the documentation lives, and how to build it.
- Ship real API documentation with every artifact. The documentation file attached to each release has been empty every time, because nothing ever generated one. All six artifacts now carry the full reference built from the comments in the source.
- Document every public declaration and fail the build when one arrives without documentation. Thirty-one were missing, among them the whole
moduleGraph {}block, and four references pointed at names that no longer resolved. The reference is now complete, and it stays that way on its own rather than by anyone remembering. - Save a list of everything each published artifact exposes, and fail the build when a change does not match the saved list. A change that would break someone else's code now has to be made on purpose, and shows up in review as a difference in that file rather than as a surprise after release.
- Turn a compiler warning into a build failure across all three builds, and replace two deprecated compiler flags with the settings that succeed them. Warnings had been switched off, which is how the report settings above stayed deprecated without anyone noticing.
- Check how the plugins themselves are written, using the Android lint checks for Gradle code. They found real faults, listed above. The remaining findings are all one thing, using the root project from a module, which stops Gradle from configuring projects independently. Those are recorded so a new one still fails the build.
- Add the Apache 2.0 license text at the repository root. Every artifact says it is licensed under Apache 2.0, but the license itself was never committed, so GitHub read the project as having no license.
- Add the Apache license header to every Kotlin file, so the published sources carry it too. The formatter was switched on for
pluginsandlint-rulesbut never told which files to read, so most of the project had never been formatted or checked. - Only enable Dependency Guard on
:appwhen release builds exist, sincedebugOnlydisables them andreleaseRuntimeClasspathno longer resolves.
0.8.5 (2026-07-24)¶
- Attach the Android host-test task to the
linuxTestaggregate.KotlinMultiplatformPluginwired variant test tasks by iteratingKotlinTargetWithTests, but the AGP Kotlin Multiplatform android target does not implement that interface, so a module whose suite lived only inandroidHostTestnever reached the aggregate and its tests went unrun on CI while the job still reported green. The plugin now attachestestAndroidHostTestfor any module that has asrc/androidHostTestsource set. Modules carrying onlycommonTestare deliberately left out: those tests already run on the jvm target, and repeating them on the Android host adds runtime without adding coverage. Consumers need no change, though a module that had darkandroidHostTesttests will start running them, so expect the aggregate to take longer and to surface failures that were previously hidden. Locked in by a functional test that asserts the dependency edge throughlinuxTest --dry-runrather than only checking that the task resolves. - Apply the unused-return-value checker (
-Xreturn-value-checker=check) to production compilations only. The flag was set on the sharedcompilerOptions, so it reached every compilation including test source sets, where Kotest matchers (shouldBe,shouldNotBeNull, and the like) are annotated must-use yet legitimately discard their returned subject in an assertion. That produced anUnused return valuewarning on nearly every matcher call across a consumer's test suite.BasePluginnow adds the flag through a task-level configuration that skips Kotlin compile tasks whose name containstest(both unit and instrumented), so production code keeps the check while test compilations build cleanly. Consumers need no change; a module that still wants the check in a specific test source set can add-Xreturn-value-checker=checkback on that compile task. - Document that
@ChildPresenteris the annotation for a presenter that needs a graph but is not a navigation destination. Reaching for@NavDestinationto obtain the@GraphExtensionalso emits aNavDestination.Screenand aNavRouteBinding, and those resolve to nothing when the parent builds the presenter directly rather than routing to it (an app's tab shell, for example), as does theScreenContentif its composable carries@ScreenUi.@ChildPresenter(scope = HostScope::class, parentScope = ActivityScope::class)emits the graph and its factory and nothing else, and the parent injects<Presenter>ChildGraph.Factorythe same way it injected the screen graph factory. The generator already supports this shape, so it needs no codegen change.
0.8.4 (2026-06-27)¶
- Add a
useFirebase()toggle to theapp {}extension that moves the Firebase Gradle wiring out of consumer build files. When agoogle-services.jsonis present at the module root or undersrc/debugorsrc/release, it applies the Google Services and Firebase Crashlytics Gradle plugins and enables mapping file upload on thereleasebuild type; checkouts without the config file skip the wiring so they still build. The Crashlytics Gradle plugin is consumed as acompileOnlydependency for itsCrashlyticsExtensiontype, matching the existing metro and baseline-profile pattern where the consuming project supplies the plugin at runtime viaapply false. - Support a parent-supplied runtime parameter on
@ChildPresenter. When the annotated presenter declares a nested@AssistedFactory(because the parent passes a runtime value such as a show id), the generated<Presenter>ChildGraphnow exposes that assisted factory as its property instead of the presenter directly, mirroring the parameterized@NavDestinationscreen path; the parent injects the generated<Presenter>ChildGraph.Factory, creates the graph with aComponentContext, and callscreate(...)on the exposed factory with the runtime arguments. Plain@Injectchild presenters are unchanged — the graph still exposes the presenter directly, so existing param-less children generate byte-identical output. This lets a parent-owned child presenter that needs a runtime argument (for example a per-section Show Details child scoped to a show id) satisfypresenter-needs-codegen-annotationwith@ChildPresenterrather than a manual assisted factory plus aktlint_tvmaniac_unrouted_presentersexemption. The parser reads the nested@AssistedFactoryandChildGraphGeneratoremits the factory or presenter property accordingly; locked in by a new parameterized golden alongside the existing flat and embeddable shapes.
0.8.3 (2026-06-21)¶
- Remove the
tvmaniac:compose-screen-needs-codegen-annotationrule. The rule flagged any@Composabletaking apresenterparameter that lacked a UI codegen annotation, but a composable that renders a child presenter and is dispatched directly by its parent host (an embedded section or a reusable component embedded in a screen) is intentionally a plain composable, not a navigation destination. A ktlint rule cannot resolve the presenter's type, so it cannot distinguish such an embedded child UI from a routed screen, which made the requirement (and itsktlint_tvmaniac_unrouted_screensexemption list) wrong for the embeddable-component direction. Only routed presenters (@NavDestination/@AppRoot) and their@ScreenUi/@SheetUi/@TabUi/@AppRootUicomposables are codegen-wired; everything else is a plain composable. Thektlint_tvmaniac_unrouted_screensproperty is removed with the rule. - Make the
tvmaniac:presenter-needs-codegen-annotationexemption case-insensitive. The rule compared thektlint_tvmaniac_unrouted_presentersentry against the declared class name with a case-sensitiveincheck, so once the entry reached the rule in a different case than the declared name (for example lowercased, which is how aLowerCasingPropertyType-declared value can arrive through the Gradle ktlint path) a PascalCase entry silently failed to match. The rule now lowercases the parsed exemption set and compares with the lowercased name, and the property uses a case-preserving basePropertyType. Covered by tests that drive a real.editorconfigthroughKtLintRuleEngine, including a case-mismatch case that fails before the fix. - Document the embeddable / reusable component convention for
@ChildPresenter. SettingparentScopeto a shared ancestor scope (ActivityScope) contributes the generated factory to a graph every screen descends from, so a component can live in its own module and be embedded by any host (or nested in another component). The generator is scope-agnostic, so this needs no codegen change; the@ChildPresentergolden coverage now locks in both the flat (pinned) and embeddable shapes. - Add a
moduleGraph {}extension that generates a per-module Mermaid dependency graph viagraphDump/graphUpdatetasks, with configurable module and configuration filtering. - Integrate the
dependency-guardplugin to baseline resolved dependencies.AppPluginguardsreleaseRuntimeClasspathautomatically; other modules opt in viascaffold { useDependencyGuard(...) }.
0.8.2 (2026-06-20)¶
- Clean up experimental Kotlin compiler flags. Remove the
-Xannotation-default-target,-Xcontext-parameters,-Xannotation-target-all,-Xallow-reified-type-in-catch, and-Xexplicit-backing-fieldscompiler flags now that these features are stable in Kotlin 2.4. Passing them had become redundant and made every consumer module emit aredundant for the current language version 2.4warning on each compile task. Projects that pinkotlin-languagebelow 2.4 can pass any flag they still need directly. - Rename
ignoreUnused()toignoreUnusedDependencies()(breaking) and scope it to exclude the named project dependencies from the calling module's unused-dependency check, instead of silencing the named modules' own analysis output. This letsscaffold { ignoreUnusedDependencies(...) }stand in for a hand-written project-scopedconfigure<DependencyAnalysisSubExtension>block when a module declares a dependency asapi(...)for downstream consumers (for example integration-test fixtures) that its own sources never reference.
0.8.1 (2026-06-20)¶
ignoreAll()now defaults to the project it is called from when no path is passed, so a bareignoreAll()inside a module'sscaffold {}block silences that module's dependency analysis. The empty vararg previously silenced nothing, which left framework umbrella modules such asios-frameworkflagged for every dependency the iOS application consumes across the Objective-C boundary.- Exclude
codegen-featureflag-annotationsfrom the unused-dependency analysis. The@FeatureFlagannotation has source retention and is consumed by KSP, so dependency analysis cannot see it in bytecode and reported it as unused on every module that callsuseFeatureFlagCodegen().
0.8.0 (2026-05-19)¶
- Introduce a KSP-based feature-flag codegen that eliminates the per-flag qualifier and DI binding boilerplate in Metro KMP projects. A single
@FeatureFlagobject anchor generates the Metro@Qualifierand theSet<FeatureFlag<Boolean>>binding, and aplatformfield scopes a flag to one platform at compile time. - Bump Kotlin to 2.4.0.
- Refactor dependency analysis exclusions to a DSL-based configuration
tvmaniac:no-manual-nav-bindingflags manual bindings@Provides @IntoSetproviders returningNavRoot,NavRootBinding,NavDestination, orNavRouteBinding. The codegen processor owns those multibindings whenever a presenter is annotated with@NavDestinationor@AppRoot, so any hand-written contribution duplicates the generated provider.
0.7.9 (2026-05-17)¶
- Fix dependency analysis configuration
0.7.8 (2026-05-10)¶
Navigation¶
Three additions extend the codegen surface so consumers no longer hand-write tab pager renderers, parent-owned child presenter graphs, or the NavRoot multibinding.
@TabUitargets a@Composablefunction as the renderer for one tab pager page. The generatedScreenContentbinding mirrors@ScreenUiexcept the matcher casts the active child toTabChild<*>rather thanScreenDestination<*>. Use it on bottom-bar tab pages whose presenters are wrapped asTabChildrather than pushed onto a stack.@ChildPresentertargets a presenter constructed by another presenter rather than navigated to through a route. The processor emits a<Presenter>ChildGraphgraph extension exposing the presenter as a property plus a@ContributesTo(parentScope) @GraphExtension.Factorywhosecreate<BaseName>Graphfunction takes aComponentContextand returns the graph. Multiple children may share ascope; each gets its own graph extension and its own factory function (the unique name avoids return-type collisions when both factories contribute to the same parent scope).@NavDestination(kind = TAB_ROOT)now also contributes the route singleton itself intoSet<NavRoot>. Consumers no longer need to keep a hand-written<Feature>RootBindingnext to each tab to populate that set. The new contribution lives inside the existing<Presenter>TabDestinationBindingfile alongside theNavDestination<*>andNavRootBinding<*>entries.
See annotations.md, examples.md sections 4, 7, and 8, and architecture/consumer-contract.md for the full surface.
Lint rules¶
tvmaniac:presenter-needs-codegen-annotationnow accepts@ChildPresenteras a satisfying annotation, so child presenters routed through the new codegen path no longer need aneditorconfigexemption.
Fix¶
- Apply
com.autonomousapps.dependency-analysisper subproject. - Default
appAuthRedirectSchemetest manifest placeholder on KMP Android targets so transitive AppAuth dependencies do not breakprocessAndroidHostTestManifest/processAndroidDeviceTestManifest.
0.7.7 (2026-05-10)¶
Navigation¶
Two new annotations cover the application's root host. The pair eliminates the manual @BindingContainer that consumers used to write for the root presenter and the multi-argument call site every activity used to make to render the root composable.
@AppRoottargets an@AssistedInjectpresenter implementation. The processor reads the nested@AssistedFactory, infers the bound interface from the implementation's supertypes, and emits a<InterfaceName>BindingContainerthat contributes@Provides @SingleIn(parentScope)for the bound interface. Consumers replace their hand-written root binding container with one annotation.@AppRootUitargets the host@Composablefunction. The processor reads the function's non-modifier parameters and emits anAppRootProviderinterface plus a@Composable AppRootProvider.AppRootContent(modifier)extension. Consumers make their activity-scope@DependencyGraphextend the generatedAppRootProvider, and the activity invokesgraph.AppRootContent()instead of forwarding each dependency by hand.
The codegen now publishes @SingleIn, @Composable, and Modifier in addition to the previously-published Metro and Decompose constants. See annotations.md, examples.md sections 7 and 8, and architecture/consumer-contract.md for the full surface.
Lint rules¶
Two new ktlint rules enforce that the codegen annotations above are actually applied. Forgetting either annotation now fails the build at lint time rather than slipping through to runtime.
tvmaniac:presenter-needs-codegen-annotationflags any top-level class whose name ends withPresenterand is annotated with@Injector@AssistedInjectbut is missing both@NavDestinationand@AppRoot. Classes carrying a@Contributes...Metro annotation are exempt; child presenters routed through a manual@GraphExtensionopt out via the newktlint_tvmaniac_unrouted_presenterseditorconfig property.tvmaniac:compose-screen-needs-codegen-annotationflags any top-level@Composablefunction with apresenterorrootPresenterparameter that is missing@ScreenUi,@SheetUi, and@AppRootUi. Tab-root screens dispatched manually inside a parent host opt out via the newktlint_tvmaniac_unrouted_screenseditorconfig property.
KSP¶
- Register the
kspCommonMainKotlinMetadataoutput (build/generated/ksp/metadata/commonMain/kotlin) as acommonMainKotlin source directory for KMP projects, and wire everyKotlinCompilationTaskand per-targetksp*task to depend on it. Resolves IDEUnresolved referencewarnings for KSP-generated symbols (Metro@GraphExtension, navigation codegen) referenced fromcommonMain. useCodegen()now registers the navigation codegen processor only onkspCommonMainMetadatafor KMP projects (via the newaddKspDependencyForCommonMainhelper). Combined with the metadata srcDir registration above, this avoids duplicate generation that would otherwise occur when per-target ksp tasks reprocessed commonMain sources.
0.7.6 (2026-05-09)¶
Navigation¶
A single annotation now covers every navigation destination. The three older annotations (@NavScreen, @TabScreen, @NavSheet)
have been replaced by @NavDestination(kind = ...), and the processor auto-detects whether a presenter
accepts a runtime parameter from the route.
- Replace
@NavScreen,@TabScreen, and@NavSheetwith a single@NavDestination(kind = ...)annotation. The processor reads one annotation on the presenter and picks the destination role from thekindparameter:SCREENfor stack screens,OVERLAYfor modal sheets and dialogs,TAB_ROOTfor top level tab anchors. - Auto-detect parameterized presenters from a nested Metro's
@AssistedFactory. A presenter with a nested factory generates a binding that reads the route property and threads it throughfactory.create(...). A plain@Injectpresenter generates a binding that exposes the presenter directly. Annotating a tab presenter with@AssistedInjectproduces a compile error because a tab's route is a singletondata objectand carries no payload.
Lint rules¶
A new published lint-rules artifact ships six ktlint rules that enforce the project's navigation, preview, dependency injection, and test naming conventions. Two of the rules read .editorconfig so consumer projects can adapt the navigation layer location and the set of forbidden preview wrappers without forking.
- New
lint-rulesartifact (io.github.thomaskioko.gradle.plugins:lint-rules) shipping six custom ktlint rules:tvmaniac:no-mutating-router-importprevents Decompose router mutation imports outside the navigation layer. The two read only types (ChildStack,ChildSlot) remain allowed everywhere.tvmaniac:no-navigation-construct-outside-navpreventsStackNavigation()andSlotNavigation()construction outside the navigation layer. Type references in parameter and return positions are unaffected.tvmaniac:no-custom-navigator-interfaceprevents feature specific*Navigatorinterfaces. Presenters must inject the canonicalNavigatororSheetNavigatorfromnavigation/api.tvmaniac:no-style-wrapper-in-previewprevents redundant styling wrappers (TvManiacTheme,TvManiacBackground,Surface,MaterialThemeby default) inside@Previewcomposables. The wrapper provider applies the project styling once.tvmaniac:metro-redundant-injectremoves redundant@Injectfrom classes that already declare a Metro@Contributes...annotation. Autocorrect-able.tvmaniac:test-name-formatenforces theshould X given Ytest naming convention. Backticked and camelCase forms are both accepted.
- The navigation and preview rules read
.editorconfigproperties (ktlint_tvmaniac_navigation_module_paths,ktlint_tvmaniac_preview_wrappers,ktlint_tvmaniac_preview_wrapper_packages) so consumer projects can adjust the navigation layer location and the set of forbidden wrappers without forking. See the lint rules documentation.
Misc¶
- Bumped ktlint dependency 1.4.0 → 1.8.0.
- Dependency updates.
0.7.5 (2026-04-26)¶
- Apply KT-42254 Kotlin/Native cache-disable workaround automatically in
addIosTargetsWithXcFramework io.github.thomaskioko.gradle.plugins.rootis now required on the root project. Any subproject plugin in this suite (app,android,jvm,multiplatform,base) throwsGradleExceptionat apply-time whenrootis missing on the root project.- Add
id("io.github.thomaskioko.gradle.plugins.root")to the rootbuild.gradle.ktsplugins block. - Removed per-subproject application of
com.autonomousapps.dependency-analysisfromAndroidPlugin. The plugin is applied only at the root viaRootPlugin; consumers that previously relied on the leaked transitive must applyRootPluginexplicitly. - Introduced typed
ScaffoldPropertieslayer; all Gradle property keys consumed by the plugins are centralized inPropertyKeys. - Aggregate test tasks (
linuxTest,iosTest,ciTest) are now registered only on the root project. Subproject plugins (AndroidPlugin,JvmPlugin,KotlinMultiplatformPlugin) attach their variant test tasks to the root aggregates viadependsOn. - Removed dead
SpotlessPlugin.shouldConfigureXmlFormattingmethod. AndroidPluginno longer throws when thelintbundle is absent from the consumer's version catalog. The lint-check bundle is now correctly optional via the newgetBundleDependenciesOrNullhelper (matches existinggetDependencyOrNull).
0.7.4 (2026-04-25)¶
- Apply manifest placeholders to device tests
0.7.3 (2026-04-21)¶
- Add
manifestPlaceholdersDSL
0.7.2 (2026-04-18)¶
- Add support for UI renderer bindings
0.7.1 (2026-04-17)¶
- Introduce a KSP-based navigation codegen that eliminates per-destination DI boilerplate in Metro + Decompose KMP projects.
0.6.7 (2026-04-10)¶
- Remove SKIE DSL
0.6.6 (2026-04-09)¶
- Fix iOS test crashes for modules using moko resources.
- Copy moko resource bundles to iOS test binaries so localization tests run on iOS.
- Optimize
MokoResourceGeneratorTask: remove dead incremental logic, reduce duplication, scope compile dependency tocommonMain. - Add golden file tests for moko resource code generation.
0.6.4 (2026-04-01)¶
- Add Metro Gradle plugin and configure contribution providers.
- Add support for Compose UI tests.
- Dependency updates.
0.6.3 (2026-03-26)¶
- Remove Tag publishing from beta builds
0.6.2 (2026-03-25)¶
- Add support for beta version bumps.
- Update
AppPluginto useBUILD_NUMBERand enable release optimizations.
0.6.1 (2026-03-24)¶
- Push release tags to origin automatically during release.
0.6.0 (2026-03-24)¶
- Add release automation tasks (
bumpVersion,release). - Dependency updates.
0.5.1 (2026-02-26)¶
- Enable new compiler features: explicit backing fields, reified types in catch clauses, and
@all:annotation target. - Fix dependency analysis plugin configuration for KMP projects.
- Replace deprecated
-Xjvm-defaultcompiler flag with-jvm-default. - Dependency updates.
0.5.0 (2026-02-12)¶
- Migrate to gradle 9.0
- Delete
AndroidMultiplatformPluginplugin. We now only needKotlinMultiplatformPlugin - Remove
org.jetbrains.kotlin.android - Delete deprecated androidTarget support.
0.4.3 (2025-12-30)¶
- Enable return-value-checker.
- Enable
explicitApiby default and remove it from base extension. - Update java-toolchain version to 25.
- Dependency updates.
0.4.2¶
- Rename
useSkies()touseSkie() - Fix typo in release key alias property (
rReleaseKeyAlias→releaseKeyAlias) - Make
MokoResourceGeneratorTaskpackage name configurable viaresourcePackageproperty - Improve configuration cache compatibility and task disabling performance
- Add validation for release signing properties and BuildConfig package name
- Remove duplicate
-Xconsistent-data-class-copy-visibilitycompiler argument
0.4.1¶
- Dependency updates.
0.4.0¶
- Add "io.github.thomaskioko.gradle.plugins.buildconfig" plugin. Helps us read keys from
local.properties
Usage
buildConfig {
packageName.set("com.thomaskioko.tvmaniac.core.base")
booleanField("IS_DEBUG", true)
buildConfigField("TMDB_API_KEY")
buildConfigField("CLIENT_ID")
buildConfigField("CLIENT_SECRET")
}
0.3.2¶
- Added
useSkie()to DSL - Group Kotlin, KSP & Skie in Renovate
- Enable Kotlin/Native binary size optimization (Experimental) - Reduces release binary size
- Simplify DisableTasks and fix library lint configuration
0.3.0¶
- CI/CD automation
- Enable tests in multiplatform by default
- Configure ktlint & spotless.
- Fix formatting on files
0.2.1¶
- Add debug flag and disable tasks during development.
- Update dependencies.
0.1.0¶
- Initial stable release
- Maven Central publishing support
Plugin Inventory¶
com.thomaskioko.gradle.app- Android application modulescom.thomaskioko.gradle.android- Android library modulescom.thomaskioko.gradle.android.multiplatform- Android targets in KMPcom.thomaskioko.gradle.jvm- JVM modulescom.thomaskioko.gradle.multiplatform- Kotlin Multiplatform modulescom.thomaskioko.gradle.base- Base configurationscom.thomaskioko.gradle.root- Root project setupcom.thomaskioko.gradle.baseline.profile- Android baseline profilescom.thomaskioko.gradle.spotless- Code formatting with Spotlesscom.thomaskioko.resource.generator- Moko resource generation