Skip to content

Commit 7f3c361

Browse files
[CI] build'n'publish with steroids (#64)
* Update .gitignore (not venv in it, what crime was that 👀 ) https://github.com/github/gitignore/blob/main/Python.gitignore * Update publish CI * refine instructions * Update publish.yml * retrigger RTD by removing an optional instruction * Change CI name * Fix using env in if statements * Hard-coding it cause GH did not thought about constants * setuptools-scm did not work with a shallow copy * fix installation size listing * Switch to SPDX license format * Add license-file field to pyproject.toml --------- Co-authored-by: Adam R. Jensen <[email protected]>
1 parent b1421e3 commit 7f3c361

File tree

3 files changed

+254
-17
lines changed

3 files changed

+254
-17
lines changed

.github/workflows/publish.yml

Lines changed: 74 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,96 @@
1-
name: Publish distributions to PyPI
1+
name: Build & Publish package to PyPI
22

3-
# if this workflow is modified to be a generic CI workflow then
4-
# add an if statement to the publish step so it only runs on tags.
3+
# CI setup instructions:
4+
# 1. Replace 'pvlib/twoaxistracking' and 'twoaxistracking' with your GitHub organization and repository name
5+
# 2. Create a new environment for additional protection and security in the GitHub UI:
6+
# Settings > Environments
7+
# Name: release
8+
# 3. Setup trusted publishing for the release environment:
9+
# https://docs.pypi.org/trusted-publishers/
10+
# 4. Ensure your main development branch is named 'main'; if not, update the workflow or rename the branch
11+
12+
# This workflow is triggered on pull requests that target the main branch
13+
# on pushes to the main branch new tags that start with 'v' (for example, 'v1.0.0').
14+
# Only the main branch is used for publishing to PyPI, in the second job.
515
on:
16+
pull_request:
17+
branches:
18+
- main
619
push:
20+
branches:
21+
- main
722
tags:
823
- "v*"
924

25+
env:
26+
python-version: "3.12"
27+
1028
jobs:
11-
build-n-publish:
12-
name: Build and publish distributions to PyPI
13-
if: github.repository == 'pvlib/twoaxistracking'
29+
build-distribution:
30+
name: Build distribution
1431
runs-on: ubuntu-latest
15-
permissions:
16-
id-token: write # This is required for requesting the JWT
17-
contents: read # This is required for actions/checkout
1832
steps:
19-
# fetch all commits and tags so versioneer works
2033
- uses: actions/checkout@v4
34+
# Deep clone to fetch all commits and tags, by setting the fetch-depth to 0
2135
with:
2236
fetch-depth: 0
2337

2438
- name: Set up Python
2539
uses: actions/setup-python@v5
2640
with:
27-
python-version: "3.12"
41+
python-version: ${{ env.python-version }}
2842

2943
- name: Install build tools
3044
run: |
3145
python -m pip install --upgrade pip
32-
python -m pip install --upgrade setuptools wheel build
46+
python -m pip install --upgrade setuptools wheel build twine
47+
3348
- name: Build packages
34-
run: python -m build --sdist --wheel
49+
# creates the necessary distribution files to /dist
50+
run: python -m build
51+
52+
- name: Check metadata verification
53+
# this step ensures the metadata is correct and complete
54+
# it is a good practice to run this before publishing to PyPI
55+
run: python -m twine check --strict dist/*
56+
57+
- name: Distribution files & installation sizes
58+
# this step is useful to get some useful metrics and ensure changes do not break the size of the distribution
59+
run: |
60+
echo "Distribution files sizes"
61+
du -sh dist/*
62+
python -m pip install dist/*.whl --target /tmp/pvlib --quiet --quiet
63+
echo "Installation size of wheel"
64+
du -sh /tmp/pvlib/twoaxistracking
65+
66+
- name: Upload artifact with distribution files
67+
# this step uploads the distribution files to the GitHub artifact store if they are needed later to publish to PyPI
68+
if: github.repository == 'pvlib/twoaxistracking' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
69+
uses: actions/upload-artifact@v4
70+
with:
71+
name: distro-files
72+
path: dist/
73+
if-no-files-found: error # files are required in the next job
74+
retention-days: 1 # delete the artifact after 1 day, no need to keep it for too long
75+
compression-level: 0 # no need to compress the files
76+
77+
publish-distribution:
78+
name: Upload distribution to PyPI
79+
runs-on: ubuntu-latest
80+
needs: build-distribution # first build, then publish
81+
# only publish distribution to PyPI in tagged commits
82+
if: github.repository == 'pvlib/twoaxistracking' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
83+
environment: release
84+
permissions:
85+
id-token: write # this permission mandatory for trusted publishing
86+
steps:
87+
- name: Download artifact with distribution files
88+
uses: actions/download-artifact@v4
89+
with:
90+
name: distro-files
91+
path: dist/
3592

36-
- name: Publish distribution to PyPI
37-
uses: pypa/gh-action-pypi-publish@release/v1
93+
- name: Publish distribution to PyPI
94+
# this step publishes the distribution files to PyPI by using PyPI trusted publishers
95+
# https://docs.pypi.org/trusted-publishers/
96+
uses: pypa/gh-action-pypi-publish@release/v1

.gitignore

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## .gititnore template file retrieved from
2+
## https://github.com/github/gitignore/blob/main/Python.gitignore in 2025-03-18
3+
14
.ipynb_checkpoints
25
.vscode
36
*/.ipynb_checkpoints/*
@@ -12,3 +15,177 @@ dist/
1215
docs/source/generated
1316

1417
.coverage
18+
# Byte-compiled / optimized / DLL files
19+
__pycache__/
20+
*.py[cod]
21+
*$py.class
22+
23+
# C extensions
24+
*.so
25+
26+
# Distribution / packaging
27+
.Python
28+
build/
29+
develop-eggs/
30+
dist/
31+
downloads/
32+
eggs/
33+
.eggs/
34+
lib/
35+
lib64/
36+
parts/
37+
sdist/
38+
var/
39+
wheels/
40+
share/python-wheels/
41+
*.egg-info/
42+
.installed.cfg
43+
*.egg
44+
MANIFEST
45+
46+
# PyInstaller
47+
# Usually these files are written by a python script from a template
48+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
49+
*.manifest
50+
*.spec
51+
52+
# Installer logs
53+
pip-log.txt
54+
pip-delete-this-directory.txt
55+
56+
# Unit test / coverage reports
57+
htmlcov/
58+
.tox/
59+
.nox/
60+
.coverage
61+
.coverage.*
62+
.cache
63+
nosetests.xml
64+
coverage.xml
65+
*.cover
66+
*.py,cover
67+
.hypothesis/
68+
.pytest_cache/
69+
cover/
70+
71+
# Translations
72+
*.mo
73+
*.pot
74+
75+
# Django stuff:
76+
*.log
77+
local_settings.py
78+
db.sqlite3
79+
db.sqlite3-journal
80+
81+
# Flask stuff:
82+
instance/
83+
.webassets-cache
84+
85+
# Scrapy stuff:
86+
.scrapy
87+
88+
# Sphinx documentation
89+
docs/_build/
90+
91+
# PyBuilder
92+
.pybuilder/
93+
target/
94+
95+
# Jupyter Notebook
96+
.ipynb_checkpoints
97+
98+
# IPython
99+
profile_default/
100+
ipython_config.py
101+
102+
# pyenv
103+
# For a library or package, you might want to ignore these files since the code is
104+
# intended to run in multiple environments; otherwise, check them in:
105+
# .python-version
106+
107+
# pipenv
108+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
109+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
110+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
111+
# install all needed dependencies.
112+
#Pipfile.lock
113+
114+
# UV
115+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
116+
# This is especially recommended for binary packages to ensure reproducibility, and is more
117+
# commonly ignored for libraries.
118+
#uv.lock
119+
120+
# poetry
121+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
122+
# This is especially recommended for binary packages to ensure reproducibility, and is more
123+
# commonly ignored for libraries.
124+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
125+
#poetry.lock
126+
127+
# pdm
128+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
129+
#pdm.lock
130+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
131+
# in version control.
132+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
133+
.pdm.toml
134+
.pdm-python
135+
.pdm-build/
136+
137+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
138+
__pypackages__/
139+
140+
# Celery stuff
141+
celerybeat-schedule
142+
celerybeat.pid
143+
144+
# SageMath parsed files
145+
*.sage.py
146+
147+
# Environments
148+
.env
149+
.venv
150+
env/
151+
venv/
152+
ENV/
153+
env.bak/
154+
venv.bak/
155+
156+
# Spyder project settings
157+
.spyderproject
158+
.spyproject
159+
160+
# Rope project settings
161+
.ropeproject
162+
163+
# mkdocs documentation
164+
/site
165+
166+
# mypy
167+
.mypy_cache/
168+
.dmypy.json
169+
dmypy.json
170+
171+
# Pyre type checker
172+
.pyre/
173+
174+
# pytype static type analyzer
175+
.pytype/
176+
177+
# Cython debug symbols
178+
cython_debug/
179+
180+
# PyCharm
181+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
182+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
183+
# and can be added to the global gitignore or merged into this file. For a more nuclear
184+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
185+
#.idea/
186+
187+
# Ruff stuff:
188+
.ruff_cache/
189+
190+
# PyPI configuration file
191+
.pypirc

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ description = "twoaxistracking is a python package for simulating two-axis track
2424
readme = "README.md"
2525
requires-python = ">=3.9"
2626
keywords = ["solar energy", "photovoltaics", "solar collector", "shading"]
27-
license = {file = "LICENSE"}
27+
license = "BSD-3-Clause"
28+
license-files = ["LICEN[CS]E*"]
2829
classifiers = [
2930
"Programming Language :: Python :: 3",
3031
"Programming Language :: Python :: 3.9",
3132
"Programming Language :: Python :: 3.10",
3233
"Programming Language :: Python :: 3.11",
3334
"Programming Language :: Python :: 3.12",
3435
"Programming Language :: Python :: 3.13",
35-
"License :: OSI Approved :: BSD License",
3636
"Operating System :: OS Independent",
3737
"Topic :: Scientific/Engineering",
3838
"Intended Audience :: Science/Research",
@@ -59,6 +59,7 @@ doc = [
5959
Documentation = "https://twoaxistracking.readthedocs.io"
6060
Issues = "https://github.com/pvlib/twoaxistracking/issues"
6161
Repository = "https://github.com/pvlib/twoaxistracking.git"
62+
Changelog = "https://github.com/pvlib/twoaxistracking/blob/main/docs/source/whatsnew.md"
6263

6364
[tool.pytest.ini_options]
6465
addopts = "--cov=twoaxistracking --cov-fail-under=100 --cov-report=term-missing"

0 commit comments

Comments
 (0)