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
4 changes: 2 additions & 2 deletions dotnet/private/docfx_repo.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ docfx_repo = repository_rule(
def _docfx_extension_impl(module_ctx):
docfx_repo(
name = "docfx",
version = "2.78.2",
sha256 = "68b70b5e3e3f0df0dd858b228131fec40ca45493bb5b93f77b9ab3a38b21f7fb",
version = "2.78.4",
sha256 = "56faca4233a743b446a7584ff8195d8bb09a33aaa97e9e089c1e6b112212a848",
)
return module_ctx.extension_metadata(reproducible = True)

Expand Down
2 changes: 2 additions & 0 deletions dotnet/update-deps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ DOTNET="${DOTNET:-dotnet}"
("$DOTNET" tool restore && "$DOTNET" tool run paket install)
bazel run @rules_dotnet//tools/paket2bazel:paket2bazel -- --dependencies-file "$(pwd)/paket.dependencies" --output-folder "$(pwd)"
)

bazel run //scripts:update_docfx
9 changes: 9 additions & 0 deletions scripts/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ py_binary(
srcs = ["update_multitool_binaries.py"],
)

py_binary(
name = "update_docfx",
srcs = ["update_docfx.py"],
deps = [
requirement("packaging"),
requirement("urllib3"),
],
)

java_binary(
name = "google-java-format",
jvm_flags = [
Expand Down
138 changes: 138 additions & 0 deletions scripts/update_docfx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
#!/usr/bin/env python
"""Update docfx_repo.bzl to the latest DocFX package on NuGet.

This script fetches the latest stable DocFX version (or a user-specified one),
computes the nupkg sha256, and rewrites dotnet/private/docfx_repo.bzl.
"""

import argparse
import hashlib
import json
import os
from pathlib import Path

import urllib3
from packaging.version import InvalidVersion, Version

NUGET_INDEX_URL = "https://api.nuget.org/v3-flatcontainer/docfx/index.json"
NUGET_NUPKG_URL = "https://api.nuget.org/v3-flatcontainer/docfx/{version}/docfx.{version}.nupkg"

http = urllib3.PoolManager()


def fetch_json(url):
r = http.request("GET", url)
return json.loads(r.data)


def choose_version(versions, allow_prerelease, explicit_version=None):
if explicit_version:
if explicit_version not in versions:
raise ValueError(f"Requested DocFX version {explicit_version!r} not found in NuGet index")
return explicit_version

parsed = []
for v in versions:
try:
pv = Version(v)
except InvalidVersion:
continue
if not allow_prerelease and pv.is_prerelease:
continue
parsed.append((pv, v))

if not parsed:
if allow_prerelease:
raise ValueError("No parseable DocFX versions found in NuGet index")
else:
raise ValueError("No stable DocFX versions found. Use --allow-prerelease to include prereleases.")

return max(parsed, key=lambda item: item[0])[1]


def sha256_of_url(url):
digest = hashlib.sha256()
r = http.request("GET", url, preload_content=False)
for chunk in r.stream(1024 * 1024):
digest.update(chunk)
r.release_conn()
return digest.hexdigest()


def render_docfx_repo(version, sha256):
return f'''\
"""Repository rule to download the docfx NuGet package."""

_BUILD = """
package(default_visibility = ["//visibility:public"])
exports_files(glob(["**/*"]))
filegroup(name = "docfx_dll", srcs = ["tools/net8.0/any/docfx.dll"])
"""

def _docfx_repo_impl(ctx):
ctx.download_and_extract(
url = "https://api.nuget.org/v3-flatcontainer/docfx/{{0}}/docfx.{{0}}.nupkg".format(ctx.attr.version),
sha256 = ctx.attr.sha256,
type = "zip",
)
ctx.file("BUILD.bazel", _BUILD)

docfx_repo = repository_rule(
implementation = _docfx_repo_impl,
attrs = {{
"version": attr.string(mandatory = True),
"sha256": attr.string(mandatory = True),
}},
)

def _docfx_extension_impl(module_ctx):
docfx_repo(
name = "docfx",
version = "{version}",
sha256 = "{sha256}",
)
return module_ctx.extension_metadata(reproducible = True)

docfx_extension = module_extension(implementation = _docfx_extension_impl)
'''


def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"--version",
help="Use this DocFX version instead of the latest stable.",
)
parser.add_argument(
"--allow-prerelease",
action="store_true",
help="Allow prerelease versions when selecting latest.",
)
parser.add_argument(
"--output",
default="dotnet/private/docfx_repo.bzl",
help="Output file path (default: dotnet/private/docfx_repo.bzl)",
)
args = parser.parse_args()

index = fetch_json(NUGET_INDEX_URL)
versions = index.get("versions", [])
if not versions:
raise ValueError("NuGet index returned no versions for DocFX")

version = choose_version(versions, args.allow_prerelease, args.version)
nupkg_url = NUGET_NUPKG_URL.format(version=version)
sha256 = sha256_of_url(nupkg_url)

output_path = Path(args.output)
if not output_path.is_absolute():
workspace_dir = os.environ.get("BUILD_WORKSPACE_DIRECTORY")
if workspace_dir:
output_path = Path(workspace_dir) / output_path
output_path.write_text(render_docfx_repo(version, sha256))

print(f"Updated {output_path} to DocFX {version}")


if __name__ == "__main__":
main()
Loading