def _is_newer_version(installed, latest): try: iv = SemVer(installed, partial=True) lv = SemVer(latest, partial=True) return lv > iv except: return False
async def download(self, collection_downloader: CollectionDownloader): missing_versions = set(self.versions) while missing_versions: missing_version = max(missing_versions) # Try to get hold of changelog for this version changelog = await self._download_changelog_stream( missing_version, collection_downloader) if changelog: current_changelog = self.changelog if current_changelog is None: # If we didn't have a changelog so far, start with it self.changelog = changelog missing_versions -= { SemVer(version) for version in changelog.changes.releases } else: # Insert entries from changelog into combined changelog that are missing there for version, entry in changelog.changes.releases.items(): sem_version = SemVer(version) if sem_version in missing_versions: current_changelog.changes.releases[version] = entry missing_versions.remove(sem_version) # Make sure that this version isn't checked again missing_versions -= {missing_version}
async def _download_changelog_stream( self, start_version: SemVer, collection_downloader: CollectionDownloader ) -> t.Optional[ChangelogData]: changelog = await self._get_changelog(start_version, collection_downloader) if changelog is None: return None changelog.changes.prune_versions(versions_after=None, versions_until=str(start_version)) changelogs = [changelog] ancestor = changelog.changes.ancestor while ancestor is not None: ancestor_ver = SemVer(ancestor) if ancestor_ver < self.earliest: break changelog = await self._get_changelog(ancestor_ver, collection_downloader) if changelog is None: break changelog.changes.prune_versions(versions_after=None, versions_until=ancestor) changelogs.append(changelog) ancestor = changelog.changes.ancestor return ChangelogData.concatenate(changelogs)
async def download(self, collection_downloader: CollectionDownloader): changelog = await self._get_changelog(self.latest, collection_downloader) if changelog is None: return changelog.changes.prune_versions(versions_after=None, versions_until=str(self.latest)) changelogs = [changelog] ancestor = changelog.changes.ancestor while ancestor is not None: ancestor_ver = SemVer(ancestor) if ancestor_ver < self.earliest: break changelog = await self._get_changelog(ancestor_ver, collection_downloader) if changelog is None: break changelog.changes.prune_versions(versions_after=None, versions_until=ancestor) changelogs.append(changelog) ancestor = changelog.changes.ancestor self.changelog = ChangelogData.concatenate(changelogs)
def build_single_impl(dependency_data: DependencyFileData, add_release: bool = True) -> None: app_ctx = app_context.app_ctx.get() # Determine included collection versions ansible_base_version = PypiVer(dependency_data.ansible_base_version) included_versions = { collection: SemVer(version) for collection, version in dependency_data.deps.items() } with tempfile.TemporaryDirectory() as tmp_dir: download_dir = os.path.join(tmp_dir, 'collections') os.mkdir(download_dir, mode=0o700) # Download included collections asyncio.run(download_collections(included_versions, app_ctx.galaxy_url, download_dir, app_ctx.extra['collection_cache'])) # Get Ansible changelog, add new release ansible_changelog = ChangelogData.ansible( app_ctx.extra['data_dir'], app_ctx.extra['dest_data_dir']) if add_release: date = datetime.date.today() ansible_changelog.add_ansible_release( str(app_ctx.extra['ansible_version']), date, f'Release Date: {date}' f'\n\n' f'`Porting Guide <https://docs.ansible.com/ansible/devel/porting_guides.html>`_') # Get changelog and porting guide data changelog = get_changelog( app_ctx.extra['ansible_version'], deps_dir=app_ctx.extra['data_dir'], deps_data=[dependency_data], collection_cache=app_ctx.extra['collection_cache'], ansible_changelog=ansible_changelog) # Create package and collections directories package_dir = os.path.join(tmp_dir, f'ansible-{app_ctx.extra["ansible_version"]}') os.mkdir(package_dir, mode=0o700) ansible_collections_dir = os.path.join(package_dir, 'ansible_collections') os.mkdir(ansible_collections_dir, mode=0o700) # Write the ansible release info to the collections dir write_release_py(app_ctx.extra['ansible_version'], ansible_collections_dir) # Install collections # TODO: PY3.8: # collections_to_install = [p for f in os.listdir(download_dir) # if os.path.isfile(p := os.path.join(download_dir, f))] collections_to_install = [] for collection in os.listdir(download_dir): path = os.path.join(download_dir, collection) if os.path.isfile(path): collections_to_install.append(path) asyncio.run(install_together(collections_to_install, ansible_collections_dir)) # Compose and write release notes release_notes = ReleaseNotes.build(changelog) release_notes.write_changelog_to(package_dir) release_notes.write_porting_guide_to(package_dir) # Write build scripts and files write_build_script(app_ctx.extra['ansible_version'], ansible_base_version, package_dir) write_python_build_files(app_ctx.extra['ansible_version'], ansible_base_version, '', package_dir, release_notes, app_ctx.extra['debian']) if app_ctx.extra['debian']: write_debian_directory(app_ctx.extra['ansible_version'], ansible_base_version, package_dir) make_dist(package_dir, app_ctx.extra['sdist_dir']) # Write changelog and porting guide also to destination directory release_notes.write_changelog_to(app_ctx.extra['dest_data_dir']) release_notes.write_porting_guide_to(app_ctx.extra['dest_data_dir']) if add_release: ansible_changelog.changes.save()
def __init__(self, collection: str, versions: t.ValuesView[str]): self.collection = collection self.versions = sorted(SemVer(version) for version in versions) self.earliest = self.versions[0] self.latest = self.versions[-1] self.changelog = None
from packaging.version import Version as PypiVer from semantic_version import Version as SemVer import pytest from antsibull.dependency_files import BuildFile SIMPLE_TEST_FILE = """_ansible_version: 4 _ansible_base_version: 2.11.0rc1 community.general: >=1.0.0,<2.0.0 community.routeros: >=2.0.0-a2,<3.0.0 """ SIMPLE_TEST_DEPS = { 'community.general': SemVer('1.0.0'), 'community.routeros': SemVer('2.0.0-a2'), } @pytest.mark.parametrize('dependencies, file_contents', ((SIMPLE_TEST_DEPS, SIMPLE_TEST_FILE), )) def test_build_file_write(tmpdir, dependencies, file_contents): filename = tmpdir / 'test.build' bf = BuildFile(filename) bf.write(PypiVer('4.0.0'), '2.11.0rc1', dependencies) with open(filename) as f: assert f.read() == file_contents
def versionsCompatible(remote, local): rv = SemVer(remote, partial=True) lv = SemVer(local, partial=True) if rv.major == 0: return rv.major == lv.major and rv.minor == lv.minor return rv.major == lv.major and rv.minor >= lv.minor