Skip to content

Commit fc4f9d1

Browse files
authored
Add index file to src_code path. This is package that contains release rc source code. This way users can build pytorch from source (#7621)
Fixes: pytorch/pytorch#124759 Index is available here: https://download.pytorch.org/source_code/test/index.html already populated using following command: ``` python manage_v2.py source_code/test ```
1 parent 3be855e commit fc4f9d1

2 files changed

Lines changed: 70 additions & 1 deletion

File tree

.github/workflows/update-s3-html.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
environment: pytorchbot-env
1818
strategy:
1919
matrix:
20-
prefix: ["whl", "whl/test", "whl/nightly", "libtorch", "libtorch/nightly", "whl/preview/forge"]
20+
prefix: ["whl", "whl/test", "whl/nightly", "libtorch", "libtorch/nightly", "whl/preview/forge", "source_code/test"]
2121
fail-fast: False
2222
container:
2323
image: continuumio/miniconda3:23.10.0-1

s3_management/manage_v2.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
"whl/test/variant",
8787
"whl/variant",
8888
"whl/preview/forge",
89+
"source_code/test",
8990
]
9091

9192
# NOTE: This refers to the name on the wheels themselves and not the name of
@@ -661,6 +662,21 @@ def to_libtorch_html(self, subdir: Optional[str] = None) -> str:
661662
out.append(f'<a href="/{obj.key}">{sanitized_obj}</a><br/>')
662663
return "\n".join(sorted(out))
663664

665+
def to_source_code_html(self, subdir: Optional[str] = None) -> str:
666+
"""Generates a string that can be used as the HTML index for source code packages
667+
668+
Creates a simple browseable index for pytorch-*.tar.gz source code packages.
669+
"""
670+
out: List[str] = []
671+
subdir = self._resolve_subdir(subdir)
672+
for obj in self.gen_file_list(subdir):
673+
# Strip our prefix
674+
sanitized_obj = obj.key.replace(subdir, "", 1)
675+
if sanitized_obj.startswith("/"):
676+
sanitized_obj = sanitized_obj.lstrip("/")
677+
out.append(f'<a href="/{obj.key}">{sanitized_obj}</a><br/>')
678+
return "\n".join(sorted(out))
679+
664680
def to_simple_package_html(
665681
self,
666682
subdir: Optional[str],
@@ -804,6 +820,34 @@ def upload_libtorch_html(self) -> None:
804820
Body=index_html,
805821
)
806822

823+
def upload_source_code_html(self) -> None:
824+
"""Upload source code index to S3 and R2"""
825+
# For source_code/test, it has a flat structure, so we only upload to the prefix directory
826+
index_html = self.to_source_code_html(subdir=self.prefix)
827+
828+
# Upload to S3
829+
print(
830+
f"INFO Uploading {self.prefix}/{self.html_name} to S3 bucket {BUCKET.name}"
831+
)
832+
BUCKET.Object(key=f"{self.prefix}/{self.html_name}").put(
833+
ACL="public-read",
834+
CacheControl="no-cache,no-store,must-revalidate",
835+
ContentType="text/html",
836+
Body=index_html,
837+
)
838+
839+
# Upload to R2 if configured
840+
if R2_BUCKET:
841+
print(
842+
f"INFO Uploading {self.prefix}/{self.html_name} to R2 bucket {R2_BUCKET.name}"
843+
)
844+
R2_BUCKET.Object(key=f"{self.prefix}/{self.html_name}").put(
845+
ACL="public-read",
846+
CacheControl="no-cache,no-store,must-revalidate",
847+
ContentType="text/html",
848+
Body=index_html,
849+
)
850+
807851
def upload_pep503_htmls(self) -> None:
808852
# Pre-fetch bucket listings for all subdirectories to optimize S3 API calls
809853
print("INFO: Pre-fetching S3 bucket listings for optimization...")
@@ -970,6 +1014,15 @@ def save_libtorch_html(self) -> None:
9701014
) as f:
9711015
f.write(self.to_libtorch_html(subdir=subdir))
9721016

1017+
def save_source_code_html(self) -> None:
1018+
"""Save source code index to local file"""
1019+
print(f"INFO Saving {self.prefix}/{self.html_name}")
1020+
makedirs(self.prefix, exist_ok=True)
1021+
with open(
1022+
path.join(self.prefix, self.html_name), mode="w", encoding="utf-8"
1023+
) as f:
1024+
f.write(self.to_source_code_html(subdir=self.prefix))
1025+
9731026
def save_pep503_htmls(self) -> None:
9741027
for subdir in self.subdirs:
9751028
print(f"INFO Saving {subdir}/index.html")
@@ -1150,6 +1203,17 @@ def grant_public_read(cls, key: str) -> None:
11501203
@classmethod
11511204
def fetch_object_names(cls, prefix: str) -> List[str]:
11521205
obj_names = []
1206+
1207+
# Special handling for source_code prefix - flat structure with only tar.gz files
1208+
if prefix.startswith("source_code"):
1209+
for obj in BUCKET.objects.filter(Prefix=prefix):
1210+
# For source_code, we only want files directly in the prefix directory
1211+
# and they should be tar.gz files matching pytorch-*.tar.gz
1212+
if path.dirname(obj.key) == prefix and obj.key.endswith(".tar.gz"):
1213+
obj_names.append(obj.key)
1214+
return obj_names
1215+
1216+
# Original logic for whl and libtorch prefixes
11531217
for obj in BUCKET.objects.filter(Prefix=prefix):
11541218
is_acceptable = any(
11551219
[path.dirname(obj.key) == prefix]
@@ -1331,6 +1395,7 @@ def main() -> None:
13311395
prefixes = PREFIXES if args.prefix == "all" else [args.prefix]
13321396
for prefix in prefixes:
13331397
generate_pep503 = prefix.startswith("whl")
1398+
generate_source_code = prefix.startswith("source_code")
13341399
print(f"INFO: {action} for '{prefix}'")
13351400
stime = time.time()
13361401
idx = S3Index.from_S3(
@@ -1345,11 +1410,15 @@ def main() -> None:
13451410
elif args.do_not_upload:
13461411
if generate_pep503:
13471412
idx.save_pep503_htmls()
1413+
elif generate_source_code:
1414+
idx.save_source_code_html()
13481415
else:
13491416
idx.save_libtorch_html()
13501417
else:
13511418
if generate_pep503:
13521419
idx.upload_pep503_htmls()
1420+
elif generate_source_code:
1421+
idx.upload_source_code_html()
13531422
else:
13541423
idx.upload_libtorch_html()
13551424

0 commit comments

Comments
 (0)