diff --git a/bazel/rules/rules_score/README.md b/bazel/rules/rules_score/README.md index aea4c605..5162c104 100644 --- a/bazel/rules/rules_score/README.md +++ b/bazel/rules/rules_score/README.md @@ -66,13 +66,14 @@ Also generates a `_test` target that validates metamodel compliance. ```starlark assumptions_of_use( name = "my_aou", - requirements = [":my_feat_reqs"], srcs = ["assumptions.rst"], ) ``` -**`bazel build`** — collects LOBSTER traceability files from the linked -requirements and exposes them via `AssumptionsOfUseInfo`. +**`bazel build`** — renders the AoU TRLC/RST sources and exposes their +LOBSTER traceability file via `AssumptionsOfUseInfo.aou_lobster`. Tracing to +feature/assumed-system requirements is established at the `dependable_element` +level (via its own `requirements` attribute), not here. --- diff --git a/bazel/rules/rules_score/private/assumptions_of_use.bzl b/bazel/rules/rules_score/private/assumptions_of_use.bzl index f5a522cc..4eacad4b 100644 --- a/bazel/rules/rules_score/private/assumptions_of_use.bzl +++ b/bazel/rules/rules_score/private/assumptions_of_use.bzl @@ -14,127 +14,22 @@ """ Assumptions of Use build rules for S-CORE projects. -This module provides macros and rules for defining Assumptions of Use (AoU) -following S-CORE process guidelines. Assumptions of Use define the safety-relevant +This module provides a macro for defining Assumptions of Use (AoU) following +S-CORE process guidelines. Assumptions of Use define the safety-relevant operating conditions and constraints for a Safety Element out of Context (SEooC). -""" - -load("@lobster//:lobster.bzl", "subrule_lobster_trlc") -load("@trlc//:trlc.bzl", "TrlcProviderInfo", "trlc_requirements_test") -load("//bazel/rules/rules_score:providers.bzl", "AssumptionsOfUseInfo", "ComponentRequirementsInfo", "FeatureRequirementsInfo", "SphinxSourcesInfo") -load("//bazel/rules/rules_score/private:rst_to_trlc.bzl", "rst_srcs_to_trlc") - -# ============================================================================ -# Private Rule Implementation -# ============================================================================ - -def _assumptions_of_use_impl(ctx): - """Implementation for assumptions_of_use rule. - Collects assumptions of use source files and links them to their - parent feature requirements through providers. +Implemented as the "aou" kind of the shared score_requirements_rule (see +requirements.bzl), so raw .trlc files, .rst files, and existing +TrlcProviderInfo-emitting targets (e.g. trlc_requirements) may all be passed +as srcs, matching the conventions of feature_requirements, +component_requirements, and assumed_system_requirements. - Args: - ctx: Rule context - - Returns: - List of providers including DefaultInfo and AssumptionsOfUseInfo - """ - - # Render each TRLC source to RST for Sphinx - rendered_files = [] - for src in ctx.attr.srcs: - trlc_provider = src[TrlcProviderInfo] - rendered_file = ctx.actions.declare_file("{}_{}.rst".format(ctx.attr.name, src.label.name)) - args = ctx.actions.args() - args.add("--output", rendered_file.path) - args.add("--input-dir", ".") - args.add("--title", ctx.label.name.replace("_", " ").title()) - args.add("--source-files") - args.add_all(trlc_provider.reqs) - ctx.actions.run( - inputs = src[DefaultInfo].files, - outputs = [rendered_file], - arguments = [args], - executable = ctx.executable._renderer, - ) - rendered_files.append(rendered_file) - - all_srcs = depset(rendered_files) - - # Generate lobster file from AoU TRLC sources for traceability forwarding - all_trlc_files = [] - for src in ctx.attr.srcs: - all_trlc_files.extend(src[DefaultInfo].files.to_list()) - aou_lobster_file = None - if all_trlc_files and ctx.file.lobster_config: - aou_lobster_file, _ = subrule_lobster_trlc(all_trlc_files, ctx.file.lobster_config) - - # Collect requirements providers and lobster files - reqs = [] - lobster_files = [] - for req in ctx.attr.requirements: - if FeatureRequirementsInfo in req: - info = req[FeatureRequirementsInfo] - reqs.append(info) - lobster_files.append(info.srcs) - elif ComponentRequirementsInfo in req: - info = req[ComponentRequirementsInfo] - reqs.append(info) - lobster_files.append(info.srcs) - - # Collect transitive sphinx sources from requirements - transitive = [all_srcs] - for req in ctx.attr.requirements: - if SphinxSourcesInfo in req: - transitive.append(req[SphinxSourcesInfo].deps) - - return [ - DefaultInfo(files = all_srcs), - AssumptionsOfUseInfo( - srcs = depset(transitive = lobster_files), - aou_lobster = depset([aou_lobster_file] if aou_lobster_file else []), - name = ctx.label.name, - ), - SphinxSourcesInfo( - srcs = all_srcs, - deps = depset(transitive = transitive), - aux_srcs = depset(), - ), - ] - -# ============================================================================ -# Rule Definition -# ============================================================================ +Traceability to feature/assumed-system requirements is established at the +dependable_element level (via its own `requirements` attribute), not here. +""" -_assumptions_of_use = rule( - implementation = _assumptions_of_use_impl, - doc = "Collects Assumptions of Use documents with traceability to feature requirements", - attrs = { - "srcs": attr.label_list( - providers = [TrlcProviderInfo], - mandatory = True, - doc = "trlc_requirements targets containing Assumptions of Use specifications", - ), - "requirements": attr.label_list( - providers = [[FeatureRequirementsInfo], [ComponentRequirementsInfo]], - mandatory = False, - doc = "List of feature or component requirements targets that these Assumptions of Use trace to", - ), - "lobster_config": attr.label( - allow_single_file = True, - mandatory = True, - doc = "Lobster YAML configuration file for AoU traceability extraction.", - ), - "_renderer": attr.label( - default = Label("@trlc//tools/trlc_rst:trlc_rst"), - executable = True, - allow_files = True, - cfg = "exec", - ), - }, - subrules = [subrule_lobster_trlc], -) +load("@trlc//:trlc.bzl", "trlc_requirements_test") +load("//bazel/rules/rules_score/private:requirements.bzl", "score_requirements_rule") # ============================================================================ # Public Macro @@ -143,7 +38,7 @@ _assumptions_of_use = rule( def assumptions_of_use( name, srcs, - requirements = [], + deps = [], ref_package = None, lobster_config = Label("//bazel/rules/rules_score/lobster/config:aou_config"), **kwargs): @@ -157,13 +52,13 @@ def assumptions_of_use( Args: name: The name of the assumptions of use target. Used as the base name for all generated targets. - srcs: List of labels to trlc_requirements targets containing the - Assumptions of Use specifications as defined in the S-CORE - process. RST files containing ``aou_req`` directives are also - accepted and will be converted to TRLC automatically. - requirements: Optional list of labels to feature or component requirements - targets that these Assumptions of Use trace to. Establishes - traceability as defined in the S-CORE process. + srcs: List of TRLC/RST/label sources defining the Assumptions of Use. + Accepts raw ``.trlc`` files, ``.rst`` files containing ``aou_req`` + directives (converted to TRLC automatically), and/or labels to + existing targets that already provide TrlcProviderInfo (e.g. + ``trlc_requirements`` targets). + deps: Optional list of other requirement targets (providing + TrlcProviderInfo) needed for cross-reference parsing. ref_package: Optional TRLC package prefix used for ``derived_from`` cross-references when converting RST sources. lobster_config: Lobster YAML configuration for AoU traceability @@ -174,12 +69,11 @@ def assumptions_of_use( : Main assumptions of use target providing AssumptionsOfUseInfo _test: TRLC validation test for the assumptions of use sources - Example using trlc_requirements targets: + Example using raw TRLC sources directly: ```starlark assumptions_of_use( name = "my_assumptions_of_use", - srcs = [":my_aous_trlc"], - requirements = [":my_feature_requirements"], + srcs = ["assumptions_of_use.trlc"], ) ``` @@ -188,21 +82,20 @@ def assumptions_of_use( assumptions_of_use( name = "my_assumptions_of_use", srcs = ["docs/assumptions_of_use.rst"], - requirements = [":my_feature_requirements"], ) ``` """ - trlc_srcs = rst_srcs_to_trlc(name, srcs, ref_package = ref_package or "") - - _assumptions_of_use( + score_requirements_rule( name = name, - srcs = trlc_srcs, - requirements = requirements, + srcs = srcs, + deps = deps, + req_kind = "aou", lobster_config = lobster_config, + ref_package = ref_package or "", **kwargs ) trlc_requirements_test( name = name + "_test", - reqs = trlc_srcs, + reqs = [":" + name], **kwargs ) diff --git a/bazel/rules/rules_score/private/dependable_element.bzl b/bazel/rules/rules_score/private/dependable_element.bzl index 6536efd8..6c249a88 100644 --- a/bazel/rules/rules_score/private/dependable_element.bzl +++ b/bazel/rules/rules_score/private/dependable_element.bzl @@ -1100,6 +1100,11 @@ def _dependable_element_index_impl(ctx): own_aou_lobster_depset = depset(transitive = own_aou_lobster_files) + own_assumptions_of_use_info = AssumptionsOfUseInfo( + aou_lobster = own_aou_lobster_depset, + name = ctx.label.name, + ) + # Collect forwarded AoU lobster files from deps (received AoUs) received_aou_lobster_files = [] for dep in ctx.attr.processed_deps: @@ -1209,6 +1214,7 @@ def _dependable_element_index_impl(ctx): own_aou_lobster = own_aou_lobster_depset, chain_forwarded_lobster = chain_forwarded_lobster_depset, ), + own_assumptions_of_use_info, OutputGroupInfo(debug = depset(validation_output_files)), ] diff --git a/bazel/rules/rules_score/private/requirements.bzl b/bazel/rules/rules_score/private/requirements.bzl index 4645ba7d..bae9284b 100644 --- a/bazel/rules/rules_score/private/requirements.bzl +++ b/bazel/rules/rules_score/private/requirements.bzl @@ -21,7 +21,7 @@ public-facing macros. load("@lobster//:lobster.bzl", "subrule_lobster_trlc") load("@trlc//:trlc.bzl", "TrlcProviderInfo", "subrule_trlc_image_stage") -load("//bazel/rules/rules_score:providers.bzl", "AssumedSystemRequirementsInfo", "ComponentRequirementsInfo", "FeatureRequirementsInfo", "SphinxSourcesInfo") +load("//bazel/rules/rules_score:providers.bzl", "AssumedSystemRequirementsInfo", "AssumptionsOfUseInfo", "ComponentRequirementsInfo", "FeatureRequirementsInfo", "SphinxSourcesInfo") load("//bazel/rules/rules_score/private:rst_to_trlc.bzl", "rst_to_trlc") # ============================================================================ @@ -99,6 +99,11 @@ def _requirements_impl(ctx): srcs = depset([lobster_file]), name = ctx.label.name, ) + elif ctx.attr.req_kind == "aou": + req_provider = AssumptionsOfUseInfo( + aou_lobster = depset([lobster_file]), + name = ctx.label.name, + ) else: # assumed_system req_provider = AssumedSystemRequirementsInfo( srcs = depset([lobster_file]), @@ -153,7 +158,7 @@ _score_requirements_rule = rule( doc = "Other requirement targets whose TRLC records are needed for cross-reference parsing.", ), "req_kind": attr.string( - values = ["feature", "component", "assumed_system"], + values = ["feature", "component", "assumed_system", "aou"], mandatory = True, doc = "Kind of requirements; determines which domain provider is emitted.", ), @@ -192,16 +197,28 @@ def score_requirements_rule( **kwargs): """Macro wrapper around _score_requirements_rule with RST support. - Any .rst files in srcs are converted to .trlc via rst_to_trlc before - being passed to the underlying rule. .trlc sources are passed through - unchanged. + Each entry in srcs is classified as follows: + - ".rst" files are converted to .trlc via rst_to_trlc and treated as + own sources. + - ".trlc" files are passed through unchanged as own sources. + - Any other label is assumed to already provide TrlcProviderInfo (e.g. + an existing trlc_requirements/assumed_system_requirements/... target) + and is routed to ``deps`` instead, since only raw TRLC files may be + listed in the underlying rule's ``srcs``. Args: ref_package: TRLC package prefix used for derived_from cross-references when converting RST sources (e.g. "AssumedSystemRequirements" for feature requirements that derive from ASR). + + Returns: + List of resolved labels corresponding to srcs (after any .rst-to-.trlc + conversion), in the same order. Useful for callers that need to run + trlc_requirements_test against the same source set. """ trlc_srcs = [] + extra_deps = [] + resolved_srcs = [] for i, src in enumerate(srcs): if type(src) == type("") and src.endswith(".rst"): gen_name = "_{}_rst_gen_{}".format(name, i) @@ -211,15 +228,22 @@ def score_requirements_rule( ref_package = ref_package, ) trlc_srcs.append(":" + gen_name) - else: + resolved_srcs.append(":" + gen_name) + elif type(src) == type("") and src.endswith(".trlc"): trlc_srcs.append(src) + resolved_srcs.append(src) + else: + extra_deps.append(src) + resolved_srcs.append(src) _score_requirements_rule( name = name, srcs = trlc_srcs, - deps = deps, + deps = deps + extra_deps, req_kind = req_kind, lobster_config = lobster_config, spec = spec, **kwargs ) + + return resolved_srcs diff --git a/bazel/rules/rules_score/providers.bzl b/bazel/rules/rules_score/providers.bzl index 0bf78451..043060e8 100644 --- a/bazel/rules/rules_score/providers.bzl +++ b/bazel/rules/rules_score/providers.bzl @@ -123,10 +123,8 @@ AnalysisInfo = provider( AssumptionsOfUseInfo = provider( doc = "Provider for assumptions of use artifacts.", fields = { - "srcs": "Depset of .lobster traceability files collected from all linked requirements targets.", "aou_lobster": "Depset of .lobster traceability files generated from the AoU TRLC sources themselves (used for forwarding to dependees).", - "requirements": "List of FeatureRequirementsInfo or ComponentRequirementsInfo providers this AoU traces to.", - "name": "Name of the assumptions of use target.", + "name": "Name of the assumptions of use (or dependable_element) target.", }, ) diff --git a/bazel/rules/rules_score/test/BUILD b/bazel/rules/rules_score/test/BUILD index e00a0c6d..506f7c28 100644 --- a/bazel/rules/rules_score/test/BUILD +++ b/bazel/rules/rules_score/test/BUILD @@ -210,7 +210,6 @@ component_requirements( assumptions_of_use( name = "aous", srcs = ["fixtures/seooc_test/assumptions_of_use.rst"], - requirements = [":feat_req"], ) # - Architecture Design: wp__component_arch @@ -719,7 +718,6 @@ component_requirements( assumptions_of_use( name = "aous_rst", srcs = ["fixtures/rst_requirements/assumptions_of_use.rst"], - requirements = [":feat_req_rst"], ) asr_rst_output_test( diff --git a/bazel/rules/rules_score/test/requirements_rst_test.bzl b/bazel/rules/rules_score/test/requirements_rst_test.bzl index 4de10ab4..c78a7a8a 100644 --- a/bazel/rules/rules_score/test/requirements_rst_test.bzl +++ b/bazel/rules/rules_score/test/requirements_rst_test.bzl @@ -210,8 +210,8 @@ def _aous_rst_provider_test_impl(ctx): ) asserts.true( env, - info.srcs != None, - "AssumptionsOfUseInfo should have a srcs field", + info.aou_lobster != None, + "AssumptionsOfUseInfo should have an aou_lobster field", ) return analysistest.end(env)