diff --git a/.github/workflows/publish-pypi.yaml b/.github/workflows/publish-pypi.yaml new file mode 100644 index 000000000..7640d89ea --- /dev/null +++ b/.github/workflows/publish-pypi.yaml @@ -0,0 +1,30 @@ +name: Publish + +on: + push: + tags: + - '[1-9]+.[0-9]+.[0-9]+' + +env: + PIP_DISABLE_PIP_VERSION_CHECK: '1' + PY_COLORS: '1' + +jobs: + pypi: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Install build tools + run: pip install tox + - name: Verify package version is same as Git tag + run: tox run -qe ensure_version_matches -- $GIT_TAG + env: + GIT_TAG: ${{ github.ref_name }} + - name: Build package and upload to PyPI + run: tox run -e package -- upload + env: + TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} + TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} diff --git a/.gitignore b/.gitignore index e2c300205..242024fd7 100644 --- a/.gitignore +++ b/.gitignore @@ -137,6 +137,7 @@ dmypy.json # backups *~ /charmcraft/_version.py +/results/ # Spread files .spread-reuse*.yaml diff --git a/HOWTO_RELEASE.md b/HOWTO_RELEASE.md index fe8bce2cd..1ad38a3e9 100644 --- a/HOWTO_RELEASE.md +++ b/HOWTO_RELEASE.md @@ -60,8 +60,8 @@ paste, but do please pay attention to details! - build a tarball to test - rm -rf dist/ - ./setup.py sdist bdist_wheel + tox -e clean + tox -e package - try the tarball @@ -89,7 +89,10 @@ paste, but do please pay attention to details! git push --tags -- release in Github + For a new tag, this will trigger publishing a release of the Python + package on PyPI via GHA. + +- release on GitHub xdg-open https://github.com/canonical/charmcraft/tags @@ -101,10 +104,6 @@ paste, but do please pay attention to details! Click on "Publish release" -- release to PyPI - - fades -d twine -x twine upload --verbose dist/* - - release to Snap Store (for all the archs) snapcraft upload charmcraft_X.Y.Z_amd64.snap --release=edge,candidate diff --git a/pyproject.toml b/pyproject.toml index 8329b6e31..559a38f24 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,8 @@ [project] name = "charmcraft" +dynamic = ["version"] description = "The main tool to build, upload, and develop in general the Juju charms." -dynamic = ["version", "readme"] +readme = "README.md" dependencies = [ "craft-application~=2.0", "craft-cli>=2.3.0", @@ -83,9 +84,6 @@ requires = [ ] build-backend = "setuptools.build_meta" -[tool.setuptools.dynamic] -readme = {file = "README.md"} - [tool.setuptools_scm] write_to = "charmcraft/_version.py" # the version comes from the latest annotated git tag formatted as 'X.Y.Z' diff --git a/tox.ini b/tox.ini index 0cbef9470..8f4d18954 100644 --- a/tox.ini +++ b/tox.ini @@ -115,3 +115,31 @@ env_dir = {work_dir}/pre-commit runner = ignore_env_name_mismatch description = Run pre-commit on staged files or arbitrary pre-commit commands (tox run -e pre-commit -- [args]) commands = pre-commit {posargs:run} + +[testenv:clean] +description = Clean up bytecode and build artifacts +skip_install = true +deps = pyclean +commands = pyclean {posargs:. --debris --erase results/* results/ --yes} + +[testenv:ensure_version_matches] +description = Verify package version is same as Git tag +deps = +commands = python -c 'import os; from importlib.metadata import version; pkg, tag = os.environ["PKG_NAME"], os.environ["GIT_TAG"]; ver = version(pkg); error = f"`{ver}` != `{tag}`"; abort = f"Package version does not match the Git tag ({error}). ABORTING."; raise SystemExit(0 if ver and tag and ver == tag else abort)' +setenv = + PKG_NAME=charmcraft + GIT_TAG={posargs} + +[testenv:package] +description = Build package and check metadata (or upload package) +skip_install = true +deps = + build + twine +commands = + python -m build + twine {posargs:check --strict} dist/* +passenv = + TWINE_USERNAME + TWINE_PASSWORD + TWINE_REPOSITORY_URL