From b05fe885aa9c56e4af0d2ed8cd26b958bdd117ca Mon Sep 17 00:00:00 2001 From: BM Cho Date: Sun, 26 Jul 2026 13:00:14 +0800 Subject: [PATCH 1/2] fix(release): surface bundled JavaScript licenses --- LICENSE-wheel | 6 ++++++ pyproject.toml | 7 +++++- scripts/verify_apache_artifacts.py | 26 ++++++++++++++++++++++ tests/test_verify_apache_artifacts.py | 31 +++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/LICENSE-wheel b/LICENSE-wheel index b1c8c03b0..74a5cd29b 100644 --- a/LICENSE-wheel +++ b/LICENSE-wheel @@ -226,3 +226,9 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +------------------------------- + +Third-party JavaScript license notices for the bundled Burr UI are included +under the wheel's .dist-info/licenses/burr/tracking/server/build/static/js/ +directory. diff --git a/pyproject.toml b/pyproject.toml index 6a17ee988..a9a3f904b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,12 @@ maintainers = [ ] description = "Apache Burr (incubating) makes it easy to develop applications that make decisions (chatbots, agents, simulations, etc...) from simple python building blocks." readme = "README.md" -license-files = ["LICENSE-wheel", "NOTICE", "DISCLAIMER"] +license-files = [ + "LICENSE-wheel", + "NOTICE", + "DISCLAIMER", + "burr/tracking/server/build/static/js/main.*.js.LICENSE.txt", +] keywords = ["mlops", "data", "state-machine", "llmops"] classifiers = [ "Development Status :: 4 - Beta", diff --git a/scripts/verify_apache_artifacts.py b/scripts/verify_apache_artifacts.py index 17b29f240..cc8cad0a0 100755 --- a/scripts/verify_apache_artifacts.py +++ b/scripts/verify_apache_artifacts.py @@ -62,6 +62,7 @@ REQUIRED_TEXT_FILES = ("LICENSE", "NOTICE", "DISCLAIMER") WHEEL_LICENSE_FILES = ("LICENSE-wheel",) WHEEL_REQUIRED_TEXT_FILES = ("NOTICE", "DISCLAIMER") + WHEEL_LICENSE_FILES +WHEEL_JS_LICENSE_SUFFIX = ".js.LICENSE.txt" PASS = "PASS" FAIL = "FAIL" SKIP = "SKIP" @@ -411,6 +412,29 @@ def _verify_required_text_files( return all_valid +def _verify_bundled_js_license( + artifact_name: str, + file_bytes: dict[str, bytes], + summary: VerificationSummary, +) -> bool: + check_name = f"{artifact_name} contains bundled JavaScript licenses" + matches = [ + path + for path in file_bytes + if any(part.endswith(".dist-info") for part in PurePosixPath(path).parts) + and "/licenses/burr/tracking/server/build/static/js/" in f"/{path}" + and path.endswith(WHEEL_JS_LICENSE_SUFFIX) + ] + if not matches: + print(" Missing bundled JavaScript license notices") + summary.fail(check_name, "missing") + return False + + print(f" Bundled JavaScript license notices present ({matches[0]})") + summary.pass_(check_name, matches[0]) + return True + + def verify_artifact_contents( artifacts_dir: str, summary: VerificationSummary | None = None ) -> bool: @@ -456,6 +480,8 @@ def verify_artifact_contents( summary, ): all_valid = False + if not _verify_bundled_js_license(artifact_name, file_bytes, summary): + all_valid = False else: print(f" ⚠️ Skipping unsupported artifact type: {artifact_name}") summary.skip(f"Artifact metadata: {artifact_name}", "unsupported type") diff --git a/tests/test_verify_apache_artifacts.py b/tests/test_verify_apache_artifacts.py index c8f15f362..d0ea91cbf 100644 --- a/tests/test_verify_apache_artifacts.py +++ b/tests/test_verify_apache_artifacts.py @@ -86,6 +86,8 @@ def test_verify_artifact_contents_passes_for_tarball_and_wheel(): "apache_burr-0.41.0.dist-info/licenses/LICENSE-wheel": _reference_text( "LICENSE-wheel" ), + "apache_burr-0.41.0.dist-info/licenses/burr/tracking/server/build/static/js/" + "main.abc123.js.LICENSE.txt": b"third-party notices", }, ) @@ -119,6 +121,35 @@ def test_verify_artifact_contents_fails_when_wheel_license_file_is_missing(): ) +def test_verify_artifact_contents_fails_when_bundled_js_license_is_missing(): + with tempfile.TemporaryDirectory() as temp_dir: + artifacts_dir = Path(temp_dir) / "dist" + artifacts_dir.mkdir() + + wheel_path = artifacts_dir / "apache_burr-0.41.0-py3-none-any.whl" + _write_wheel( + wheel_path, + { + "apache_burr/__init__.py": b"__version__ = '0.41.0'\n", + "apache_burr-0.41.0.dist-info/METADATA": b"Metadata-Version: 2.1\n", + "apache_burr-0.41.0.dist-info/WHEEL": b"Wheel-Version: 1.0\n", + "apache_burr-0.41.0.dist-info/licenses/NOTICE": _reference_text("NOTICE"), + "apache_burr-0.41.0.dist-info/licenses/DISCLAIMER": _reference_text("DISCLAIMER"), + "apache_burr-0.41.0.dist-info/licenses/LICENSE-wheel": _reference_text( + "LICENSE-wheel" + ), + }, + ) + + summary = verify.VerificationSummary() + assert verify.verify_artifact_contents(str(artifacts_dir), summary) is False + assert any( + result.name.endswith("contains bundled JavaScript licenses") + and result.status == verify.FAIL + for result in summary.results + ) + + def test_verify_reproducible_build_compares_rebuilt_outputs(monkeypatch): with tempfile.TemporaryDirectory() as temp_dir: artifacts_dir = Path(temp_dir) / "dist" From 0823b1876915dedfc0a59814061aa934c1dc49a3 Mon Sep 17 00:00:00 2001 From: BM Cho Date: Mon, 27 Jul 2026 16:31:04 +0800 Subject: [PATCH 2/2] fix(release): store bundled UI licenses in source --- LICENSE-bundled-js | 110 ++++++++++++++++++++++++++ LICENSE-wheel | 3 +- pyproject.toml | 3 +- scripts/verify_apache_artifacts.py | 28 +------ tests/test_verify_apache_artifacts.py | 34 +------- 5 files changed, 117 insertions(+), 61 deletions(-) create mode 100644 LICENSE-bundled-js diff --git a/LICENSE-bundled-js b/LICENSE-bundled-js new file mode 100644 index 000000000..b4a722a28 --- /dev/null +++ b/LICENSE-bundled-js @@ -0,0 +1,110 @@ +/** + * @license React + * react-dom.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * @license React + * react-jsx-runtime.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * @license React + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * @license React + * scheduler.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * @license React + * use-sync-external-store-shim.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * @license React + * use-sync-external-store-shim/with-selector.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +/** + * @remix-run/router v1.15.1 + * + * Copyright (c) Remix Software Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE.md file in the root directory of this source tree. + * + * @license MIT + */ + +/** + * Prism: Lightweight, robust, elegant syntax highlighting + * + * @license MIT + * @author Lea Verou + * @namespace + * @public + */ + +/** + * React Router DOM v6.22.1 + * + * Copyright (c) Remix Software Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE.md file in the root directory of this source tree. + * + * @license MIT + */ + +/** + * React Router v6.22.1 + * + * Copyright (c) Remix Software Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE.md file in the root directory of this source tree. + * + * @license MIT + */ + +/** @license React v16.13.1 + * react-is.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ diff --git a/LICENSE-wheel b/LICENSE-wheel index 74a5cd29b..141655a6b 100644 --- a/LICENSE-wheel +++ b/LICENSE-wheel @@ -230,5 +230,4 @@ SOFTWARE. ------------------------------- Third-party JavaScript license notices for the bundled Burr UI are included -under the wheel's .dist-info/licenses/burr/tracking/server/build/static/js/ -directory. +in ``LICENSE-bundled-js``. diff --git a/pyproject.toml b/pyproject.toml index a9a3f904b..2a934d01f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,9 +36,9 @@ description = "Apache Burr (incubating) makes it easy to develop applications th readme = "README.md" license-files = [ "LICENSE-wheel", + "LICENSE-bundled-js", "NOTICE", "DISCLAIMER", - "burr/tracking/server/build/static/js/main.*.js.LICENSE.txt", ] keywords = ["mlops", "data", "state-machine", "llmops"] classifiers = [ @@ -272,6 +272,7 @@ include = [ "NOTICE", "DISCLAIMER", "LICENSE-wheel", + "LICENSE-bundled-js", "scripts/**", "telemetry/ui/**", "examples/__init__.py", diff --git a/scripts/verify_apache_artifacts.py b/scripts/verify_apache_artifacts.py index cc8cad0a0..fc7226ac6 100755 --- a/scripts/verify_apache_artifacts.py +++ b/scripts/verify_apache_artifacts.py @@ -60,9 +60,8 @@ # Configuration PROJECT_SHORT_NAME = "burr" REQUIRED_TEXT_FILES = ("LICENSE", "NOTICE", "DISCLAIMER") -WHEEL_LICENSE_FILES = ("LICENSE-wheel",) +WHEEL_LICENSE_FILES = ("LICENSE-wheel", "LICENSE-bundled-js") WHEEL_REQUIRED_TEXT_FILES = ("NOTICE", "DISCLAIMER") + WHEEL_LICENSE_FILES -WHEEL_JS_LICENSE_SUFFIX = ".js.LICENSE.txt" PASS = "PASS" FAIL = "FAIL" SKIP = "SKIP" @@ -412,29 +411,6 @@ def _verify_required_text_files( return all_valid -def _verify_bundled_js_license( - artifact_name: str, - file_bytes: dict[str, bytes], - summary: VerificationSummary, -) -> bool: - check_name = f"{artifact_name} contains bundled JavaScript licenses" - matches = [ - path - for path in file_bytes - if any(part.endswith(".dist-info") for part in PurePosixPath(path).parts) - and "/licenses/burr/tracking/server/build/static/js/" in f"/{path}" - and path.endswith(WHEEL_JS_LICENSE_SUFFIX) - ] - if not matches: - print(" Missing bundled JavaScript license notices") - summary.fail(check_name, "missing") - return False - - print(f" Bundled JavaScript license notices present ({matches[0]})") - summary.pass_(check_name, matches[0]) - return True - - def verify_artifact_contents( artifacts_dir: str, summary: VerificationSummary | None = None ) -> bool: @@ -480,8 +456,6 @@ def verify_artifact_contents( summary, ): all_valid = False - if not _verify_bundled_js_license(artifact_name, file_bytes, summary): - all_valid = False else: print(f" ⚠️ Skipping unsupported artifact type: {artifact_name}") summary.skip(f"Artifact metadata: {artifact_name}", "unsupported type") diff --git a/tests/test_verify_apache_artifacts.py b/tests/test_verify_apache_artifacts.py index d0ea91cbf..36837cd07 100644 --- a/tests/test_verify_apache_artifacts.py +++ b/tests/test_verify_apache_artifacts.py @@ -86,8 +86,9 @@ def test_verify_artifact_contents_passes_for_tarball_and_wheel(): "apache_burr-0.41.0.dist-info/licenses/LICENSE-wheel": _reference_text( "LICENSE-wheel" ), - "apache_burr-0.41.0.dist-info/licenses/burr/tracking/server/build/static/js/" - "main.abc123.js.LICENSE.txt": b"third-party notices", + "apache_burr-0.41.0.dist-info/licenses/LICENSE-bundled-js": _reference_text( + "LICENSE-bundled-js" + ), }, ) @@ -121,35 +122,6 @@ def test_verify_artifact_contents_fails_when_wheel_license_file_is_missing(): ) -def test_verify_artifact_contents_fails_when_bundled_js_license_is_missing(): - with tempfile.TemporaryDirectory() as temp_dir: - artifacts_dir = Path(temp_dir) / "dist" - artifacts_dir.mkdir() - - wheel_path = artifacts_dir / "apache_burr-0.41.0-py3-none-any.whl" - _write_wheel( - wheel_path, - { - "apache_burr/__init__.py": b"__version__ = '0.41.0'\n", - "apache_burr-0.41.0.dist-info/METADATA": b"Metadata-Version: 2.1\n", - "apache_burr-0.41.0.dist-info/WHEEL": b"Wheel-Version: 1.0\n", - "apache_burr-0.41.0.dist-info/licenses/NOTICE": _reference_text("NOTICE"), - "apache_burr-0.41.0.dist-info/licenses/DISCLAIMER": _reference_text("DISCLAIMER"), - "apache_burr-0.41.0.dist-info/licenses/LICENSE-wheel": _reference_text( - "LICENSE-wheel" - ), - }, - ) - - summary = verify.VerificationSummary() - assert verify.verify_artifact_contents(str(artifacts_dir), summary) is False - assert any( - result.name.endswith("contains bundled JavaScript licenses") - and result.status == verify.FAIL - for result in summary.results - ) - - def test_verify_reproducible_build_compares_rebuilt_outputs(monkeypatch): with tempfile.TemporaryDirectory() as temp_dir: artifacts_dir = Path(temp_dir) / "dist"