diff --git a/MODULE.bazel b/MODULE.bazel index e900e735..188ba71b 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -248,7 +248,7 @@ use_repo(pip, "manual_analysis_deps") bazel_dep(name = "trlc", version = "0.0.0") git_override( module_name = "trlc", - commit = "1872957ae981ae632a0ec6eafb5b8d3aa44bdb86", + commit = "8bdcb1fe6d5af97b69a293673815592371bdbb20", remote = "https://github.com/bmw-software-engineering/trlc.git", ) diff --git a/bazel/rules/rules_score/examples/seooc/docs/requirements/BUILD b/bazel/rules/rules_score/examples/seooc/docs/requirements/BUILD index 31448633..9acf5946 100644 --- a/bazel/rules/rules_score/examples/seooc/docs/requirements/BUILD +++ b/bazel/rules/rules_score/examples/seooc/docs/requirements/BUILD @@ -11,99 +11,60 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -load("@trlc//:trlc.bzl", "trlc_requirements", "trlc_requirements_test") -load("//bazel/rules/rules_score:rules_score.bzl", "component_requirements", "feature_requirements") +load("//bazel/rules/rules_score:rules_score.bzl", "assumed_system_requirements", "component_requirements", "feature_requirements") load("//validation/ai_checker:ai_checker.bzl", "trlc_requirements_ai_test") -trlc_requirements( +assumed_system_requirements( name = "assumed_system_requirements", srcs = [ "assumed_system_requirements.trlc", ], - spec = [ - "//bazel/rules/rules_score/trlc/config:score_requirements_model", - ], visibility = ["//visibility:public"], ) -trlc_requirements_test( - name = "assumed_system_requirements_test", - reqs = [ - ":assumed_system_requirements", - ], - visibility = ["//visibility:public"], -) - -trlc_requirements( - name = "feature_requirements_trlc", +feature_requirements( + name = "feature_requirements", srcs = [ "feature_requirements.trlc", ], - spec = [ - "//bazel/rules/rules_score/trlc/config:score_requirements_model", - ], visibility = ["//visibility:public"], deps = [ ":assumed_system_requirements", ], ) -feature_requirements( - name = "feature_requirements", - srcs = [":feature_requirements_trlc"], - visibility = ["//visibility:public"], -) - trlc_requirements_ai_test( name = "feature_requirements_ai_test", - reqs = [":feature_requirements_trlc"], + reqs = [":feature_requirements"], tags = ["manual"], ) -trlc_requirements( - name = "component_requirements_trlc", +component_requirements( + name = "component_requirements", srcs = [ "component_requirements.trlc", ], - spec = [ - "//bazel/rules/rules_score/trlc/config:score_requirements_model", - ], visibility = ["//visibility:public"], deps = [ ":assumed_system_requirements", - ":feature_requirements_trlc", + ":feature_requirements", ], ) component_requirements( - name = "component_requirements", - srcs = [":component_requirements_trlc"], - visibility = ["//visibility:public"], -) - -trlc_requirements( - name = "component_requirements_extra_trlc", + name = "component_requirements_extra", srcs = [ "component_requirements_extra.trlc", ], - spec = [ - "//bazel/rules/rules_score/trlc/config:score_requirements_model", - ], visibility = ["//visibility:public"], deps = [ ":assumed_system_requirements", - ":feature_requirements_trlc", + ":feature_requirements", ], ) -component_requirements( - name = "component_requirements_extra", - srcs = [":component_requirements_extra_trlc"], - visibility = ["//visibility:public"], -) - trlc_requirements_ai_test( name = "component_requirements_ai_test", - reqs = [":component_requirements_trlc"], + reqs = [":component_requirements"], tags = ["manual"], ) diff --git a/bazel/rules/rules_score/lobster/config/lobster_comp_req.yaml b/bazel/rules/rules_score/lobster/config/lobster_comp_req.yaml index 902a95f4..0356a672 100644 --- a/bazel/rules/rules_score/lobster/config/lobster_comp_req.yaml +++ b/bazel/rules/rules_score/lobster/config/lobster_comp_req.yaml @@ -22,6 +22,7 @@ conversion-rules: - package: ScoreReq record-type: CompReq namespace: req + version-field: version description-fields: description tags: - derived_from diff --git a/bazel/rules/rules_score/private/assumed_system_requirements.bzl b/bazel/rules/rules_score/private/assumed_system_requirements.bzl new file mode 100644 index 00000000..c0c5c3cf --- /dev/null +++ b/bazel/rules/rules_score/private/assumed_system_requirements.bzl @@ -0,0 +1,91 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +""" +Assumed System Requirements build rules for S-CORE projects. + +Assumed System Requirements (ASR) are system-level requirements that represent +the assumptions a Safety Element out of Context (SEooC) makes about the system +it will be integrated into. Feature requirements are derived from them. +""" + +load("@trlc//:trlc.bzl", "trlc_requirements_test") +load("//bazel/rules/rules_score/private:requirements.bzl", "score_requirements_rule") + +# ============================================================================ +# Public Macro +# ============================================================================ + +def assumed_system_requirements( + name, + srcs, + deps = [], + spec = Label("//bazel/rules/rules_score/trlc/config:score_requirements_model"), + ref_package = "", + visibility = None): + """Define Assumed System Requirements following S-CORE process guidelines. + + Creates a target providing AssumedSystemRequirementsInfo, TrlcProviderInfo, + and SphinxSourcesInfo, plus a validation test target ``_test``. + + Because this target emits TrlcProviderInfo, downstream requirement targets + (e.g. feature_requirements) can reference it directly in their ``deps`` + without any intermediate trlc_requirements wrapper. + + Args: + name: The name of the target. + srcs: List of .trlc source files containing AssumedSystemReq records as + defined in the S-CORE requirements model. + deps: Optional list of requirement targets whose TRLC records are needed + for cross-reference parsing. These targets must provide + TrlcProviderInfo. Typically empty for top-level system requirements. + spec: Optional TRLC specification target providing RSL type definitions. + Defaults to the S-CORE requirements model + (``@score_tooling//bazel/rules/rules_score/trlc/config:score_requirements_model``). + Override this when using a custom requirements model. + visibility: Bazel visibility specification for the generated targets. + + Generated Targets: + : Main target providing AssumedSystemRequirementsInfo, + TrlcProviderInfo, and SphinxSourcesInfo. + _test: TRLC validation test (runs ``trlc --verify``). + + Example: + ```starlark + assumed_system_requirements( + name = "asr", + srcs = ["assumed_system_requirements.trlc"], + ) + + feature_requirements( + name = "feat_req", + srcs = ["feature_requirements.trlc"], + deps = [":asr"], + ) + ``` + """ + score_requirements_rule( + name = name, + srcs = srcs, + deps = deps, + req_kind = "assumed_system", + lobster_config = Label("//bazel/rules/rules_score/lobster/config:assumed_system_requirement"), + spec = spec, + ref_package = ref_package, + visibility = visibility, + ) + trlc_requirements_test( + name = name + "_test", + reqs = [":" + name], + visibility = visibility, + ) diff --git a/bazel/rules/rules_score/private/component_requirements.bzl b/bazel/rules/rules_score/private/component_requirements.bzl index e0fddfed..e0f310b5 100644 --- a/bazel/rules/rules_score/private/component_requirements.bzl +++ b/bazel/rules/rules_score/private/component_requirements.bzl @@ -14,67 +14,12 @@ """ Component Requirements build rules for S-CORE projects. -This module provides macros and rules for defining component requirements -following S-CORE process guidelines. Component requirements are derived from -feature requirements and define the specific requirements for a software component. +Component requirements are derived from feature requirements and define the +specific requirements for a software component. """ -load("//bazel/rules/rules_score:providers.bzl", "ComponentRequirementsInfo", "SphinxSourcesInfo") - -# ComponentRequirementsInfo and FeatureRequirementsInfo are re-exported from providers.bzl for backward compatibility. - -# ============================================================================ -# Private Rule Implementation -# ============================================================================ - -def _component_requirements_impl(ctx): - """Implementation for component_requirements rule. - - Collects component requirements source files and links them to their - parent feature requirements through providers. - - Args: - ctx: Rule context - - Returns: - List of providers including DefaultInfo and ComponentRequirementsInfo - """ - srcs = depset(ctx.files.srcs) - - # Collect feature requirements providers - feature_reqs = [] - - # Collect transitive sphinx sources from feature requirements - transitive = [srcs] - - return [ - DefaultInfo(files = srcs), - ComponentRequirementsInfo( - srcs = srcs, - name = ctx.label.name, - ), - SphinxSourcesInfo( - srcs = srcs, - deps = depset(transitive = transitive), - ancillary = depset(), - ), - ] - -# ============================================================================ -# Rule Definition -# ============================================================================ - -_component_requirements = rule( - implementation = _component_requirements_impl, - doc = "Collects component requirements documents with traceability to feature requirements", - attrs = { - "srcs": attr.label_list( - allow_files = [".rst", ".md", ".trlc"], - mandatory = True, - doc = "Source files containing component requirements specifications", - ), - }, -) +load("@trlc//:trlc.bzl", "trlc_requirements_test") +load("//bazel/rules/rules_score/private:requirements.bzl", "score_requirements_rule") # ============================================================================ # Public Macro @@ -83,35 +28,58 @@ _component_requirements = rule( def component_requirements( name, srcs, + deps = [], + spec = Label("//bazel/rules/rules_score/trlc/config:score_requirements_model"), + ref_package = "", visibility = None): """Define component requirements following S-CORE process guidelines. - Component requirements are derived from feature requirements and define - the specific functional and safety requirements for a software component. - They establish traceability from high-level features to component-level - specifications. + Creates a target providing ComponentRequirementsInfo, TrlcProviderInfo, + and SphinxSourcesInfo, plus a validation test target ``_test``. + + Because this target emits TrlcProviderInfo, downstream targets can + reference it directly in their ``deps`` without any intermediate + trlc_requirements wrapper. Args: - name: The name of the component requirements target. Used as the base - name for all generated targets. - srcs: List of labels to .rst, .md, or .trlc files containing the - component requirements specifications as defined in the S-CORE - process. + name: The name of the target. + srcs: List of .trlc source files containing CompReq records as defined + in the S-CORE requirements model. + deps: Optional list of requirement targets (e.g. assumed_system_requirements, + feature_requirements) whose TRLC records are needed for cross-reference + parsing. These targets must provide TrlcProviderInfo. + spec: Optional TRLC specification target providing RSL type definitions. + Defaults to the S-CORE requirements model + (``@score_tooling//bazel/rules/rules_score/trlc/config:score_requirements_model``). + Override this when using a custom requirements model. visibility: Bazel visibility specification for the generated targets. Generated Targets: - : Main component requirements target providing ComponentRequirementsInfo + : Main target providing ComponentRequirementsInfo, TrlcProviderInfo, + and SphinxSourcesInfo. + _test: TRLC validation test (runs ``trlc --verify``). Example: ```starlark component_requirements( - name = "my_component_requirements", - srcs = ["component_requirements.rst"], + name = "comp_req", + srcs = ["component_requirements.trlc"], + deps = [":asr", ":feat_req"], ) ``` """ - _component_requirements( + score_requirements_rule( name = name, srcs = srcs, + deps = deps, + req_kind = "component", + lobster_config = Label("//bazel/rules/rules_score/lobster/config:component_requirement"), + spec = spec, + ref_package = ref_package, + visibility = visibility, + ) + trlc_requirements_test( + name = name + "_test", + reqs = [":" + name], visibility = visibility, ) diff --git a/bazel/rules/rules_score/private/feature_requirements.bzl b/bazel/rules/rules_score/private/feature_requirements.bzl index 95cabb90..8f8dba71 100644 --- a/bazel/rules/rules_score/private/feature_requirements.bzl +++ b/bazel/rules/rules_score/private/feature_requirements.bzl @@ -14,61 +14,13 @@ """ Feature Requirements build rules for S-CORE projects. -This module provides macros and rules for defining feature requirements -following S-CORE process guidelines. Feature requirements describe the -high-level features that a software component must implement. +Feature requirements describe the high-level features that a software component +must implement. They are derived from Assumed System Requirements and feed into +Component Requirements. """ -load("//bazel/rules/rules_score:providers.bzl", "FeatureRequirementsInfo", "SphinxSourcesInfo") - -# FeatureRequirementsInfo is re-exported from providers.bzl for backward compatibility. - -# ============================================================================ -# Private Rule Implementation -# ============================================================================ - -def _feature_requirements_impl(ctx): - """Implementation for feature_requirements rule. - - Collects feature requirements source files and provides them through - the FeatureRequirementsInfo provider. - - Args: - ctx: Rule context - - Returns: - List of providers including DefaultInfo and FeatureRequirementsInfo - """ - srcs = depset(ctx.files.srcs) - - return [ - DefaultInfo(files = srcs), - FeatureRequirementsInfo( - srcs = srcs, - name = ctx.label.name, - ), - SphinxSourcesInfo( - srcs = srcs, - deps = srcs, - ancillary = depset(), - ), - ] - -# ============================================================================ -# Rule Definition -# ============================================================================ - -_feature_requirements = rule( - implementation = _feature_requirements_impl, - doc = "Collects feature requirements documents for S-CORE process compliance", - attrs = { - "srcs": attr.label_list( - allow_files = [".rst", ".md", ".trlc"], - mandatory = True, - doc = "Source files containing feature requirements specifications", - ), - }, -) +load("@trlc//:trlc.bzl", "trlc_requirements_test") +load("//bazel/rules/rules_score/private:requirements.bzl", "score_requirements_rule") # ============================================================================ # Public Macro @@ -77,34 +29,63 @@ _feature_requirements = rule( def feature_requirements( name, srcs, + deps = [], + spec = Label("//bazel/rules/rules_score/trlc/config:score_requirements_model"), + ref_package = "", visibility = None): """Define feature requirements following S-CORE process guidelines. - Feature requirements describe the high-level features and capabilities - that a software component must implement. They serve as the top-level - requirements that drive component-level requirements. + Creates a target providing FeatureRequirementsInfo, TrlcProviderInfo, + and SphinxSourcesInfo, plus a validation test target ``_test``. + + Because this target emits TrlcProviderInfo, downstream requirement targets + (e.g. component_requirements) can reference it directly in their ``deps`` + without any intermediate trlc_requirements wrapper. Args: - name: The name of the feature requirements target. Used as the base - name for all generated targets. - srcs: List of labels to .rst, .md, or .trlc files containing the - feature requirements specifications as defined in the S-CORE - process. + name: The name of the target. + srcs: List of .trlc source files containing FeatReq records as defined + in the S-CORE requirements model. + deps: Optional list of requirement targets (e.g. assumed_system_requirements) + whose TRLC records are needed for cross-reference parsing. These + targets must provide TrlcProviderInfo. + spec: Optional TRLC specification target providing RSL type definitions. + Defaults to the S-CORE requirements model + (``@score_tooling//bazel/rules/rules_score/trlc/config:score_requirements_model``). + Override this when using a custom requirements model. visibility: Bazel visibility specification for the generated targets. Generated Targets: - : Main feature requirements target providing FeatureRequirementsInfo + : Main target providing FeatureRequirementsInfo, TrlcProviderInfo, + and SphinxSourcesInfo. + _test: TRLC validation test (runs ``trlc --verify``). Example: ```starlark + assumed_system_requirements( + name = "asr", + srcs = ["assumed_system_requirements.trlc"], + ) + feature_requirements( - name = "my_feature_requirements", - srcs = ["feature_requirements.rst"], + name = "feat_req", + srcs = ["feature_requirements.trlc"], + deps = [":asr"], ) ``` """ - _feature_requirements( + score_requirements_rule( name = name, srcs = srcs, + deps = deps, + req_kind = "feature", + lobster_config = Label("//bazel/rules/rules_score/lobster/config:feature_requirement"), + spec = spec, + ref_package = ref_package, + visibility = visibility, + ) + trlc_requirements_test( + name = name + "_test", + reqs = [":" + name], visibility = visibility, ) diff --git a/bazel/rules/rules_score/private/requirements.bzl b/bazel/rules/rules_score/private/requirements.bzl index f7889897..f887e88d 100644 --- a/bazel/rules/rules_score/private/requirements.bzl +++ b/bazel/rules/rules_score/private/requirements.bzl @@ -12,299 +12,207 @@ # ******************************************************************************* """ -Requirements build rules for S-CORE projects. +Shared internal requirements rule for S-CORE projects. -This module provides macros and rules for defining requirements at any level -(feature, component, etc.) following S-CORE process guidelines. +Not intended for direct use. See feature_requirements.bzl, +component_requirements.bzl, and assumed_system_requirements.bzl for the +public-facing macros. """ load("@lobster//:lobster.bzl", "subrule_lobster_trlc") -load("@trlc//:trlc.bzl", "TrlcProviderInfo", "trlc_requirements", "trlc_requirements_test") +load("@trlc//:trlc.bzl", "TrlcProviderInfo") load("//bazel/rules/rules_score:providers.bzl", "AssumedSystemRequirementsInfo", "ComponentRequirementsInfo", "FeatureRequirementsInfo", "SphinxSourcesInfo") -load("//bazel/rules/rules_score/private:rst_to_trlc.bzl", "rst_srcs_to_trlc") +load("//bazel/rules/rules_score/private:rst_to_trlc.bzl", "rst_to_trlc") # ============================================================================ # Private Rule Implementation # ============================================================================ def _requirements_impl(ctx): - """Implementation for requirements rule. + """Shared implementation for all requirement kinds. - Collects requirement source files, renders TRLC to RST, - and extracts lobster traceability items. Args: - ctx: Rule context + ctx: Rule context. Returns: - List of providers including DefaultInfo, FeatureRequirementsInfo or ComponentRequirementsInfo, - and SphinxSourcesInfo + [DefaultInfo, TrlcProviderInfo, RequirementsInfo, SphinxSourcesInfo] """ - 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) - - lobster_trlc_file, _lobster_trlc = subrule_lobster_trlc(ctx.files.srcs, ctx.file.lobster_config) + # ------------------------------------------------------------------------- + # Assemble TrlcProviderInfo + # ------------------------------------------------------------------------- + transitive_spec = [] + transitive_reqs = [] + for dep in ctx.attr.deps: + trlc_info = dep[TrlcProviderInfo] + transitive_spec.append(trlc_info.spec) + transitive_reqs.append(trlc_info.reqs) + transitive_reqs.append(trlc_info.deps) + + own_spec_files = ctx.attr.spec[DefaultInfo].files + spec_depset = depset(transitive = [own_spec_files] + transitive_spec) + deps_depset = depset(transitive = transitive_reqs) + + # All files needed for TRLC parsing: own sources + spec RSL + transitive deps. + # This matches DefaultInfo.files of an equivalent trlc_requirements target so + # that trlc_requirements_test(reqs=[":this_target"]) works out of the box. + all_trlc_files = depset(ctx.files.srcs, transitive = [spec_depset, deps_depset]) + + # ------------------------------------------------------------------------- + # Render TRLC → RST for Sphinx documentation. + # --source-files: own .trlc files — rendered AND registered for parsing. + # --dep-files: spec .rsl + transitive .trlc deps — parsed but not rendered. + # ------------------------------------------------------------------------- + rendered_file = ctx.actions.declare_file("{}.rst".format(ctx.attr.name)) + dep_files_depset = depset(transitive = [spec_depset, deps_depset]) + + render_args = ctx.actions.args() + render_args.add("--output", rendered_file.path) + render_args.add_all("--source-files", ctx.files.srcs) + render_args.add_all("--dep-files", dep_files_depset) + + ctx.actions.run( + inputs = all_trlc_files, + outputs = [rendered_file], + executable = ctx.executable._renderer, + arguments = [render_args], + progress_message = "Rendering TRLC to RST for %s" % ctx.label, + mnemonic = "TrlcToRst", + ) - providers = [DefaultInfo(files = all_srcs)] + # ------------------------------------------------------------------------- + # Lobster traceability extraction. + # ------------------------------------------------------------------------- + lobster_file, _ = subrule_lobster_trlc(all_trlc_files.to_list(), ctx.file.lobster_config) + # ------------------------------------------------------------------------- + # Build the kind-specific domain provider. + # ------------------------------------------------------------------------- if ctx.attr.req_kind == "feature": - providers.append(FeatureRequirementsInfo( - srcs = depset([lobster_trlc_file]), + req_provider = FeatureRequirementsInfo( + srcs = depset([lobster_file]), name = ctx.label.name, - )) - - # Propagate AssumedSystemRequirementsInfo from deps so the parent - # dependable_element/component can include assumed system requirement - # lobster files without listing them separately. - asr_srcs = [ - dep[AssumedSystemRequirementsInfo].srcs - for dep in ctx.attr.deps - if AssumedSystemRequirementsInfo in dep - ] - if asr_srcs: - providers.append(AssumedSystemRequirementsInfo( - srcs = depset(transitive = asr_srcs), - name = ctx.label.name, - )) - elif ctx.attr.req_kind == "assumed_system": - providers.append(AssumedSystemRequirementsInfo( - srcs = depset([lobster_trlc_file]), + ) + elif ctx.attr.req_kind == "component": + req_provider = ComponentRequirementsInfo( + srcs = depset([lobster_file]), name = ctx.label.name, - )) - else: # component - providers.append(ComponentRequirementsInfo( - srcs = depset([lobster_trlc_file]), + ) + else: # assumed_system + req_provider = AssumedSystemRequirementsInfo( + srcs = depset([lobster_file]), name = ctx.label.name, - )) + ) + + sphinx_srcs = depset([rendered_file]) - # Propagate FeatureRequirementsInfo from deps so the parent component - # can include feature requirement lobster files in its traceability - # config without listing them separately. - feat_req_srcs = [ - dep[FeatureRequirementsInfo].srcs - for dep in ctx.attr.deps - if FeatureRequirementsInfo in dep - ] - if feat_req_srcs: - providers.append(FeatureRequirementsInfo( - srcs = depset(transitive = feat_req_srcs), - name = ctx.label.name, - )) + transitive_sphinx = [sphinx_srcs] + for dep in ctx.attr.deps: + if SphinxSourcesInfo in dep: + transitive_sphinx.append(dep[SphinxSourcesInfo].deps) - providers.append(SphinxSourcesInfo( - srcs = all_srcs, - deps = all_srcs, - ancillary = depset(), - )) - return providers + return [ + DefaultInfo(files = all_trlc_files), + TrlcProviderInfo( + spec = spec_depset, + reqs = depset(ctx.files.srcs), + deps = deps_depset, + ), + req_provider, + SphinxSourcesInfo( + srcs = sphinx_srcs, + deps = depset(transitive = transitive_sphinx), + ancillary = depset(), + ), + ] # ============================================================================ # Rule Definition # ============================================================================ -_requirements = rule( +_score_requirements_rule = rule( implementation = _requirements_impl, - doc = "Collects requirements documents for S-CORE process compliance", + doc = """Shared internal rule for all S-CORE requirement kinds. + + Accepts raw .trlc source files and emits TrlcProviderInfo so that + downstream requirement targets can list this target in their deps + directly, without needing an intermediate trlc_requirements wrapper. + """, attrs = { "srcs": attr.label_list( - providers = [TrlcProviderInfo], + allow_files = [".trlc"], mandatory = True, - doc = "TRLC requirement targets providing TrlcProviderInfo", + doc = "TRLC source files containing requirement records.", ), - "lobster_config": attr.label( - allow_single_file = True, - mandatory = True, - doc = "Lobster YAML configuration file for traceability extraction", + "deps": attr.label_list( + providers = [TrlcProviderInfo], + default = [], + doc = "Other requirement targets whose TRLC records are needed for cross-reference parsing.", ), "req_kind": attr.string( values = ["feature", "component", "assumed_system"], mandatory = True, - doc = "Kind of requirements: 'feature', 'component', or 'assumed_system'.", + doc = "Kind of requirements; determines which domain provider is emitted.", ), - "deps": attr.label_list( - providers = [[FeatureRequirementsInfo], [AssumedSystemRequirementsInfo]], - doc = "Requirements targets this target derives from. " + - "For 'component' req_kind: feature_requirements targets whose lobster files " + - "are propagated as FeatureRequirementsInfo. " + - "For 'feature' req_kind: assumed_system_requirements targets whose lobster " + - "files are propagated as AssumedSystemRequirementsInfo.", + "lobster_config": attr.label( + allow_single_file = True, + mandatory = True, + doc = "Lobster YAML configuration file for traceability extraction.", + ), + "spec": attr.label( + default = Label("//bazel/rules/rules_score/trlc/config:score_requirements_model"), + doc = "TRLC specification target providing the RSL files that define the requirement types. Defaults to the S-CORE requirements model.", ), "_renderer": attr.label( default = Label("@trlc//tools/trlc_rst:trlc_rst"), executable = True, - allow_files = True, cfg = "exec", + doc = "TRLC-to-RST renderer tool.", ), }, subrules = [subrule_lobster_trlc], ) -# ============================================================================ -# Public Macros -# ============================================================================ -def _create_trlc_aliases(name, srcs, visibility): - """Expose stable public aliases for generated trlc_requirements targets. - - For each RST file in *srcs*, a named alias is created so that downstream - requirement macros can reference the generated trlc_requirements target via - ``deps`` for cross-package TRLC validation without knowing internal names. - When a single RST file is given the alias is ``_trlc``; for multiple - RST files the per-source index is appended (``_trlc_0``, …). - - Args: - name: Base name used by the enclosing macro (same as passed to - rst_srcs_to_trlc). - srcs: Original srcs list passed to the enclosing macro. - visibility: Bazel visibility to apply to the generated aliases. - """ - rst_count = len([s for s in srcs if s.endswith(".rst")]) - rst_index = 0 - for i, src in enumerate(srcs): - if src.endswith(".rst"): - alias_name = name + "_trlc" if rst_count == 1 else "{}_trlc_{}".format(name, rst_index) - native.alias( - name = alias_name, - actual = ":_{}_trlc_{}".format(name, i), - visibility = visibility, - ) - rst_index += 1 - -def _score_requirements(name, srcs, deps, ref_package, visibility, req_kind, req_deps = []): - """Shared implementation for feature_requirements and component_requirements. - - Args: - name: Target name. - srcs: Mixed list of trlc_requirements labels or RST file paths. - deps: trlc_requirements labels used as parsing dependencies for RST files. - ref_package: TRLC package prefix for derived_from cross-references. - visibility: Bazel visibility specification. - req_kind: Either "feature" or "component". - req_deps: Requirements targets for provider propagation (e.g. assumed_system_requirements - targets for a feature_requirements target). - """ - trlc_srcs = rst_srcs_to_trlc(name, srcs, deps = deps, ref_package = ref_package or "") - _requirements( - name = name, - srcs = trlc_srcs, - deps = req_deps, - lobster_config = Label("//bazel/rules/rules_score/lobster/config:{}_requirement".format(req_kind)), - req_kind = req_kind, - visibility = visibility, - ) - trlc_requirements_test( - name = name + "_test", - reqs = trlc_srcs, - visibility = visibility, - ) - _create_trlc_aliases(name, srcs, visibility) - -def assumed_system_requirements( +def score_requirements_rule( name, srcs, + req_kind, + lobster_config, deps = [], - ref_package = None, + spec = Label("//bazel/rules/rules_score/trlc/config:score_requirements_model"), + ref_package = "", visibility = None): - """Define Assumed System Requirements following S-CORE process guidelines. - - Creates an assumed_system_requirements target (providing AssumedSystemRequirementsInfo - and SphinxSourcesInfo) and a validation test target named *name*_test. - - Args: - name: The name of the target. - srcs: List of trlc_requirements labels (providing TrlcProviderInfo) - or RST file paths containing ``asr_req`` directives. - RST files are converted to TRLC automatically. - deps: Optional list of trlc_requirements labels to include as - parsing dependencies. Only used when RST files are present in *srcs*. - ref_package: TRLC package prefix for derived_from cross-references - when converting RST sources. - visibility: Bazel visibility specification. - """ - _score_requirements(name, srcs, deps, ref_package, visibility, "assumed_system") + """Macro wrapper around _score_requirements_rule with RST support. -def feature_requirements( - name, - srcs, - deps = [], - req_deps = [], - ref_package = None, - visibility = None): - """Define feature requirements following S-CORE process guidelines. + 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. Args: - name: The name of the target. - srcs: List of trlc_requirements labels (providing TrlcProviderInfo) - or RST file paths containing ``feat_req`` directives. - RST files are converted to TRLC automatically. - deps: Optional list of trlc_requirements labels to include as - parsing dependencies. Only used when RST files are present in *srcs*. - req_deps: Optional list of assumed_system_requirements targets whose - AssumedSystemRequirementsInfo is propagated alongside this target's - FeatureRequirementsInfo so that consumers can resolve assumed system - requirement references without listing them separately. - ref_package: TRLC package prefix for derived_from cross-references - when converting RST sources. - visibility: Bazel visibility specification. + 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). """ - _score_requirements(name, srcs, deps, ref_package, visibility, "feature", req_deps = req_deps) - -def component_requirements( - name, - srcs = [], - deps = [], - trlc_deps = [], - ref_package = None, - visibility = None): - """Define component requirements following S-CORE process guidelines. + trlc_srcs = [] + for i, src in enumerate(srcs): + if type(src) == type("") and src.endswith(".rst"): + gen_name = "_{}_rst_gen_{}".format(name, i) + rst_to_trlc( + name = gen_name, + srcs = [src], + ref_package = ref_package, + ) + trlc_srcs.append(":" + gen_name) + else: + trlc_srcs.append(src) - Args: - name: The name of the target. - srcs: List of trlc_requirements labels (providing TrlcProviderInfo) or - RST file paths containing ``comp_req`` directives. - RST files are converted to TRLC automatically. - deps: Optional list of feature_requirements targets whose lobster files are - propagated alongside this target's ComponentRequirementsInfo, so that - a parent component rule can resolve derived_from references without - having to list the feature requirements separately. - trlc_deps: Optional list of trlc_requirements labels to include as - parsing dependencies when RST files are present in *srcs*. - ref_package: TRLC package prefix for derived_from cross-references - when converting RST sources. - visibility: Bazel visibility specification. - """ - trlc_srcs = rst_srcs_to_trlc(name, srcs, deps = trlc_deps, ref_package = ref_package or "") - _requirements( + _score_requirements_rule( name = name, srcs = trlc_srcs, deps = deps, - lobster_config = Label("//bazel/rules/rules_score/lobster/config:component_requirement"), - req_kind = "component", - visibility = visibility, - ) - - trlc_requirements_test( - name = name + "_test", - reqs = trlc_srcs, + req_kind = req_kind, + lobster_config = lobster_config, + spec = spec, visibility = visibility, ) - _create_trlc_aliases(name, srcs, visibility) diff --git a/bazel/rules/rules_score/rules_score.bzl b/bazel/rules/rules_score/rules_score.bzl index 7cc217c7..3df157f7 100644 --- a/bazel/rules/rules_score/rules_score.bzl +++ b/bazel/rules/rules_score/rules_score.bzl @@ -21,6 +21,10 @@ load( "//bazel/rules/rules_score/private:architectural_design.bzl", _architectural_design = "architectural_design", ) +load( + "//bazel/rules/rules_score/private:assumed_system_requirements.bzl", + _assumed_system_requirements = "assumed_system_requirements", +) load( "//bazel/rules/rules_score/private:assumptions_of_use.bzl", _assumptions_of_use = "assumptions_of_use", @@ -29,6 +33,10 @@ load( "//bazel/rules/rules_score/private:component.bzl", _component = "component", ) +load( + "//bazel/rules/rules_score/private:component_requirements.bzl", + _component_requirements = "component_requirements", +) load( "//bazel/rules/rules_score/private:dependability_analysis.bzl", _dependability_analysis = "dependability_analysis", @@ -37,6 +45,10 @@ load( "//bazel/rules/rules_score/private:dependable_element.bzl", _dependable_element = "dependable_element", ) +load( + "//bazel/rules/rules_score/private:feature_requirements.bzl", + _feature_requirements = "feature_requirements", +) load( "//bazel/rules/rules_score/private:filter_execpath.bzl", _filter_execpath = "filter_execpath", @@ -45,12 +57,6 @@ load( "//bazel/rules/rules_score/private:fmea.bzl", _fmea = "fmea", ) -load( - "//bazel/rules/rules_score/private:requirements.bzl", - _assumed_system_requirements = "assumed_system_requirements", - _component_requirements = "component_requirements", - _feature_requirements = "feature_requirements", -) load( "//bazel/rules/rules_score/private:sphinx_module.bzl", _sphinx_module = "sphinx_module", diff --git a/bazel/rules/rules_score/test/BUILD b/bazel/rules/rules_score/test/BUILD index d1801668..e1624e2a 100644 --- a/bazel/rules/rules_score/test/BUILD +++ b/bazel/rules/rules_score/test/BUILD @@ -125,40 +125,27 @@ sphinx_module( # Tests the score_component macro with S-CORE process artifacts # - Feature Requirements: wp__requirements_feat -trlc_requirements( +assumed_system_requirements( name = "asr_trlc", srcs = ["fixtures/seooc_test/assumed_system_requirements.trlc"], - spec = ["@score_tooling//bazel/rules/rules_score/trlc/config:score_requirements_model"], -) - -trlc_requirements( - name = "feat_req_trlc", - srcs = ["fixtures/seooc_test/feature_requirements.trlc"], - spec = ["@score_tooling//bazel/rules/rules_score/trlc/config:score_requirements_model"], - deps = [":asr_trlc"], ) feature_requirements( name = "feat_req", - srcs = [":feat_req_trlc"], + srcs = ["fixtures/seooc_test/feature_requirements.trlc"], + deps = [":asr_trlc"], ) # - Component Requirements: wp__requirements_comp -trlc_requirements( - name = "comp_req_trlc", +component_requirements( + name = "comp_req", srcs = ["fixtures/seooc_test/component_requirements.trlc"], - spec = ["@score_tooling//bazel/rules/rules_score/trlc/config:score_requirements_model"], deps = [ ":asr_trlc", - ":feat_req_trlc", + ":feat_req", ], ) -component_requirements( - name = "comp_req", - srcs = [":comp_req_trlc"], -) - # - Assumptions of Use: wp__requirements_comp_aou assumptions_of_use( name = "aous", @@ -640,13 +627,17 @@ feature_requirements( name = "feat_req_rst", srcs = ["fixtures/rst_requirements/feature_requirements.rst"], ref_package = "AssumedSystemRequirements", - deps = [":asr_rst_trlc"], + deps = [":asr_rst"], ) # Fixture: component_requirements from RST component_requirements( name = "comp_req_rst", srcs = ["fixtures/rst_requirements/component_requirements.rst"], + deps = [ + ":asr_rst", + ":feat_req_rst", + ], ) # Fixture: assumptions_of_use from RST diff --git a/bazel/rules/rules_score/test/requirements_rst_test.bzl b/bazel/rules/rules_score/test/requirements_rst_test.bzl index 5e6c8fde..4de10ab4 100644 --- a/bazel/rules/rules_score/test/requirements_rst_test.bzl +++ b/bazel/rules/rules_score/test/requirements_rst_test.bzl @@ -40,17 +40,17 @@ def _asr_rst_output_test_impl(ctx): env = analysistest.begin(ctx) target_under_test = analysistest.target_under_test(env) - files = target_under_test[DefaultInfo].files.to_list() asserts.true( env, - len(files) > 0, - "assumed_system_requirements from RST should produce output files", + SphinxSourcesInfo in target_under_test, + "assumed_system_requirements should provide SphinxSourcesInfo", ) - rst_files = [f for f in files if f.basename.endswith(".rst")] + sphinx_files = target_under_test[SphinxSourcesInfo].srcs.to_list() + rst_files = [f for f in sphinx_files if f.basename.endswith(".rst")] asserts.true( env, len(rst_files) > 0, - "assumed_system_requirements from RST should produce a rendered .rst file", + "assumed_system_requirements should produce a rendered .rst file in SphinxSourcesInfo.srcs", ) return analysistest.end(env) diff --git a/bazel/rules/rules_score/test/seooc_test.bzl b/bazel/rules/rules_score/test/seooc_test.bzl index 3d8d0a90..689a62f1 100644 --- a/bazel/rules/rules_score/test/seooc_test.bzl +++ b/bazel/rules/rules_score/test/seooc_test.bzl @@ -61,7 +61,7 @@ def _seooc_artifacts_copied_test_impl(ctx): # Expected artifact basenames - these come from the SphinxSourcesInfo providers # and are filtered to only include .rst/.md files for the index expected_artifacts = [ - "feat_req_feat_req_trlc.rst", # from feature requirements + "feat_req.rst", # from feature requirements (rendered TRLC → RST) "dfa.rst", # from :dependability_analysis_target ] diff --git a/bazel/rules/rules_score/trlc/config/score_requirements_model.rsl b/bazel/rules/rules_score/trlc/config/score_requirements_model.rsl index c8fc4868..ec07d2f3 100644 --- a/bazel/rules/rules_score/trlc/config/score_requirements_model.rsl +++ b/bazel/rules/rules_score/trlc/config/score_requirements_model.rsl @@ -35,12 +35,6 @@ abstract type Requirement { freeze status = Status.valid } -tuple ReqId { - item Requirement - separator @ - version Integer -} - abstract type RequirementSafety extends Requirement { safety Asil } @@ -124,8 +118,8 @@ type AoU extends ControlMeasure { // Standards /////////////////////////////// -abstract type StdReq extends Requirement { -} +// abstract type StdReq extends Requirement { +// } ///////////////////////////////