Skip to content

Commit f14ec12

Browse files
authored
Merge pull request #255 from beeware/ci-cleanup
Modify CI workflow so that wheels built for test are used for release
2 parents e198bb0 + 1f8ba81 commit f14ec12

File tree

13 files changed

+256
-130
lines changed

13 files changed

+256
-130
lines changed

.github/workflows/ci.yml

+49-20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
push:
55
branches:
66
- main
7+
workflow_call:
78

89
jobs:
910
pre-commit:
@@ -19,39 +20,62 @@ jobs:
1920
- name: Lint with Pre-commit
2021
uses: pre-commit/[email protected]
2122

22-
beefore:
23-
name: Pre-test checks
23+
towncrier:
2424
runs-on: macos-latest
25-
strategy:
26-
matrix:
27-
task:
28-
- "towncrier-check"
29-
- "package"
3025
steps:
31-
- name: Check out code
26+
# Fetch main branch for comparison, then check out current branch.
27+
- name: Check out main branch
28+
uses: actions/[email protected]
29+
with:
30+
fetch-depth: 0
31+
ref: main
32+
- name: Check out branch
3233
uses: actions/[email protected]
3334
with:
3435
fetch-depth: 0
3536
- name: Set up Python
3637
uses: actions/[email protected]
3738
with:
3839
python-version: "3.X"
39-
- name: Install dependencies
40+
- name: Install dev dependencies
4041
run: |
41-
python -m pip install --upgrade pip
42-
python -m pip install --upgrade setuptools
43-
python -m pip install tox
42+
# We don't actually want to install rubicon;
43+
# we just want the dev etras so we have a known version of tox
44+
python -m pip install -e .[dev]
4445
- name: Run pre-test check
4546
run: |
46-
tox -e ${{ matrix.task }}
47+
tox -e towncrier-check
48+
49+
package:
50+
runs-on: macos-latest
51+
steps:
52+
# Fetch all refs so setuptools_scm can generate the correct version number.
53+
- uses: actions/[email protected]
54+
with:
55+
fetch-depth: 0
56+
- uses: actions/[email protected]
57+
with:
58+
python-version: "3.X"
59+
- name: Install dev dependencies
60+
run: |
61+
# We don't actually want to install rubicon;
62+
# we just want the dev extras so we have a known version of tox
63+
python -m pip install -e .[dev]
64+
- name: Build wheels
65+
run: tox -e package
66+
- uses: actions/upload-artifact@v3
67+
with:
68+
name: packages
69+
path: dist
70+
if-no-files-found: error
4771

4872
unit-tests:
4973
name: Unit tests
50-
needs: [pre-commit, beefore]
74+
needs: [pre-commit, towncrier, package]
5175
strategy:
5276
matrix:
5377
platform: ["macOS-11", "macOS-12"]
54-
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11", "3.12-dev"]
78+
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12-dev"]
5579
include:
5680
- experimental: false
5781
- python-version: "3.12-dev"
@@ -67,11 +91,16 @@ jobs:
6791
uses: actions/[email protected]
6892
with:
6993
python-version: ${{ matrix.python-version }}
70-
- name: Install dependencies
94+
- name: Get packages
95+
uses: actions/download-artifact@v3
96+
with:
97+
name: packages
98+
path: dist
99+
- name: Install dev dependencies
71100
run: |
72-
python -m pip install --upgrade pip
73-
python -m pip install --upgrade setuptools
74-
python -m pip install tox
101+
# We don't actually want to install rubicon;
102+
# we just want the dev extras so we have a known version of tox.
103+
python -m pip install $(ls dist/rubicon_objc-*.whl)[dev]
75104
- name: Test
76105
run: |
77-
tox -e py
106+
tox -e py --installpkg dist/rubicon_objc-*.whl

.github/workflows/publish.yml

+11-20
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,15 @@ on:
66

77
jobs:
88
deploy:
9-
runs-on: macos-latest
9+
runs-on: ubuntu-latest
1010
steps:
11-
- uses: actions/[email protected]
12-
- name: Set up Python
13-
uses: actions/[email protected]
14-
with:
15-
python-version: "3.x"
16-
- name: Install dependencies
17-
run: |
18-
python -m pip install --upgrade pip
19-
python -m pip install --upgrade setuptools
20-
python -m pip install tox
21-
- name: Build release artefacts
22-
run: |
23-
tox -e package
24-
- name: Publish release
25-
env:
26-
TWINE_USERNAME: __token__
27-
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
28-
run: |
29-
tox -e publish
11+
- uses: dsaltares/[email protected]
12+
with:
13+
version: tags/${{ github.event.release.tag_name }}
14+
file: ${{ github.event.repository.name }}.*
15+
regex: true
16+
target: dist/
17+
- name: Publish release to production PyPI
18+
uses: pypa/gh-action-pypi-publish@release/v1
19+
with:
20+
password: ${{ secrets.PYPI_PASSWORD }}

.github/workflows/release.yml

+51-11
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,59 @@ on:
66
- "v*"
77

88
jobs:
9-
build:
9+
ci:
10+
uses: ./.github/workflows/ci.yml
11+
12+
release:
1013
name: Create Release
11-
runs-on: macos-latest
14+
needs: [ci]
15+
# This has to be run on macOS, because rubicon tries to load the Foundation library
16+
runs-on: macOS-latest
17+
permissions:
18+
contents: write
1219
steps:
13-
- name: Checkout code
14-
uses: actions/[email protected]
20+
- name: Set build variables
21+
run: |
22+
echo "VERSION=${GITHUB_REF_NAME#v}" >> $GITHUB_ENV
23+
- name: Set up Python
24+
uses: actions/[email protected]
25+
with:
26+
python-version: '3.X'
27+
- name: Get packages
28+
uses: actions/download-artifact@v3
29+
with:
30+
name: packages
31+
path: dist
32+
- name: Install packages
33+
run: pip install dist/rubicon_objc-*.whl
34+
- name: Check version number
35+
# Check that the setuptools_scm-generated version number is still the same when
36+
# installed from a wheel with setuptools_scm not present.
37+
run: |
38+
set -x
39+
test $(python -c "from rubicon.objc import __version__; print(__version__)") = $VERSION
1540
- name: Create Release
16-
id: create_release
17-
uses: actions/create-release@v1
18-
env:
19-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41+
uses: ncipollo/[email protected]
2042
with:
21-
tag_name: ${{ github.ref }}
22-
release_name: ${{ github.ref }}
43+
name: ${{ env.VERSION }}
2344
draft: true
24-
prerelease: false
45+
artifacts: dist/*
46+
artifactErrorsFailBuild: true
47+
48+
test-publish:
49+
name: Publish test package
50+
needs: [release]
51+
runs-on: ubuntu-latest
52+
permissions:
53+
contents: write
54+
steps:
55+
- name: Get packages
56+
uses: actions/download-artifact@v3
57+
with:
58+
name: packages
59+
path: dist
60+
- name: Publish release to Test PyPI
61+
uses: pypa/gh-action-pypi-publish@release/v1
62+
with:
63+
repository_url: https://test.pypi.org/legacy/
64+
password: ${{ secrets.TEST_PYPI_PASSWORD }}

changes/254.misc.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
The CI configuration was modified to publish the same artefacts used for testing, with a version number coming from git.

changes/371.feature.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Support for Python 3.6 was dropped.

docs/conf.py

+2-12
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
# serve to show the default.
1111

1212
import os
13-
import re
1413
import sys
14+
from importlib.metadata import version as metadata_version
1515

1616
# If extensions (or modules to document with autodoc) are in another directory,
1717
# add these directories to sys.path here. If the directory is relative to the
@@ -48,17 +48,7 @@
4848
# built documents.
4949
#
5050
# The full version, including alpha/beta/rc tags.
51-
with open("../src/rubicon/objc/__init__.py", encoding="utf8") as version_file:
52-
version_match = re.search(
53-
r"^__version__ = ['\"]([^'\"]*)['\"]", version_file.read(), re.MULTILINE
54-
)
55-
if version_match:
56-
release = version_match.group(1)
57-
else:
58-
raise RuntimeError("Unable to find version string.")
59-
60-
# The short X.Y version.
61-
version = ".".join(release.split(".")[:2])
51+
version = metadata_version("rubicon-objc")
6252

6353
autoclass_content = "both"
6454

docs/how-to/internal/release.rst

+39-22
Original file line numberDiff line numberDiff line change
@@ -21,46 +21,63 @@ The procedure for cutting a new release is as follows:
2121

2222
Check that the HEAD of release now matches upstream/main.
2323

24-
2. Make sure the branch is ready for release. Ensure that:
24+
2. Ensure that the release notes are up to date. Run::
2525

26-
1. The version number has been bumped.
27-
28-
2. The release notes are up to date. If they are, the `changes
29-
<https://github.com/beeware/rubicon-objc/tree/main/changes>`__ directory
30-
should be empty, except for the ``template.rst`` file.
31-
32-
These two changes (the version bump and release notes update) should go
33-
through the normal pull request and review process. They should generally
34-
comprise the last PR merged before the release occurs.
35-
36-
If the version number *hasn't* been updated, or ``changes`` directory
37-
*isn't* empty, you need to create a PR (using the normal development
38-
process) that contains these changes. Run::
39-
40-
$ tox -e towncrier -- --draft
26+
$ tox -e towncrier -- --draft
4127

4228
to review the release notes that will be included, and then::
4329

4430
$ tox -e towncrier
4531

46-
to generate the updated release notes. Submit the PR; once it's been
47-
reviewed and merged, you can restart the release process from step 1.
32+
to generate the updated release notes.
4833

4934
3. Tag the release, and push the tag upstream::
5035

5136
$ git tag v1.2.3
37+
$ git push upstream HEAD:main
5238
$ git push upstream v1.2.3
5339

5440
4. Pushing the tag will start a workflow to create a draft release on GitHub.
5541
You can `follow the progress of the workflow on GitHub
5642
<https://github.com/beeware/rubicon-objc/actions?query=workflow%3A%22Create+Release%22>`__;
5743
once the workflow completes, there should be a new `draft release
58-
<https://github.com/beeware/rubicon-objc/releases>`__.
59-
60-
5. Edit the GitHub release. Add release notes (you can use the text generated
44+
<https://github.com/beeware/rubicon-objc/releases>`__, and an entry on the
45+
`Test PyPI server <https://test.pypi.org/project/rubicon-objc/>`__.
46+
47+
Confirm that this action successfully completes. If it fails, there's a
48+
couple of possible causes:
49+
50+
a. The final upload to Test PyPI failed. Test PyPI is not have the same
51+
service monitoring as PyPI-proper, so it sometimes has problems. However,
52+
it's also not critical to the release process; if this step fails, you can
53+
perform Step 6 by manually downloading the "packages" artifact from the
54+
GitHub workflow instead.
55+
b. Something else fails in the build process. If the problem can be fixed
56+
without a code change to the Rubicon-ObjC repository (e.g., a transient
57+
problem with build machines not being available), you can re-run the
58+
action that failed through the Github Actions GUI. If the fix requires a
59+
code change, delete the old tag, make the code change, and re-tag the
60+
release.
61+
62+
5. Create a clean virtual environment, install the new release from Test PyPI, and
63+
perform any pre-release testing that may be appropriate::
64+
65+
$ python3 -m venv testvenv
66+
$ . ./testvenv/bin/activate
67+
(testvenv) $ pip install --extra-index-url https://test.pypi.org/simple/ rubicon-objc==1.2.3
68+
(testvenv) $ python -c "from rubicon.objc import __version__; print(__version__)"
69+
1.2.3
70+
(testvenv) $ ... any other manual checks you want to perform ...
71+
72+
6. Log into ReadTheDocs, visit the `Versions tab
73+
<https://readthedocs.org/projects/rubicon-objc/versions/>`__, and activate the
74+
new version. Ensure that the build completes; if there's a problem, you
75+
may need to correct the build configuration, roll back and re-tag the release.
76+
77+
7. Edit the GitHub release. Add release notes (you can use the text generated
6178
by towncrier). Check the pre-release checkbox (if necessary).
6279

63-
6. Double check everything, then click Publish. This will trigger a
80+
8. Double check everything, then click Publish. This will trigger a
6481
`publication workflow on GitHub
6582
<https://github.com/beeware/rubicon-objc/actions?query=workflow%3A%22Upload+Python+Package%22>`__.
6683

pyproject.toml

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
[build-system]
2-
requires = [
3-
"setuptools >= 46.4.0",
4-
"wheel >= 0.32.0",
5-
]
2+
requires = ["setuptools>=60", "setuptools_scm[toml]>=7.0"]
63
build-backend = "setuptools.build_meta"
74

85
[tool.isort]
96
profile = "black"
107
split_on_trailing_comma = true
118
combine_as_imports = true
129

10+
[tool.setuptools_scm]
11+
# To enable SCM versioning, we need an empty tool configuration for setuptools_scm
12+
1313
[tool.towncrier]
1414
directory = "changes"
1515
package = "rubicon.objc"

setup.cfg

+7-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
[metadata]
22
name = rubicon-objc
3-
version = attr: rubicon.objc.__version__
43
url = https://beeware.org/rubicon
54
project_urls =
65
Funding = https://beeware.org/contributing/membership/
@@ -15,7 +14,6 @@ classifiers =
1514
License :: OSI Approved :: BSD License
1615
Programming Language :: Objective C
1716
Programming Language :: Python :: 3
18-
Programming Language :: Python :: 3.6
1917
Programming Language :: Python :: 3.7
2018
Programming Language :: Python :: 3.8
2119
Programming Language :: Python :: 3.9
@@ -32,17 +30,23 @@ long_description = file: README.rst
3230
long_description_content_type = text/x-rst
3331

3432
[options]
35-
python_requires = >=3.6
33+
python_requires = >=3.7
3634
packages = find:
3735
package_dir =
3836
= src
37+
install_requires =
38+
# We need importlib.metadata.version, added in Python 3.8
39+
importlib_metadata >= 4.4; python_version < "3.8"
3940

4041
[options.packages.find]
4142
where = src
4243

4344
[options.extras_require]
4445
dev =
4546
pre-commit == 2.21.0
47+
pytest == 7.2.1
48+
pytest-tldr == 0.2.5
49+
setuptools_scm[toml] == 7.1.0
4650
tox == 4.3.5
4751
docs =
4852
furo == 2022.12.7

setup.py

-3
This file was deleted.

0 commit comments

Comments
 (0)