PLASMA-8120: feat(sdds-core/theme-builder): per-platform generate tasks - #920
Merged
Merged
Conversation
raininforest
requested review from
SerraMorec,
angirb and
malilex
as code owners
September 16, 2026 06:30
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Advanced Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
raininforest
force-pushed
the
develop
branch
from
September 16, 2026 15:24
79a7c34 to
4fcb0d2
Compare
SerraMorec
approved these changes
Sep 18, 2026
… local components source Adds generateComposeTheme/generateViewTheme/generateComposeComponents/ generateViewComponents alongside the existing generateTheme/ generateComponents, each generating exactly one platform and registered only when the module actually configures it. This unblocks an external caller (the dsbuilder CLI's Android platform delegate) that needs to request one platform and get a clear "task not found" instead of a silent wrong-platform generation. - ThemeBuilderPlugin: registerThemeGenerator/registerGenerateComponentsTask take target as an explicit parameter instead of always reading extension.target; existing generateTheme/generateComponents calls are unchanged (same name, same type, same target incl. ALL). - SddsComponentsSourceReader: local .sdds/components/meta.json fallback for dsBuilder.components, mirroring the existing theme fallback. registerFetchAndUnzipComponents skips fetch/unzip for local sources. - Generate tasks are finalizedBy(spotlessApply) when present, with mustRunAfter declared from the spotless* tasks themselves — Gradle's implicit-dependency validation doesn't accept finalizedBy alone here, since spotlessKotlin reads the whole src/main/kotlin tree including freshly generated files. - Syncs the ds-builder-gradle-dsl spec and adds the new components-builder-dsbuilder-source capability spec; archives the dsbuilder-cli-integration OpenSpec change.
…egation tasks Review feedback on the CLI delegate (design-system-builder#74) pointed out that the same "request a platform the module didn't configure and get a clear error" reasoning behind the per-platform theme/components tasks applies equally to documentationAggregate, which today is a single task per module that silently picks Compose over View. Adds aggregateComposeDocumentation/aggregateViewDocumentation, registered only when that platform's target and documentation.compose/ documentation.view resolve, each pinned to its own componentsInfoFile/ themeInfoFile. documentationExtract is shared (code-snippet extraction isn't platform-specific). documentationAggregate itself is unchanged: same name, same Compose-over-View priority, still the only one wired into preBuild/autoGenerate.
…tionable FontTokenValidator reported duplicate fontWeight/fontStyle combinations with a bare "has fontWeight and fontStyle duplicates" message that named neither the font family nor which files collided. Include the family name and the colliding file names per duplicate weight/style pair. Also move the duplicate check out of the per-font forEach loop — it re-scanned the whole font list from scratch on every iteration (O(n^2) for no reason), now it runs once after the loop.
… generated theme name Theme generation names the theme object from .sdds/config.json's tenant publicName (SddsThemeSourceReader.baseAlias), while component generation fell back to .sdds/components/meta.json's own "name" field when no explicit componentSource was configured. When the tenant's public name differs from the components package name (e.g. tenant "init_default" vs components "init"), generated component styles end up referencing a theme object (<name>Theme) that was never generated — every style file fails to compile with "Unresolved reference". SddsComponentsSourceReader.read() now accepts an optional themeNameOverride; ComponentsCapability.toLegacyExtension resolves it from the same SddsThemeSourceReader the theme capability uses, falling back to the old meta.json-derived name if the theme config is missing or unreadable (so components-only projects, with no theme block, keep working).
…mentation pipeline Two independent problems surfaced only when the full generateTheme -> generateComponents -> documentationExtract -> documentationAggregate chain ran together under configuration cache: - documentationExtract reads src/main/kotlin and src/main/theme-builder-res directly via project.file(...), with no declared dependency on the tasks that write them. Gradle can't infer the ordering itself, and with configuration cache enabled this is a hard "implicit dependency" failure instead of a warning. Order it explicitly with mustRunAfter against both generator task types (tasks.withType — safe even when a capability is disabled and its task was never registered). - ExtractCodeSnippetsTask.compile() called project.layout.projectDirectory from inside @TaskAction — Task.project access at execution time is unsupported under configuration cache. Snapshot it into a DirectoryProperty at configuration time instead and read that at execution time.
…ly optional screenshotsDirectory and userDocumentationRoot on DocumentationAggregateTask are declared @optional @InputDirectory, and aggregate() already treats a missing value as "no override docs" via .orNull. But registerAggregate() always set them to the convention path regardless of whether it existed on disk, and Gradle validates any *set* @InputDirectory value for existence even when the property is optional — so a project with no override-docs/ directory (the common case) failed to build. Only set the property when the directory is actually present; otherwise leave it unset, which is exactly what the optional/.orNull handling already expects. Updated the plugin test fixture to create override-docs/ since it's now asserting on the convention path resolving to a real directory.
…json and change theme defaults
dsBuilder.targets defaulted to an empty set, requiring every project to
repeat targets { compose() } even though .sdds/config.json already records
which platforms the project generates for (its "platforms" array, written
by the DS Builder CLI). Add SddsThemeSourceReader.readPlatforms(), mapping
"compose"/"android-view" to DsBuilderPlatform, and wire it as the
convention for extension.targets. It's a genuine default: an explicit
targets { } block in the build script still fully replaces it (standard
Gradle Property/SetProperty convention semantics — add/addAll supersede the
convention entirely on first call), and a missing or unreadable config.json
resolves to an empty set exactly like before.
Also change two theme defaults that made sense while the generator was
young but don't match how projects are actually configured today:
- mode: TOKENS_ONLY -> THEME
- ignoreDisabledTokens: false -> true
…h configuration cache GeneratorFactory and the generators it builds (themeGenerator, dimensGenerator, themeInfoGenerator, ...) held live DOM nodes (XmlResourcesDocumentBuilder) that configuration cache can't serialize, but they were stored as by unsafeLazy task fields — evaluated once and kept alive for the task's lifetime. Move factory/generator construction into local variables computed inside generate() instead, so nothing non-serializable is retained as task state between configuration and execution. palette follows the same pattern (local val instead of a lazy field) but stays where it's actually first used, right before createColorGenerator/ createShadowGenerator — matching the original lazy-evaluation point. Reading it any earlier makes a missing/invalid palette file mask earlier, more specific validation errors (missing metaFile, missing default tenant, missing tenant color/gradient/... files), which is what the existing test suite for this task checks message-for-message.
…om.ds.builder DEFAULT_KT_PACKAGE was com.themebuilder.tokens, used whenever a project doesn't set dsBuilder.packageName explicitly.
raininforest
force-pushed
the
feature/ds-builder-generate
branch
from
September 18, 2026 11:40
9eead16 to
74f0a26
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ПР в ds-builder salute-developers/design-system-builder#74