def extract_release(auth, dist_dir, dry_run, release_url): """Download and verify assets from a draft GitHub release""" match = parse_release_url(release_url) owner, repo = match["owner"], match["repo"] gh = GhApi(owner=owner, repo=repo, token=auth) release = util.release_for_url(gh, release_url) assets = release.assets # Clean the dist folder dist = Path(dist_dir) if dist.exists(): shutil.rmtree(dist, ignore_errors=True) os.makedirs(dist) # Fetch, validate, and publish assets for asset in assets: util.log(f"Fetching {asset.name}...") url = asset.url headers = dict(Authorization=f"token {auth}", Accept="application/octet-stream") path = dist / asset.name with requests.get(url, headers=headers, stream=True) as r: r.raise_for_status() with open(path, "wb") as f: for chunk in r.iter_content(chunk_size=8192): f.write(chunk) suffix = Path(asset.name).suffix if suffix in [".gz", ".whl"]: python.check_dist(path) elif suffix == ".tgz": npm.check_dist(path) else: util.log(f"Nothing to check for {asset.name}") # Skip sha validation for dry runs since the remote tag will not exist if dry_run: return branch = release.target_commitish tag_name = release.tag_name sha = None for tag in gh.list_tags(): if tag.ref == f"refs/tags/{tag_name}": sha = tag.object.sha if sha is None: raise ValueError("Could not find tag") # Run a git checkout # Fetch the branch # Get the commmit message for the branch commit_message = "" with TemporaryDirectory() as td: url = gh.repos.get().html_url util.run(f"git clone {url} local", cwd=td) checkout = osp.join(td, "local") if not osp.exists(url): util.run(f"git fetch origin {branch}", cwd=checkout) commit_message = util.run(f"git log --format=%B -n 1 {sha}", cwd=checkout) for asset in assets: # Check the sha against the published sha valid = False path = dist / asset.name sha = util.compute_sha256(path) for line in commit_message.splitlines(): if asset.name in line: if sha in line: valid = True else: util.log("Mismatched sha!") if not valid: # pragma: no cover raise ValueError(f"Invalid file {asset.name}")
def test_compute_sha256(py_package): assert len(util.compute_sha256(py_package / "CHANGELOG.md")) == 64