Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
8 changes: 8 additions & 0 deletions .github/workflows/test_and_docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,14 @@ jobs:
with:
bazel-docs-verify-target: "--lockfile_mode=error //:docs_check"

docs-link-verify:
uses: eclipse-score/cicd-workflows/.github/workflows/docs-verify.yml@c1c90b1a82a1fab0fc202979dde6686b2162d5a8 # v0.0.0
permissions:
pull-requests: write
contents: read
with:
bazel-docs-verify-target: "--lockfile_mode=error //:docs_link_check"

# This is the user configurable part of the workflow
unit-tests:
uses: ./.github/workflows/test.yml
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test_links.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
# Run your link checker and generate log
- name: Run LinkChecker
run: |
bazel run --lockfile_mode=error //:link_check > linkcheck_output.txt
bazel run --lockfile_mode=error //:docs_link_check > linkcheck_output.txt
continue-on-error: true

# Run your Python script to parse the linkcheck log and generate issue body
Expand Down
6 changes: 6 additions & 0 deletions BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,9 @@ alias(
name = "actionlint",
actual = "@score_devcontainer//tools:actionlint",
)

# bazel run //:lint_check
alias(
name = "link_check",
actual = ":docs_link_check",
)
Comment thread
RamakrishnanPK marked this conversation as resolved.
Outdated
2 changes: 1 addition & 1 deletion docs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ def docs(source_dir = "docs", data = [], deps = [], scan_code = [], known_good =
docs_env["ACTION"] = "linkcheck"
py_binary(
name = "docs_link_check",
tags = ["cli_help=Verify Links inside Documentation:\nbazel run //:link_check\n (Note: this could take a long time)"],
tags = ["cli_help=Verify Links inside Documentation:\nbazel run //:docs_link_check\n (Note: this could take a long time)"],
srcs = [incremental_src],
data = docs_data,
deps = deps,
Expand Down
2 changes: 1 addition & 1 deletion docs/internals/extensions/extension_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Some events also expect a return value.
For more information, please see the related documentation:
- [Attaching function signature](https://www.sphinx-doc.org/en/master/extdev/appapi.html#sphinx.application.Sphinx.connect)
- [Build API events](https://www.sphinx-doc.org/en/master/extdev/event_callbacks.html#core-events-overview)
- [sphinx-needs events](https://github.com/useblocks/sphinx-needs/blob/master/docs/contributing.rst#structure-of-the-extensions-logic)
- [sphinx-needs events](https://github.com/useblocks/sphinx-needs/blob/master/AGENTS.md#sphinx-extension-architecture)

## Adding a New Configuration Value

Expand Down
6 changes: 3 additions & 3 deletions docs/internals/extensions/source_code_linker.md
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ score_source_code_linker/

To see working examples for CodeLinks & TestLinks, take a look at the Docs-As-Code documentation.

[Example CodeLink](https://eclipse-score.github.io/docs-as-code/main/requirements/requirements.html#tool_req__docs_common_attr_id_scheme)
[Example CodeLink](https://eclipse-score.github.io/docs-as-code/main/requirements/requirements.html#tool_req__docs_common_attr_status)
[Example CodeLink](https://eclipse-score.github.io/docs-as-code/main/internals/requirements/requirements.html#tool_req__docs_common_attr_id_scheme)
[Example CodeLink](https://eclipse-score.github.io/docs-as-code/main/internals/requirements/requirements.html#tool_req__docs_common_attr_status)

[Example TestLink](https://eclipse-score.github.io/docs-as-code/main/requirements/requirements.html#tool_req__docs_dd_link_source_code_link)
[Example TestLink](https://eclipse-score.github.io/docs-as-code/main/internals/requirements/requirements.html#tool_req__docs_dd_link_source_code_link)
3 changes: 2 additions & 1 deletion docs/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@

| Target | What it does |
| ---------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `bazel run //:docs` | Builds documentation (also writes `metrics.json`) |
| `bazel run //:docs` | Builds documentation (also writes `metrics.json`) |
| `bazel run //:docs_check` | Verifies documentation correctness |
| `bazel run //:docs_link_check` | Lists broken links |
| `bazel run //:docs_combo` | Builds combined documentation with all external dependencies included |
| `bazel run //:traceability_gate -- --metrics-json bazel-bin/needs_json/_build/needs/metrics.json --min-req-code 70 --min-req-test 70 --min-req-fully-linked 60 --min-tests-linked 70` | Reads the pre-computed metrics.json and fails if coverage thresholds are not met |
| `bazel run //:live_preview` | Creates a live_preview of the documentation viewable in a local server |
Expand Down
8 changes: 8 additions & 0 deletions src/extensions/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,11 @@ py_library(
visibility = ["//visibility:public"],
deps = ["@score_docs_as_code//src/helper_lib"],
)

py_library(
name = "broken_link_fix",
srcs = ["@score_docs_as_code//src/extensions:broken_link_fix.py"],
imports = ["."],
visibility = ["//visibility:public"],
deps = ["@score_docs_as_code//src/helper_lib"],
)
100 changes: 100 additions & 0 deletions src/extensions/broken_link_fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# *******************************************************************************
# 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
# *******************************************************************************
import re
from collections.abc import Callable
from enum import StrEnum
from typing import Any, cast

from sphinx._cli.util.colour import darkgray
from sphinx.application import Sphinx
from sphinx.builders import linkcheck
from sphinx.builders.linkcheck import CheckExternalLinksBuilder, CheckResult
from sphinx.util import logging

logger = logging.getLogger(__name__)

linkcheckbase = cast(
Callable[[CheckExternalLinksBuilder, CheckResult], None],
linkcheck.CheckExternalLinksBuilder.process_result,
)


class _Status(StrEnum):
BROKEN = "broken"


def process_result(self: CheckExternalLinksBuilder, result: CheckResult) -> None:
"""hook a custom process_result function.

Args:
self: The CheckExternalLinksBuilder instance.
result: The CheckResult instance.

Returns:
None
"""
match result.status:
case _Status.BROKEN:
""" Ignore client errors from sourceforge.io """
if re.match(
r"^https://[^/]+\.sourceforge\.io(/|$)", result.uri
) and "403 Client Error" in str(result.message):
logger.info(darkgray("-ignored- ") + result.uri)
self.write_entry(
"ignored",
result.docname,
self.env.doc2path(result.docname, False),
result.lineno,
f"{result.uri} to {result.message}",
)
return

""" Ignore Anchor errors from .md files """
if re.match(
r"https?://.*?\.md#[A-Za-z0-9_.-]+$", result.uri
) and "Anchor" in str(result.message):
logger.info(darkgray("-ignored- ") + result.uri)
self.write_entry(
"ignored",
result.docname,
self.env.doc2path(result.docname, False),
result.lineno,
f"{result.uri} to {result.message}",
)
return

linkcheckbase(self, result)


def setup(app: Sphinx) -> dict[str, object]:
"""Register the custom linkcheck extension.

The extension patches the default Sphinx linkcheck builder to ignore
known false-positive anchor errors reported for selected GitHub
Markdown URLs.

Args:
app: The Sphinx application instance.

Returns:
Extension metadata required by Sphinx.
"""

# hook a custom process_result function
cast(Any, linkcheck.CheckExternalLinksBuilder).process_result = process_result

return {
"version": "0.0.1",
"parallel_read_safe": True,
"parallel_write_safe": True,
}
1 change: 1 addition & 0 deletions src/extensions/score_sphinx_bundle/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ py_library(
visibility = ["//visibility:public"],
deps = all_requirements + [
"@score_docs_as_code//src/extensions:score_plantuml",
"@score_docs_as_code//src/extensions:broken_link_fix",
"@score_docs_as_code//src/extensions/score_draw_uml_funcs",
"@score_docs_as_code//src/extensions/score_layout",
"@score_docs_as_code//src/extensions/score_metamodel",
Expand Down
1 change: 1 addition & 0 deletions src/extensions/score_sphinx_bundle/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"needs_config_writer",
"score_sync_toml",
"score_metrics",
"broken_link_fix",
]


Expand Down
Loading