diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..f26666b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,48 @@ +name: release +run-name: Release ${{ inputs.ref || github.ref_name }} + +on: + release: + types: [published] + workflow_dispatch: + inputs: + ref: + type: string + description: 'Tag to release' + required: true + +permissions: {} + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ inputs.ref }} + persist-credentials: false + - uses: hynek/build-and-inspect-python-package@2abe76da66d0a6a4a227101f9348ee855797cfa5 # v3.0.1 + + deploy: + needs: [build] + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/testcloud + permissions: + id-token: write + attestations: write + + steps: + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: Packages + path: dist + + - name: Generate artifact attestation for sdist and wheel + uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 + with: + subject-path: "dist/*" + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2 diff --git a/.packit.yaml b/.packit.yaml new file mode 100644 index 0000000..0c76b65 --- /dev/null +++ b/.packit.yaml @@ -0,0 +1,63 @@ +--- + +specfile_path: packaging/rpm/testcloud.spec +files_to_sync: + - src: packaging/rpm/ + dest: ./ + delete: true + filters: + - "protect .git*" + - "protect sources" + - "protect changelog" + - .packit.yaml + +upstream_package_name: testcloud +downstream_package_name: testcloud + +upstream_project_url: https://github.com/teemtee/testcloud +issue_repository: https://github.com/teemtee/testcloud + +srpm_build_deps: + - hatch + - python3-hatch-vcs + +actions: + create-archive: + - hatch build -t sdist + - bash -c "echo dist/testcloud-$PACKIT_PROJECT_VERSION.tar.gz" + get-current-version: + - hatch version + +targets: &all-targets + - fedora-all + - epel-9 + - epel-10 + +jobs: + # Build pull requests + - job: copr_build + trigger: pull_request + + # Propose downstream pull requests + - job: propose_downstream + trigger: release + dist_git_branches: + rawhide: + fast_forward_merge_into: + - fedora-branched + - epel-10 + - epel-9 + + # Create koji builds + - job: koji_build + trigger: commit + allowed_pr_authors: ["packit", "all_committers"] + dist_git_branches: *all-targets + + # Create bodhi updates + - job: bodhi_update + trigger: commit + dist_git_branches: + - fedora-branched + - epel-10 + - epel-9 diff --git a/docs/source/conf.py b/docs/source/conf.py index 248b414..57d5bf9 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -12,6 +12,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. +import importlib.metadata import sys import os @@ -55,7 +56,7 @@ # built documents. # # The short X.Y version. -version = "0.11.8" +version = importlib.metadata.version("testcloud") # The full version, including alpha/beta/rc tags. release = version diff --git a/packaging/rpm/testcloud.spec b/packaging/rpm/testcloud.spec new file mode 100644 index 0000000..f8becd6 --- /dev/null +++ b/packaging/rpm/testcloud.spec @@ -0,0 +1,126 @@ +%if 0%{?rhel} <= 9 +%global _sysusersdir /usr/lib/sysusers.d +%endif + +Name: testcloud +Version: 0.0.0 +Release: %autorelease +Summary: Tool for running cloud images locally + +License: GPL-2.0-or-later +URL: https://github.com/teemtee/testcloud +Source0: %{pypi_source testcloud} +Source1: testcloud.sysusers + +ExclusiveArch: %{kernel_arches} noarch +BuildArch: noarch + +BuildRequires: systemd-rpm-macros +%{?sysusers_requires_compat} + +Requires: polkit + +Recommends: edk2-ovmf + +Requires: python3-%{name} = %{version}-%{release} + +%description +testcloud is a relatively simple system which is capable of booting images +designed for cloud systems on a local system with minimal configuration. +testcloud is designed to be (and remain) somewhat simple, trading fancy cloud +system features for ease of use and sanity in development. + +%package -n python3-%{name} +Summary: Python 3 interface to testcloud + +BuildRequires: bash-completion +BuildRequires: python3-devel +BuildRequires: python3-pytest + +Requires: acl +Requires: genisoimage +Requires: libvirt-daemon +Requires: libvirt-daemon-config-network +Requires: libvirt-daemon-driver-qemu +Requires: libvirt-daemon-driver-storage-core +Recommends: butane +Suggests: python3-libguestfs +Suggests: libguestfs-tools-c + +%description -n python3-%{name} +Python 3 interface to testcloud. + +%pre +%sysusers_create_compat %{SOURCE1} + +%prep +%autosetup -n %{name}-%{version} -p1 +# Drop coverage testing +sed -i 's/ --cov-report=term-missing --cov testcloud//g' tox.ini + +%generate_buildrequires +%pyproject_buildrequires + +%build +export SETUPTOOLS_SCM_PRETEND_VERSION=%{version} +%pyproject_wheel + +%install +%pyproject_install +%pyproject_save_files testcloud + +# man page +mkdir -p %{buildroot}%{_mandir}/man1 +install -pm 644 manpages/testcloud.1 %{buildroot}%{_mandir}/man1 + +# bash completion +mkdir -p %{buildroot}%{_datadir}/bash-completion/completions +install -pm 644 conf/testcloud %{buildroot}%{_datadir}/bash-completion/completions/testcloud + +# configuration files +mkdir -p %{buildroot}%{_sysconfdir}/testcloud/ +install conf/settings-example.py %{buildroot}%{_sysconfdir}/testcloud/settings.py + +# Create running directory for testcloud +install -d %{buildroot}%{_sharedstatedir}/testcloud/ + +# backingstores dir +install -d %{buildroot}/%{_sharedstatedir}/testcloud/backingstores + +# instance dir +install -d %{buildroot}/%{_sharedstatedir}/testcloud/instances + +# create polkit rules dir and install polkit rule +mkdir -p %{buildroot}%{_sysconfdir}/polkit-1/rules.d +install conf/99-testcloud-nonroot-libvirt-access.rules %{buildroot}%{_sysconfdir}/polkit-1/rules.d/99-testcloud-nonroot-libvirt-access.rules + +# sysusers conf file for creation of testcloud group +install -p -m644 -D %{SOURCE1} %{buildroot}%{_sysusersdir}/%{name}.conf + +%check +%pyproject_check_import +%pytest + +%files +%doc README.md +%{_mandir}/man1/testcloud.1* +%license LICENSE + +%dir %{_sysconfdir}/testcloud +%dir %attr(0775, qemu, testcloud) %{_sharedstatedir}/testcloud +%dir %attr(0775, qemu, testcloud) %{_sharedstatedir}/testcloud/backingstores +%dir %attr(0775, qemu, testcloud) %{_sharedstatedir}/testcloud/instances + +%attr(0644, root, root) %{_sysconfdir}/polkit-1/rules.d/99-testcloud-nonroot-libvirt-access.rules + +%config(noreplace) %{_sysconfdir}/testcloud/settings.py +%{_bindir}/testcloud +%{_bindir}/t7d +%{_datadir}/bash-completion/completions/testcloud + +%{_sysusersdir}/%{name}.conf + +%files -n python3-%{name} -f %{pyproject_files} + +%changelog +%autochangelog diff --git a/packaging/rpm/testcloud.sysusers b/packaging/rpm/testcloud.sysusers new file mode 100644 index 0000000..6d2797f --- /dev/null +++ b/packaging/rpm/testcloud.sysusers @@ -0,0 +1 @@ +g testcloud - diff --git a/pyproject.toml b/pyproject.toml index 19e23dc..778e8ce 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,42 @@ +[build-system] +requires = ["hatchling", "hatch-vcs"] +build-backend = "hatchling.build" + +[project] +name = "testcloud" +dynamic = ["version"] +description = "A tool to download and boot cloud images locally, with an easy to use API." +readme = "README.md" +license = "GPL-2.0-or-later" +requires-python = ">=3.9" +authors = [ + {name = "Mike Ruckman", email = "roshi@fedoraproject.org"}, +] +dependencies = [ + "libvirt-python", + "peewee", + "requests", + "packaging", + "fedora-distro-aliases>=1.5", +] + +[project.optional-dependencies] +image_resolve_caching = ["requests_cache>=1.2"] + +[project.scripts] +testcloud = "testcloud.cli:main" +t7d = "testcloud.cli:main" + +[project.urls] +Homepage = "https://github.com/teemtee/testcloud" + +[tool.hatch.version] +source = "vcs" +raw-options.version_scheme = "release-branch-semver" +raw-options.git_describe_command = [ + "git", "describe", "--dirty", "--tags", "--long", + "--abbrev=9", "--match", "*[0-9]*", +] + [tool.black] line-length=140 diff --git a/setup.py b/setup.py deleted file mode 100644 index 2878068..0000000 --- a/setup.py +++ /dev/null @@ -1,73 +0,0 @@ -import codecs -import os -import re - -from setuptools import Command, setup - -here = os.path.abspath(os.path.dirname(__file__)) - - -def read(*parts): - return codecs.open(os.path.join(here, *parts), "r").read() - - -def find_version(*file_paths): - version_file = read(*file_paths) - version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M) - if version_match: - return version_match.group(1) - raise RuntimeError("Unable to find version string.") - - -class PyTest(Command): - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - import subprocess - - errno = subprocess.call(["pytest-3"]) - raise SystemExit(errno) - - -with open("README.md") as f: - long_description_readme = f.read() - -setup( - name="testcloud", - version=find_version("testcloud", "__init__.py"), - description="A tool to download and boot cloud images locally, with an easy to use API.", - long_description=long_description_readme, - long_description_content_type="text/markdown", - author="Mike Ruckman", - author_email="roshi@fedoraproject.org", - license="GPLv2+", - url="https://pagure.io/testcloud", - packages=["testcloud", "testcloud.distro_utils"], - package_dir={"testcloud": "testcloud"}, - include_package_data=True, - cmdclass={"test": PyTest}, - entry_points=dict( - console_scripts=[ - "testcloud=testcloud.cli:main", - "t7d=testcloud.cli:main", - ] - ), - data_files=[ - ("share/man/man1", ["manpages/testcloud.1"]), - ("share/bash-completion/completions", ["conf/testcloud"]), - ], - install_requires=[ - "libvirt-python", - "peewee", - "requests", - "packaging", - "fedora-distro-aliases>=1.5", - ], - extras_require={"image_resolve_caching": ["requests_cache>=1.2"]}, -) diff --git a/testcloud/__init__.py b/testcloud/__init__.py index b96827f..b07421a 100644 --- a/testcloud/__init__.py +++ b/testcloud/__init__.py @@ -1,10 +1,10 @@ -# NOTE: if you update version, *make sure* to also update `docs/source/conf.py` -__version__ = "0.11.8" - +import importlib.metadata import signal import sys import threading +__version__ = importlib.metadata.version(__name__) + def sigterm_handler(_signo, _stack_frame): # A call to sys.exit() is translated into an exception so that clean-up handlers