Skip to content

Commit bf26f95

Browse files
committed
tc
1 parent 4f4ecc5 commit bf26f95

File tree

5 files changed

+249
-169
lines changed

5 files changed

+249
-169
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Reuse old wheel if possible
2+
3+
description:
4+
Reuse old wheel if possible
5+
6+
inputs:
7+
build-environment:
8+
description: Build environment
9+
required: true
10+
workflow-id:
11+
description: Workflow ID
12+
required: true
13+
github-token:
14+
description: GitHub token
15+
required: true
16+
17+
outputs:
18+
build:
19+
description: Whether the wheel is reused or not
20+
value: ${{ steps.check-file-changes.outputs.build }}
21+
22+
runs:
23+
using: composite
24+
25+
steps:
26+
# Check out pytorch with fetch depth 0
27+
- name: Check file changes
28+
id: check-file-changes
29+
shell: bash
30+
env:
31+
GITHUB_TOKEN: ${{ inputs.github-token }}
32+
run: |
33+
set -x
34+
python3 .github/actions/check-old-whl/reuse_old_whl.py \
35+
--build-environment "${{ inputs.build-environment }}" \
36+
--workflow-id "${{ inputs.workflow-id }}"
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import argparse
2+
import os
3+
import subprocess
4+
import sys
5+
import zipfile
6+
from functools import lru_cache
7+
from pathlib import Path
8+
from typing import Any
9+
import stat
10+
import requests
11+
12+
13+
@lru_cache
14+
def get_merge_base() -> str:
15+
merge_base = subprocess.check_output(
16+
["git", "merge-base", "HEAD", "origin/main"],
17+
text=True,
18+
stderr=subprocess.DEVNULL,
19+
).strip()
20+
return merge_base
21+
22+
23+
def ok_changed_file(file: str) -> bool:
24+
if (
25+
file.startswith("torch/")
26+
and file.endswith(".py")
27+
and not file.startswith("torch/csrc/")
28+
):
29+
return True
30+
if file.startswith("test/") and file.endswith(".py"):
31+
return True
32+
return False
33+
34+
35+
def check_changed_files() -> bool:
36+
merge_base = get_merge_base()
37+
changed_files = (
38+
subprocess.check_output(
39+
["git", "diff", "--name-only", merge_base, "HEAD"],
40+
text=True,
41+
stderr=subprocess.DEVNULL,
42+
)
43+
.strip()
44+
.split()
45+
)
46+
47+
for file in changed_files:
48+
if not ok_changed_file(file):
49+
print(f"File {file} is not allowed to be changed.")
50+
return False
51+
else:
52+
print(f"File {file} is allowed to be changed.")
53+
return True
54+
55+
56+
def query_github_api(url: str) -> Any:
57+
headers = {
58+
"Accept": "application/vnd.github.v3+json",
59+
"Authorization": f"Bearer {os.environ['GITHUB_TOKEN']}",
60+
}
61+
response = requests.get(url, headers=headers)
62+
return response.json()
63+
64+
65+
def find_old_whl(workflow_id: str, build_environment: str) -> bool:
66+
if build_environment is None:
67+
print("BUILD_ENVIRONMENT is not set.")
68+
return False
69+
merge_base = get_merge_base()
70+
71+
workflow_runs = query_github_api(
72+
f"https://api.github.com/repos/pytorch/pytorch/actions/workflows/{workflow_id}/runs?head_sha={merge_base}&branch=main&status=completed&per_page=100"
73+
)
74+
if workflow_runs.get("total_count", 0) == 0:
75+
print("No workflow runs found.")
76+
return False
77+
for run in workflow_runs.get("workflow_runs", []):
78+
# Look in s3 for the old whl
79+
run_id = run["id"]
80+
try:
81+
url = f"https://gha-artifacts.s3.amazonaws.com/pytorch/pytorch/{run_id}/{build_environment}/artifacts.zip"
82+
response = requests.get(
83+
url,
84+
)
85+
if response.status_code == 200:
86+
os.makedirs("/tmp", exist_ok=True)
87+
with open("artifacts.zip", "wb") as f:
88+
f.write(response.content)
89+
print(f"Found old whl file from s3: {url}")
90+
return True
91+
except requests.RequestException as e:
92+
print(f"Error checking for old whl: {e}")
93+
continue
94+
return False
95+
96+
def is_executable(zip_info: zipfile.ZipInfo) -> bool:
97+
# Extract UNIX file mode from external_attr
98+
mode = (zip_info.external_attr >> 16) & 0xFFFF
99+
return bool(mode & stat.S_IXUSR)
100+
101+
def unzip_artifact_and_replace_files() -> None:
102+
# Unzip the artifact and replace files
103+
exectuables = []
104+
subprocess.check_output(
105+
["unzip", "-o", "artifacts.zip", "-d", "artifacts"],
106+
)
107+
os.remove("artifacts.zip")
108+
109+
# Rename wheel into zip
110+
wheel_path = Path("artifacts/dist").glob("*.whl")
111+
print(wheel_path)
112+
for path in wheel_path:
113+
new_path = path.with_suffix(".zip")
114+
os.rename(path, new_path)
115+
print(f"Renamed {path} to {new_path}")
116+
# Unzip the wheel
117+
subprocess.check_output(
118+
["unzip", "-o", new_path, "-d", f"artifacts/dist/{new_path.stem}"],
119+
)
120+
# Copy python files into the artifact
121+
subprocess.check_output(
122+
["rsync", "-avz", "torch", f"artifacts/dist/{new_path.stem}"],
123+
)
124+
125+
# Zip the wheel back
126+
subprocess.check_output(
127+
["zip", "-r", f"artifacts/dist/{new_path.stem}.zip", f"artifacts/dist/{new_path.stem}"],
128+
)
129+
130+
# Reame back to whl
131+
os.rename(new_path, path)
132+
133+
# Remove the extracted folder
134+
subprocess.check_output(
135+
["rm", "-rf", f"artifacts/dist/{new_path.stem}"],
136+
)
137+
138+
# Rezip the artifact
139+
subprocess.check_output(
140+
["zip", "-r", "artifacts.zip", "."], cwd="artifacts"
141+
)
142+
subprocess.check_output(
143+
["mv", "artifacts/artifacts.zip", "."],
144+
)
145+
return None
146+
147+
148+
def parse_args() -> argparse.Namespace:
149+
parser = argparse.ArgumentParser(description="Check for old whl files.")
150+
parser.add_argument("--workflow-id", type=str, required=True, help="Workflow ID")
151+
parser.add_argument(
152+
"--build-environment", type=str, required=True, help="Build environment"
153+
)
154+
return parser.parse_args()
155+
156+
157+
if __name__ == "__main__":
158+
args = parse_args()
159+
can_use_old_whl = check_changed_files()
160+
if not find_old_whl(args.workflow_id, args.build_environment):
161+
print("No old whl found.")
162+
if os.getenv("GITHUB_OUTPUT"):
163+
with open(str(os.getenv("GITHUB_OUTPUT")), "a") as env:
164+
print("build=true", file=env)
165+
else:
166+
print("::set-output name=build::true")
167+
sys.exit(0)
168+
unzip_artifact_and_replace_files()

.github/workflows/_linux-build.yml

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,14 @@ jobs:
132132
role-session-name: gha-linux-build
133133
aws-region: us-east-1
134134

135+
- name: Check if can use old whl build
136+
id: use-old-whl
137+
uses: ./.github/actions/check-old-whl
138+
with:
139+
build-environment: ${{ inputs.build-environment }}
140+
workflow-id: pull.yml
141+
github-token: ${{ secrets.GITHUB_TOKEN }}
142+
135143
- name: Calculate docker image
136144
id: calculate-docker-image
137145
uses: pytorch/test-infra/.github/actions/calculate-docker-image@main
@@ -141,7 +149,7 @@ jobs:
141149

142150
- name: Use following to pull public copy of the image
143151
id: print-ghcr-mirror
144-
if: inputs.build-environment != 'linux-s390x-binary-manywheel'
152+
if: inputs.build-environment != 'linux-s390x-binary-manywheel' && steps.use-old-whl.outputs.build == 'true'
145153
env:
146154
ECR_DOCKER_IMAGE: ${{ steps.calculate-docker-image.outputs.docker-image }}
147155
shell: bash
@@ -151,7 +159,7 @@ jobs:
151159
152160
- name: Pull docker image
153161
uses: pytorch/test-infra/.github/actions/pull-docker-image@main
154-
if: inputs.build-environment != 'linux-s390x-binary-manywheel'
162+
if: inputs.build-environment != 'linux-s390x-binary-manywheel' && steps.use-old-whl.outputs.build == 'true'
155163
with:
156164
docker-image: ${{ steps.calculate-docker-image.outputs.docker-image }}
157165

@@ -179,14 +187,14 @@ jobs:
179187
- name: Download pytest cache
180188
uses: ./.github/actions/pytest-cache-download
181189
continue-on-error: true
182-
if: inputs.build-environment != 'linux-s390x-binary-manywheel'
190+
if: inputs.build-environment != 'linux-s390x-binary-manywheel' && steps.use-old-whl.outputs.build == 'true'
183191
with:
184192
cache_dir: .pytest_cache
185193
job_identifier: ${{ github.workflow }}_${{ inputs.build-environment }}
186194
s3_bucket: ${{ inputs.s3-bucket }}
187195

188196
- name: Build
189-
if: steps.filter.outputs.is-test-matrix-empty == 'False' || inputs.test-matrix == ''
197+
if: (steps.filter.outputs.is-test-matrix-empty == 'False' || inputs.test-matrix == '') && steps.use-old-whl.outputs.build == 'true'
190198
id: build
191199
env:
192200
BUILD_ENVIRONMENT: ${{ inputs.build-environment }}
@@ -281,13 +289,13 @@ jobs:
281289
echo "build_time=$((END_TIME - START_TIME))" >> "$GITHUB_OUTPUT"
282290
283291
- name: Archive artifacts into zip
284-
if: inputs.build-generates-artifacts && steps.build.outcome != 'skipped'
292+
if: inputs.build-generates-artifacts && steps.build.outcome != 'skipped' && steps.use-old-whl.outputs.build == 'true'
285293
run: |
286294
zip -1 -r artifacts.zip dist/ build/custom_test_artifacts build/lib build/bin .additional_ci_files
287295
288296
- name: Store PyTorch Build Artifacts on S3
289297
uses: seemethere/upload-artifact-s3@baba72d0712b404f646cebe0730933554ebce96a # v5.1.0
290-
if: inputs.build-generates-artifacts && steps.build.outcome != 'skipped' && inputs.build-environment != 'linux-s390x-binary-manywheel'
298+
if: inputs.build-generates-artifacts && (steps.build.outcome != 'skipped' || steps.use-old-whl.outputs.build != 'true') && inputs.build-environment != 'linux-s390x-binary-manywheel'
291299
with:
292300
name: ${{ inputs.build-environment }}
293301
retention-days: 14
@@ -297,15 +305,15 @@ jobs:
297305

298306
- name: Store PyTorch Build Artifacts for s390x
299307
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
300-
if: inputs.build-generates-artifacts && steps.build.outcome != 'skipped' && inputs.build-environment == 'linux-s390x-binary-manywheel'
308+
if: inputs.build-generates-artifacts && (steps.build.outcome != 'skipped' || steps.use-old-whl.outputs.build != 'true') && inputs.build-environment == 'linux-s390x-binary-manywheel'
301309
with:
302310
name: ${{ inputs.build-environment }}
303311
retention-days: 14
304312
if-no-files-found: error
305313
path: artifacts.zip
306314

307315
- name: Upload sccache stats
308-
if: steps.build.outcome != 'skipped' && inputs.build-environment != 'linux-s390x-binary-manywheel'
316+
if: steps.build.outcome != 'skipped' && inputs.build-environment != 'linux-s390x-binary-manywheel' && steps.use-old-whl.outputs.build == 'true'
309317
uses: ./.github/actions/upload-sccache-stats
310318
with:
311319
github-token: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/pull.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name: pull
22

33
on:
4-
pull_request:
5-
branches-ignore:
6-
- nightly
4+
# pull_request:
5+
# branches-ignore:
6+
# - nightly
77
push:
88
branches:
99
- main

0 commit comments

Comments
 (0)