Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,10 @@ repos:

- repo: local
hooks:
- id: bazel-mod-tidy
name: format Bazel module files
entry: bazel mod tidy
- id: buildifier
name: format Bazel files
entry: .devcontainer/run-tool buildifier
language: system
pass_filenames: false
files: '(^|/)(MODULE\.bazel|.*\.bzl|BUILD(\.bazel)?)$'

- id: bzlmod-lockfile
Expand Down
11 changes: 6 additions & 5 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,12 @@
load("//:docs.bzl", "docs")

package(default_visibility = ["//visibility:public"])

exports_files([
"pyproject.toml",
])

docs(
project = "S-CORE Docs-as-Code",
project_url = "https://eclipse-score.github.io/docs-as-code",
external_needs = [
"@score_process_description//:needs_json_file",
],
bundles = [
{
"bundle": "//src/extensions/docs:extensions",
Expand Down Expand Up @@ -52,6 +48,11 @@ docs(
"//tools:module_verification_reports",
"//src:all_sources",
],
external_needs = [
"@score_process_description//:needs_json_file",
],
project = "S-CORE Docs-as-Code",
project_url = "https://eclipse-score.github.io/docs-as-code",
source_dir = "docs",
)

Expand Down
2 changes: 0 additions & 2 deletions MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ use_repo(pip, "docs_as_code_hub_env")
# Additional Python rules provided by aspect, e.g. an improved version of
bazel_dep(name = "aspect_rules_py", version = "1.4.0")

bazel_dep(name = "buildifier_prebuilt", version = "8.2.0.2", dev_dependency = True)

# PlantUML for docs
bazel_dep(name = "rules_java", version = "8.15.1")
bazel_dep(name = "score_tools", version = "0.0.4")
Expand Down
132 changes: 129 additions & 3 deletions MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 12 additions & 2 deletions bzl/basics.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,18 @@ def dirname(path):
def glob_doc_sources(prefix):
"""Return glob patterns for documentation sources below ``prefix``."""
extensions = [
"png", "svg", "md", "rst", "html", "css",
"puml", "need", "yaml", "json", "csv", "inc",
"png",
"svg",
"md",
"rst",
"html",
"css",
"puml",
"need",
"yaml",
"json",
"csv",
"inc",
]
param = [join_path(prefix, "**/*." + ext) for ext in extensions]
srcs = native.glob(param, allow_empty = True)
Expand Down
50 changes: 29 additions & 21 deletions bzl/bundle_rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
# its entries are consumed by the mounts manifest action. Keeping both consumers
# on this provider ensures that source ownership and runtime placement agree.



load("@score_docs_as_code//:bzl/basics.bzl", "join_path")

# Internal data passed between bundle targets and eventually consumed by an
Expand Down Expand Up @@ -83,6 +81,7 @@ CodeTargetSourcesInfo = provider(

def _source_files_from_attributes(ctx):
"""Return files explicitly declared through source or header attributes."""

# DefaultInfo resolves filegroups and generator outputs at the attribute
# boundary. We inspect the consuming library's declarations, so generator
# inputs and the library's compiled outputs do not enter the file list.
Expand Down Expand Up @@ -277,6 +276,7 @@ def _source_dir_runtime_path(ctx):

def _source_target_path(source_file):
"""Return the path spelling used by the source-target staging action."""

# Bazel marks workspace files with ``is_source``; generated outputs use
# the execroot path while workspace files use their runfiles short path.
return source_file.path if not source_file.is_source else source_file.short_path
Expand All @@ -294,6 +294,7 @@ def _source_targets_runtime_path(files):
first_path = _source_target_path(first_file)
first_is_source = first_file.is_source
separator = first_path.rfind("/")

# A root-package source has no parent component; ``.`` represents the
# workspace/execroot root so it can still be used as the shared directory.
runtime_path = first_path[:separator] if separator >= 0 else "."
Expand All @@ -305,6 +306,7 @@ def _source_targets_runtime_path(files):
fail(("explicit bundle sources cannot mix workspace and generated files; " +
"found %r and %r") % (first_path, source_path))
source_separator = source_path.rfind("/")

# Use the same ``.`` spelling for another root-package source.
source_root = source_path[:source_separator] if source_separator >= 0 else "."
if source_root != runtime_path:
Expand All @@ -317,6 +319,7 @@ def _source_targets_relative_paths(files, runtime_path):
relative_paths = []
for source_file in files:
source_path = _source_target_path(source_file)

# A root-package source has ``.`` as its shared parent, so its complete
# path is already relative to the staging tree.
if runtime_path == ".":
Expand All @@ -342,15 +345,16 @@ def _pure_data_runtime_path(ctx):
Give them a synthetic, label-derived identity so multiple distinct
pure-data bundles can be composed into one documentation site.
"""

# Encode the complete label identity so every target gets a stable,
# distinct synthetic path. In particular, local and external labels remain
# distinct when both are composed by one consuming project.
label = str(ctx.label)
encoded_label = (
label.replace("%", "%25")
.replace("@", "%40")
.replace("/", "%2F")
.replace(":", "%3A")
.replace("@", "%40")
.replace("/", "%2F")
.replace(":", "%3A")
)
return "__data__/%s" % encoded_label

Expand Down Expand Up @@ -464,6 +468,7 @@ def _docs_bundle_impl(ctx):
own_bundle_label = str(ctx.label)
own_bundle_name = ctx.label.name
own_primary_need_id = ctx.attr.primary_need_id

# Keep implementation ownership with the declaring documentation entry.
# The metamodel resolves its primary Need from that entry's own documents;
# rebasing into a parent preserves the same bounded implementation file set.
Expand Down Expand Up @@ -514,6 +519,7 @@ def _docs_bundle_impl(ctx):
code_files = own_code_files,
))
own_source_files.extend(ctx.files.source_dir_globbed)

# Local sources are read directly from the workspace by ``bazel run``.
# Only sources from external repositories must be staged in runfiles.
if external:
Expand Down Expand Up @@ -558,6 +564,7 @@ def _docs_bundle_impl(ctx):
code_files = own_code_files,
))
own_source_files.extend(ctx.files.source_targets)

# Explicit artifacts outside the workspace source tree need to be
# staged for ``bazel run`` just like external source bundles.
if not ctx.files.source_targets[0].is_source or external:
Expand Down Expand Up @@ -723,22 +730,22 @@ _docs_bundle = rule(
)

def create_bundle(
name,
bundles,
source_dir_globbed = [],
source_targets = [],
sourcelinks_json = None,
source_dir = None,
entry_doc = "index",
primary_need_id = None,
data = [],
code_targets = [],
code_files = None,
root_docs_config = None,
is_root_bundle = False,
project_name = None,
visibility = None,
**kwargs):
name,
bundles,
source_dir_globbed = [],
source_targets = [],
sourcelinks_json = None,
source_dir = None,
entry_doc = "index",
primary_need_id = None,
data = [],
code_targets = [],
code_files = None,
root_docs_config = None,
is_root_bundle = False,
project_name = None,
visibility = None,
**kwargs):
"""Create a bundle from directory-discovered files and source targets.

``source_dir_globbed`` and ``source_targets`` are separate internal inputs
Expand All @@ -749,6 +756,7 @@ def create_bundle(
A root docs configuration, when present, remains authoritative.
"""
parsed_bundles = [_parse_bundle_declaration(declaration) for declaration in bundles]

# The public macros use ``None`` to represent an omitted optional ID, but
# the underlying Bazel rule has a string attribute and the manifest schema
# keeps this field string-valued. Normalize at that boundary so callers do
Expand Down
1 change: 1 addition & 0 deletions bzl/code_file_lists.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def _file_identity(file):
repository, _, path = path[3:].partition("/")
else:
repository = "_main"

# short_path already omits the configuration root for generated outputs.
return struct(repository = repository, path = path)

Expand Down
1 change: 1 addition & 0 deletions bzl/mount_rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def _composition_manifest_impl(ctx):
],
},
}

# Explicit source targets are mounted as a file allowlist. Directory
# bundles omit this key and retain the existing recursive behavior.
if entry.files:
Expand Down
2 changes: 2 additions & 0 deletions bzl/needs_rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def _sphinx_docs_impl(ctx):
output = ctx.actions.declare_directory(ctx.label.name + "/_build/needs")

bundle = ctx.attr.bundle[DocsBundleInfo]

# The bundle owns both the direct inputs and their execution-root-relative
# source root. Nested sources are provided separately for score_mounts, so
# local exports retain their bundle ownership.
Expand All @@ -54,6 +55,7 @@ def _sphinx_docs_impl(ctx):
project_url = bundle_config.project_url,
required_in_id = bundle_config.required_in_id,
)

# Configuration-free actions need a concrete metamodel input. Use an
# explicitly supplied label first, then the bundle's inherited default.
metamodel_file = ctx.file.score_metamodel_yaml or bundle_config.metamodel
Expand Down
Loading
Loading