Skip to content

Commit 8bac4c9

Browse files
committed
[rules score] decouble unit name from bazel name
1 parent 380124c commit 8bac4c9

28 files changed

Lines changed: 374 additions & 119 deletions

File tree

‎bazel/rules/rules_score/docs/rule_reference.rst‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,11 @@ diagram.
668668
* - ``name``
669669
- string
670670
- yes
671-
- Target name; **must match** the ``<<unit>>`` name in the static PlantUML diagram
671+
- Target name; **must match** the ``<<unit>>`` name in the static PlantUML diagram unless ``design_name`` is set
672+
* - ``design_name``
673+
- string
674+
- no
675+
- Name to match against the static PlantUML diagram instead of ``name`` (default: ``name``)
672676
* - ``unit_design``
673677
- label list
674678
- yes
@@ -730,7 +734,11 @@ diagram.
730734
* - ``name``
731735
- string
732736
- yes
733-
- Target name; **must match** the ``<<component>>`` name in the static PlantUML diagram
737+
- Target name; **must match** the ``<<component>>`` name in the static PlantUML diagram unless ``design_name`` is set
738+
* - ``design_name``
739+
- string
740+
- no
741+
- Name to match against the static PlantUML diagram instead of ``name`` (default: ``name``)
734742
* - ``requirements``
735743
- label list
736744
- yes

‎bazel/rules/rules_score/docs/user_guide/architectural_design.rst‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,24 @@ component
449449
tests = [],
450450
)
451451
452+
Decoupling the Bazel Target Name from the Diagram Alias
453+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
454+
455+
By default the consistency check matches a ``unit``/``component`` against the
456+
PlantUML diagram by its Bazel target name. Pass ``design_name`` to match
457+
against a different alias instead — useful when the Bazel target name must
458+
follow a repo-wide naming convention that differs from the architecture diagram:
459+
460+
.. code-block:: starlark
461+
462+
unit(
463+
name = "unit_1_impl",
464+
design_name = "unit_1", # matches "unit_1" in the PlantUML diagram
465+
unit_design = ["//unit_1/docs:unit_design"],
466+
implementation = [":unit_1_lib"],
467+
tests = [":unit_1_test"],
468+
)
469+
452470
Dynamic Architecture
453471
----------------------
454472

‎bazel/rules/rules_score/private/architecture_aspect.bzl‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ def _collect_current_architecture_aspect_impl(target, ctx):
4040

4141
# Check if it's a unit or a component
4242
if UnitInfo in comp:
43-
current_units.append(comp_label)
43+
current_units.append({"label": comp_label, "design_name": comp[UnitInfo].design_name})
4444
elif ComponentInfo in comp:
45-
current_components.append(comp_label)
45+
current_components.append({"label": comp_label, "design_name": comp[ComponentInfo].design_name})
4646

4747
if CurrentArchitectureProviderInfo in comp:
4848
nested_info = comp[CurrentArchitectureProviderInfo]

‎bazel/rules/rules_score/private/component.bzl‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ def _component_impl(ctx):
325325
# ComponentInfo: lobster traceability files for requirements, architecture, and tests; propagated up to dependable_element
326326
ComponentInfo(
327327
name = ctx.label.name,
328+
design_name = ctx.attr.design_name or ctx.label.name,
328329
requirements = req_lobster_depset,
329330
requirements_transitive = req_lobster_transitive_depset,
330331
components = components_depset,
@@ -360,6 +361,10 @@ _component_test = rule(
360361
implementation = _component_impl,
361362
doc = "Defines a software component composed of multiple units for S-CORE process compliance",
362363
attrs = {
364+
"design_name": attr.string(
365+
default = "",
366+
doc = "Name matched against the PlantUML component-diagram alias; defaults to name.",
367+
),
363368
"requirements": attr.label_list(
364369
default = [],
365370
providers = [[ComponentRequirementsInfo], [FeatureRequirementsInfo]],
@@ -408,6 +413,7 @@ def component(
408413
requirements = None,
409414
components = [],
410415
test_case_coverage_lock = None,
416+
design_name = None,
411417
testonly = True,
412418
**kwargs):
413419
"""Define a software component following S-CORE process guidelines.
@@ -437,6 +443,9 @@ def component(
437443
If provided, the component rule generates test_case_coverage.lobster by comparing
438444
computed test coverage against the committed lock. Enables `.update`
439445
target for refreshing coverage.
446+
design_name: Optional name matched against the PlantUML component-diagram
447+
alias, decoupled from the Bazel target name (analogous to py_binary's
448+
`main`). Defaults to name.
440449
testonly: If true, only testonly targets can depend on this component.
441450
visibility: Bazel visibility specification for the component target.
442451
@@ -459,6 +468,7 @@ def component(
459468
components = components,
460469
tests = tests,
461470
test_case_coverage_lock = test_case_coverage_lock,
471+
design_name = design_name or "",
462472
testonly = testonly,
463473
**kwargs
464474
)

‎bazel/rules/rules_score/private/dependable_element.bzl‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -977,9 +977,9 @@ def _collect_architecture_components(ctx):
977977
de_units = []
978978
for comp in ctx.attr.components:
979979
if ComponentInfo in comp:
980-
de_components.append(str(comp.label))
980+
de_components.append({"label": str(comp.label), "design_name": comp[ComponentInfo].design_name})
981981
elif UnitInfo in comp:
982-
de_units.append(str(comp.label))
982+
de_units.append({"label": str(comp.label), "design_name": comp[UnitInfo].design_name})
983983

984984
de_entry = {}
985985
if de_components:

‎bazel/rules/rules_score/private/unit.bzl‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ def _unit_impl(ctx):
147147
CertifiedScope(transitive_scopes = depset(ctx.attr.scope)),
148148
UnitInfo(
149149
name = ctx.label.name,
150+
design_name = ctx.attr.design_name or ctx.label.name,
150151
unit_design = design_depset,
151152
unit_design_static_fbs = design_static_fbs_depset,
152153
unit_design_dynamic_fbs = design_dynamic_fbs_depset,
@@ -169,6 +170,10 @@ def _unit_impl(ctx):
169170
# ============================================================================
170171

171172
_unit_attrs = {
173+
"design_name": attr.string(
174+
default = "",
175+
doc = "Name matched against the PlantUML component-diagram alias; defaults to name.",
176+
),
172177
"unit_design": attr.label_list(
173178
default = [],
174179
providers = [UnitDesignInfo],
@@ -223,6 +228,7 @@ def unit(
223228
implementation,
224229
tests,
225230
scope = [],
231+
design_name = None,
226232
testonly = True,
227233
**kwargs):
228234
"""Define a software unit following S-CORE process guidelines.
@@ -243,6 +249,9 @@ def unit(
243249
but not explicitly named in the implementation list. Default is empty list.
244250
tests: List of labels to Bazel test targets (cc_test, rust_test, etc.)
245251
that verify the unit implementation.
252+
design_name: Optional name matched against the PlantUML component-diagram
253+
alias, decoupled from the Bazel target name (analogous to py_binary's
254+
`main`). Defaults to name.
246255
testonly: If true, only testonly targets can depend on this unit. Set to true
247256
when the unit depends on testonly targets like tests.
248257
visibility: Bazel visibility specification for the unit target.
@@ -274,6 +283,7 @@ def unit(
274283
implementation = implementation,
275284
scope = scope,
276285
tests = tests,
286+
design_name = design_name or "",
277287
testonly = testonly,
278288
**kwargs
279289
)

‎bazel/rules/rules_score/providers.bzl‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ UnitInfo = provider(
7676
doc = "Provider for unit artifacts.",
7777
fields = {
7878
"name": "Name of the unit target.",
79+
"design_name": "Name used to match this unit against its PlantUML component-diagram alias; defaults to name.",
7980
"unit_design": "Depset of design artifact files (PlantUML diagrams, RST documents, etc.).",
8081
"unit_design_static_fbs": "Depset of FlatBuffers binaries generated from static unit_design diagrams.",
8182
"unit_design_dynamic_fbs": "Depset of FlatBuffers binaries generated from dynamic unit_design diagrams.",
@@ -163,6 +164,7 @@ ComponentInfo = provider(
163164
doc = "Provider for component artifacts.",
164165
fields = {
165166
"name": "Name of the component target.",
167+
"design_name": "Name used to match this component against its PlantUML component-diagram alias; defaults to name.",
166168
"requirements": "Depset of component requirement traceability files (.lobster) collected from this component's own ComponentRequirementsInfo targets only (CompReq kind); not rolled up from nested components. Does not include feature or assumed-system requirement files. Consumed only by dependable_element's test-case-coverage-lock check. Includes `derived_from` tracing targets, including any AoU references within it (resolved only at the dependable_element level).",
167169
"requirements_transitive": "Depset of component requirement traceability files (.lobster), rolled up transitively from this component and all nested components. Consumed by dependable_element to build the aggregated 'Component Requirements' traceability report tier.",
168170
"components": "Depset of nested component and/or unit Targets that comprise this component.",

‎bazel/rules/rules_score/test/BUILD‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,49 @@ dependable_element(
836836
deps = [],
837837
)
838838

839+
# Regression test for design_name: the unit's Bazel target name
840+
# ("design_name_unit_bazel_target") differs from the alias matched against
841+
# the PlantUML component diagram ("design_name_unit"), decoupled via the
842+
# design_name attribute.
843+
architectural_design(
844+
name = "arch_design_design_name_example",
845+
static = ["fixtures/design_name_example.puml"],
846+
)
847+
848+
unit(
849+
name = "design_name_unit_bazel_target",
850+
testonly = True,
851+
design_name = "design_name_unit",
852+
scope = ["//:mock_lib1"],
853+
tests = [],
854+
unit_design = [":test_unit_design"],
855+
implementation = [":mock_lib1"],
856+
)
857+
858+
component(
859+
name = "design_name_component",
860+
testonly = True,
861+
components = [":design_name_unit_bazel_target"],
862+
requirements = [
863+
":comp_req",
864+
":feat_req",
865+
],
866+
tests = [],
867+
)
868+
869+
dependable_element(
870+
name = "design_name_example_lib",
871+
architectural_design = [":arch_design_design_name_example"],
872+
assumptions_of_use = [":aous"],
873+
components = [":design_name_component"],
874+
dependability_analysis = [":dependability_analysis_target"],
875+
integrity_level = "B",
876+
maturity = "development",
877+
requirements = [":feat_req"],
878+
tests = [],
879+
deps = [],
880+
)
881+
839882
unit(
840883
name = "seooc_test_unit",
841884
testonly = True,
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
' *******************************************************************************
2+
' Copyright (c) 2026 Contributors to the Eclipse Foundation
3+
'
4+
' See the NOTICE file(s) distributed with this work for additional
5+
' information regarding copyright ownership.
6+
'
7+
' This program and the accompanying materials are made available under the
8+
' terms of the Apache License Version 2.0 which is available at
9+
' https://www.apache.org/licenses/LICENSE-2.0
10+
'
11+
' SPDX-License-Identifier: Apache-2.0
12+
' *******************************************************************************
13+
14+
@startuml design_name_example
15+
16+
package "Design Name Example" as design_name_example_lib <<SEooC>> {
17+
component "Design Name Component" as design_name_component <<component>> {
18+
component "Design Name Unit" as design_name_unit <<unit>>
19+
}
20+
}
21+
22+
@enduml

‎validation/core/docs/specifications/bazel_component.md‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@ checks below operate on that merged view regardless of how many static files
2929
contributed to it. See the `architectural_design` rule reference for the
3030
cross-file merge rules.
3131

32-
All comparisons are case-insensitive: both Bazel target short names and
33-
PlantUML aliases/IDs are normalized to lowercase before matching, so a Bazel
34-
target `Component_X` matches a PlantUML entity `as COMPONENT_X`. Names are
35-
derived from the PlantUML `alias` when present, otherwise from the `id`. On
36-
the Bazel side, IDs are generated from the target's short name (the part
37-
after the last `:` in the label), also lowercased. Parent aliases are
38-
lowercased the same way when resolving parent-child relationships.
32+
All comparisons are case-insensitive: both Bazel entity keys and PlantUML
33+
aliases/IDs are normalized to lowercase before matching, so a Bazel entity
34+
`Component_X` matches a PlantUML entity `as COMPONENT_X`. Names are derived
35+
from the PlantUML `alias` when present, otherwise from the `id`. On the
36+
Bazel side, each `unit`/`component` entry carries a `design_name` (the
37+
`design_name` attribute passed to the `unit`/`component` macro, defaulting
38+
to the target's short name) which is used as the entity key, also
39+
lowercased. Parent aliases are lowercased the same way when resolving
40+
parent-child relationships.
3941

4042
### Dependable Element Consistency
4143

@@ -112,7 +114,9 @@ immediate enclosing component alias as parent.
112114

113115
Every Bazel label must define a target name. A label such as `@//pkg:` (a
114116
colon with nothing following it) has no target name and is rejected with a
115-
`[Design]` error before any entity matching happens.
117+
`[Design]` error before any entity matching happens -- this check runs
118+
independently of `design_name`, so a malformed label is still rejected even
119+
though `design_name` is the actual match key.
116120

117121
### Duplicate Entity Detection
118122

0 commit comments

Comments
 (0)