def upload_asset(release: GitRelease, path: _PathLike, replace: bool = False, text: bool = False, content: bytes = None) -> None: path = Path(path) basename = os.path.basename(str(path)) asset_name = get_gh_asset_name(basename, text) asset_label = basename for asset in get_release_assets(release, include_incomplete=True): if asset_name == asset.name: # We want to tread incomplete assets as if they weren't there # so replace them always if replace or not asset_is_complete(asset): asset.delete_asset() else: print( f"Skipping upload for {asset_name} as {asset_label}, already exists" ) return if content is None: release.upload_asset(str(path), label=asset_label, name=asset_name) else: with io.BytesIO(content) as fileobj: release.upload_asset_from_memory( # type: ignore fileobj, len(content), label=asset_label, name=asset_name) print(f"Uploaded {asset_name} as {asset_label}")
def erase_old_drafts(repo_full_name): gh = get_gh_client() ghdb = get_github_db() search_for = { 'url': { '$regex': '{}/releases/[0-9]+$'.format(repo_full_name), }, 'tag_name': { '$regex': '^untagged-', }, } for page in get_next_page(ghdb.releases.find(search_for)): for raw_release in page: document = GitRelease( gh._Github__requester, {}, raw_release, completed=False, ) doc_id = raw_release['_id'] try: # check if the object still exists document.update() except UnknownObjectException: # if doesn't exist erase from mongo ghdb.releases.remove({'_id': doc_id}) else: # if still exist just update ghdb.releases.update({'_id': doc_id}, document.raw_data)
def upload_asset(release: GitRelease, path: _PathLike, replace: bool = False) -> None: # type_: msys/mingw/failed if not environ.get("CI"): print("WARNING: upload skipped, not running in CI") return path = Path(path) basename = os.path.basename(str(path)) asset_name = get_gh_asset_name(basename) asset_label = basename for asset in get_release_assets(release, include_incomplete=True): if asset_name == asset.name: # We want to tread incomplete assets as if they weren't there # so replace them always if replace or not asset_is_complete(asset): asset.delete_asset() else: print( f"Skipping upload for {asset_name} as {asset_label}, already exists" ) return release.upload_asset(str(path), label=asset_label, name=asset_name) print(f"Uploaded {asset_name} as {asset_label}")
def publish_release(release: GitRelease) -> None: """Publish draft release""" print("Publishing new release...") release.update_release( name=release.title, message=release.body, draft=False, )
def _find_source_asset(self, release: GitRelease): """Find the right asset.""" assets = release.get_assets() regex = compile(self.config.source_regex) candidates = {} for asset in assets: if regex.fullmatch(asset.name) is not None: candidates[asset.name] = asset if len(candidates) == 0: raise Exception("No valid assets found.") elif len(candidates) > 1: # Multiple candidates found! # Lets check if they are all the same size size: Optional[int] = None for candidate in candidates.values(): if size is None: size = candidate.size if candidate.size != size: # Multiple distinct assets. assets = sorted(candidates.values(), key=lambda x: x.name) return assets[0] # All the same size return list(candidates.values())[0]
def __get_barrel_asset(self, release: GitRelease) -> GitReleaseAsset: # Matching tag download the barrels for asset in release.get_assets(): if self.BARREL_FILE.match(asset.name) is not None: return asset raise Error( "No barrel asset found in release: {rel}".format(rel=release.tag_name) )
def get_assets(release: GitRelease): try: assets = release.get_assets() downloadables = [] for asset in assets: downloadables.append(get_asset(asset)) return downloadables except GithubException as e: print(" No assets found")
def _get_release_by_tag(tag, use_token): if use_token: token = os.environ.get('GITHUB_TOKEN', False) or open('.token').readline().replace('\n', '') g = Github(token) else: g = Github() repo = g.get_user(OWNER).get_repo(REPO) headers, data = repo._requester.requestJsonAndCheck( "GET", repo.url + f'/releases/tags/{tag}' ) return GitRelease(repo._requester, headers, data, completed=True)
def add_binaries_to_github_release(github_release: GitRelease) -> None: """ Add binaries to a GitHub release. """ # We need to make the artifacts just after creating a tag so that the # --version output is exactly the one of the tag. # We fetch the latest tags, including the one which was just created. for args in ( ['git', 'fetch', '--tags'], ['git', 'merge', 'origin/master'], ['git', 'status'], ): subprocess.run(args=args, check=True) linux_artifacts = make_linux_binaries(repo_root=Path('.')) for installer_path in linux_artifacts: github_release.upload_asset( path=str(installer_path), label=installer_path.name + '-linux', ) # Remove the installer so that it is not later uploaded by twine. installer_path.unlink()
def get_release_assets(release: GitRelease, include_incomplete=False) -> List[GitReleaseAsset]: assets = [] for asset in release.get_assets(): # skip in case not fully uploaded yet (or uploading failed) if not asset_is_complete(asset) and not include_incomplete: continue uploader = asset.uploader if uploader.type != "Bot" or uploader.login != "github-actions[bot]": raise SystemExit( f"ERROR: Asset '{get_asset_filename(asset)}' not uploaded " f"by GHA but '{uploader.login}'. Aborting.") assets.append(asset) return assets
def get_release_assets(release: GitRelease, include_incomplete=False) -> List[GitReleaseAsset]: assets = [] for asset in release.get_assets(): # skip in case not fully uploaded yet (or uploading failed) if not asset_is_complete(asset) and not include_incomplete: continue uploader = asset.uploader uploader_key = (uploader.type, uploader.login) # We allow uploads from some users and GHA if uploader_key not in ALLOWED_UPLOADERS: raise SystemExit(f"ERROR: Asset '{get_asset_filename(asset)}' " f"uploaded by {uploader_key}'. Aborting.") assets.append(asset) return assets
def _find_release_asset(release: GitRelease.GitRelease, asset: str) -> str: """Return the requested asset's download url from the given release. If no specific asset is requested, it will return the first one it comes across. :exception ghau.errors.ReleaseAssetError: No asset by given name was found. :exception ghau.errors.NoAssetsFoundError: No assets found for given release.""" al = release.get_assets() if al.totalCount == 0: raise ge.NoAssetsFoundError(release.tag_name) if asset is None: return al[0].browser_download_url for item in al: if item.name == asset: log.debug( f"Found asset {item.name} with URL: {item.browser_download_url}" ) return item.browser_download_url raise ge.ReleaseAssetError(release.tag_name, asset)
def _find_release_asset(release: GitRelease.GitRelease, asset: str, debug: bool) -> str: # TODO: detect asset use regex """Return the requested asset's download url from the given release. If no specific asset is requested, it will return the first one it comes across. :exception ghau.errors.ReleaseAssetError: No asset by given name was found. :exception ghau.errors.NoAssetsFoundError: No assets found for given release.""" al = release.get_assets() if al.totalCount == 0: # if there are no assets, abort. raise ge.NoAssetsFoundError(release.tag_name) if asset is None: # if no specific asset is requested, download the first it finds. return al[0].browser_download_url for item in al: # otherwise, look for the specific asset requested. if item.name == asset: gf.message( "Found asset {} with URL: {}".format( item.name, item.browser_download_url), "debug") return item.browser_download_url raise ge.ReleaseAssetError( release.tag_name, asset) # no asset found by requested name? abort.
def test_publish_release_final(py_package): runner = CliRunner() version_spec = "1.5.1rc0" changelog = py_package / "CHANGELOG.md" # Prep the env result = runner.invoke(cli.main, ["prep-env", "--version-spec", version_spec]) assert result.exit_code == 0, result.output # Prep the changelog with patch("release_helper.cli.generate_activity_md") as mocked_gen: mocked_gen.return_value = CHANGELOG_ENTRY result = runner.invoke( cli.main, ["prep-changelog", "--changelog-path", changelog]) assert result.exit_code == 0, result.output # Create the dist files run("python -m build .") # Finalize the release result = runner.invoke(cli.main, ["prep-release"]) # Publish the release repo = Repository(None, dict(), dict(), True) release = GitRelease(None, dict(), dict(), True) repo.create_git_release = release_mock = MagicMock(return_value=release) release.delete_release = delete_mock = MagicMock() with patch.object(cli.Github, "get_repo", return_value=repo) as mock_method: result = runner.invoke( cli.main, ["publish-release", "--post-version-spec", "1.5.2.dev0"]) assert result.exit_code == 0, result.output release_mock.assert_called_once() delete_mock.assert_not_called()
def get_assets(self, rel: GitRelease) -> List[GitReleaseAsset]: return list(rel.get_assets())