##// END OF EJS Templates
Refactor variantArtifacts to variant-level publications with primary and secondary slots
Refactor variantArtifacts to variant-level publications with primary and secondary slots

File last commit:

r34:5ec65d9e5a34 default
r34:5ec65d9e5a34 default
Show More
variant-artifacts-plugin.md
311 lines | 8.0 KiB | text/x-minidsrc | MarkdownLexer
/ common / variant-artifacts-plugin.md
cin
Refactor variantArtifacts to variant-level publications with primary and secondary slots
r34 # Variant Artifacts Plugin
## NAME
`VariantsArtifactsPlugin` и extension `variantArtifacts`.
## SYNOPSIS
```groovy
import org.gradle.api.attributes.Attribute
plugins {
id 'org.implab.gradle-variants-artifacts'
}
def variantAttr = Attribute.of('test.variant', String)
def slotAttr = Attribute.of('test.slot', String)
variants {
layer('main')
variant('browser') {
role('main') { layers('main') }
}
}
variantSources {
bind('main') {
configureSourceSet {
declareOutputs('types', 'js', 'resources')
}
}
}
variantArtifacts {
variant('browser') {
primarySlot('typesPackage') {
fromVariant {
output('types')
}
}
slot('js') {
fromVariant {
output('js')
}
}
slot('resources') {
fromVariant {
output('resources')
}
}
}
whenOutgoingVariant { publication ->
publication.configureConfiguration {
attributes.attribute(variantAttr, publication.variantName())
}
publication.primarySlot().configureArtifactAttributes {
attribute(slotAttr, publication.primarySlot().slotName())
}
publication.requireSlot('js').configureArtifactAttributes {
attribute(slotAttr, 'js')
}
publication.requireSlot('resources').configureArtifactAttributes {
attribute(slotAttr, 'resources')
}
}
}
```
## DESCRIPTION
`VariantsArtifactsPlugin` применяет `VariantsSourcesPlugin`, затем строит
outgoing publication model поверх `variantSources`.
### publication model
Для каждого `variantArtifacts.variant('<name>')` публикуется один outgoing
build variant:
- primary configuration `<variant>Elements`;
- primary artifact slot на самой configuration;
- secondary variants внутри `configuration.outgoing.variants` для остальных slots.
Пример:
- `browserElements`
- primary slot: `typesPackage`
- secondary variants: `js`, `resources`
Это разделяет:
- graph selection build variant-а;
- artifact selection внутри уже выбранного variant-а.
### slot bindings
`slot('<name>')` описывает, какие outputs из `variantSources` войдут в artifact
representation этого slot-а.
Binding rules:
- `fromVariant { output(...) }`
- `fromRole('<role>') { output(...) }`
- `fromLayer('<layer>') { output(...) }`
Каждый slot materialize-ится в отдельный `ArtifactAssembly`:
- task: `process<Variant><Slot>`;
- output dir: `build/variant-artifacts/<variant>/<slot>`.
### primary slot
Primary slot задает artifact, который публикуется как основной artifact
configuration `<variant>Elements`.
Формы DSL:
```groovy
variant('browser') {
primarySlot('typesPackage')
slot('typesPackage') {
fromVariant { output('types') }
}
}
```
или sugar:
```groovy
variant('browser') {
primarySlot('typesPackage') {
fromVariant { output('types') }
}
}
```
Правила:
- если slot один, он считается primary неявно;
- если slots несколько, `primarySlot(...)` обязателен;
- `primarySlot` должен ссылаться на существующий slot.
## LIFECYCLE
- `VariantsArtifactsPlugin` ждет `variants.whenFinalized(...)`;
- после этого валидирует `variantArtifacts`;
- регистрирует `ArtifactAssembly` по каждому slot;
- materialize-ит outgoing publications;
- вызывает `whenOutgoingVariant(...)`;
- callbacks replayable.
После finalize мутации `variantArtifacts` запрещены.
## EVENTS
### whenOutgoingVariant
Replayable callback на готовую outgoing publication variant-а.
Подходит для:
- настройки общих attributes build variant-а один раз;
- настройки per-slot artifact attributes;
- доконфигурации `ArtifactAssembly`.
## PAYLOAD TYPES
### OutgoingVariantPublication
Содержит:
- `variantName()`;
- `topologyVariant()`;
- `variantArtifact()`;
- `configuration()` — primary `<variant>Elements`;
- `primarySlot()`;
- `slots()` — все slot publications;
- `secondarySlots()`;
- `findSlot(name)`, `requireSlot(name)`.
Sugar:
- `configureConfiguration(Action|Closure)`.
### OutgoingArtifactSlotPublication
Содержит:
- `slotName()`;
- `primary()`;
- `slot()` — модель `VariantArtifactSlot`;
- `assembly()`.
Sugar:
- `configureAssembly(Action|Closure)`;
- `configureArtifactAttributes(Action|Closure)`.
`configureArtifactAttributes(...)` пишет attributes:
- в `Configuration.attributes` для primary slot;
- в `ConfigurationVariant.attributes` для secondary slot.
## CONSUMER SIDE
### primary resolution
Обычное inter-project resolution выбирает primary artifact `<variant>Elements`.
Пример:
```groovy
configurations {
compileView {
canBeResolved = true
canBeConsumed = false
canBeDeclared = true
attributes {
attribute(variantAttr, 'browser')
attribute(slotAttr, 'typesPackage')
}
}
}
dependencies {
compileView project(':producer')
}
```
### artifact selection for secondary slots
Secondary artifacts выбираются через `artifactView`.
```groovy
def jsFiles = configurations.compileView.incoming.artifactView {
attributes {
attribute(slotAttr, 'js')
}
}.files
```
Здесь graph variant уже выбран, а `artifactView` выбирает нужный secondary
artifact representation.
## VALIDATION
Проверяется:
- variant существует в topology model;
- slot bindings не ссылаются на неизвестные role/layer;
- при нескольких slots указан `primarySlot`;
- `primarySlot` ссылается на существующий slot.
## API
### VariantArtifactsExtension
- `variant(String)` — получить/создать variant artifact model;
- `variant(String, Action|Closure)` — сконфигурировать variant artifact;
- `getVariants()` — контейнер variant artifacts;
- `findVariant(name)`, `requireVariant(name)`;
- `whenOutgoingVariant(...)`.
### VariantArtifact
- `slot(String)` — получить/создать slot;
- `slot(String, Action|Closure)` — сконфигурировать slot;
- `primarySlot(String)` — назначить primary slot;
- `primarySlot(String, Action|Closure)` — sugar: configure slot + mark as primary;
- `getSlots()`;
- `findSlot(name)`, `requireSlot(name)`;
- `findPrimarySlotName()`, `requirePrimarySlotName()`;
- `findPrimarySlot()`, `requirePrimarySlot()`.
### VariantArtifactSlot
- `fromVariant(...)`;
- `fromRole(String, ...)`;
- `fromLayer(String, ...)`.
### OutputSelectionSpec
- `output(name)`;
- `output(name, extra...)`.
## KEY CLASSES
- `VariantsArtifactsPlugin` — plugin adapter и materialization outgoing variants.
- `VariantArtifactsExtension` — root DSL и lifecycle.
- `VariantArtifact` — outgoing build variant model.
- `VariantArtifactSlot` — artifact representation slot.
- `OutgoingVariantPublication` — payload variant-level publication callback.
- `OutgoingArtifactSlotPublication` — payload per-slot publication callback.
- `ArtifactAssembly` — assembled files for a slot.
## NOTES
- `common` не навязывает доменную логику выбора primary slot.
- `common` не фиксирует значения `usage`, `libraryelements` и прочих
slot-specific attributes.
- `common` не смешивает эту модель с отдельными publish осями вроде package
metadata.
- Closure callbacks используют delegate-first; для вложенных closure удобнее
явный параметр (`publication -> ...`, `slotPublication -> ...`).