New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Deploy to PyPI from Travis CI #106
Conversation
One option is to only have the Test PyPI stuff uploaded automatically. There's definitely value in testing a package can be built (checks those Twine/manifest errors) and uploaded successfully (PyPI doesn't reject anything). And then production releases are still done manually. Another option: instead of uploads to Test PyPI for merges and uploads to production on tags, have both uploaded to Test PyPI. You can then download and check the packages, and/or install directly from Test PyPI, and if good, upload them manually to production PyPI. |
Looking at this PR build from my fork: Python 3.5 build. At the end of the log it shows all the reasons why it didn't attempt deploy to Test PyPI or production PyPI, ie. because I'm on a fork, it's not
Python 3.8 build. Skipped due to fork, not
This one doesn't complain about the runtime, ie. 3.8 is good. |
Codecov Report
@@ Coverage Diff @@
## master #106 +/- ##
==========================================
+ Coverage 99.29% 99.53% +0.24%
==========================================
Files 12 10 -2
Lines 568 432 -136
==========================================
- Hits 564 430 -134
+ Misses 4 2 -2
Continue to review full report at Codecov.
|
Here's an example deploy to Test PyPI from one of my projects for a merge to master: And a tagged release to production PyPI: This is the release checklist: |
I am definitely intrigued. I have a few questions.
|
TestPyPI is:
By successfully deploying there during the development cycle, you have more confidence that when it comes to actually releasing, your code can be successfully package and uploaded. It helps avoid things like MANIFEST.in errors, tests that It also possible to install your test package from TestPyPI: $ pip install --index-url https://test.pypi.org/simple/ your-package
# or to pull dependencies from PyPI:
$ pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple your-package https://packaging.python.org/guides/using-testpypi/#using-testpypi-with-pip This can be useful for additional testing of your package, that it works from end-to-end (build, upload, download, install, run). Also, occasionally someone may wish to try a fix or new feature that's in master but not yet released. This would give them something to try without installing from source. (Although |
There's not a huge benefit in doing so. I don't upload any binaries to GitHub, PyPI is enough. Basically I only mark a tag as a release and sometimes put some basic release notes there (eg. https://github.com/hugovk/pypistats/releases) but you could easily skip it as the tag list is pretty much the same (eg. https://github.com/SethMMorton/natsort/releases). |
I'm using it as a CI. I have two workflows, for lint and unit tests: Pretty much the same as Travis CI does, except unit tests on GHA are also tested on macOS and Windows, and also testing two Ubuntu versions (I have Travis only testing Linux, with a single Ubuntu version). You get 5 parallel jobs and 20 with GHA, so they run quickly. |
Thanks for all that. I was asking about the GitHub releases because it was mentioned it the checklist you linked to. |
Looking at the GitHub actions files... I wonder why I would bother with Travis-CI going forward. It seems like GitHub actions has the following advantages over Travis
Am I missing something? |
@hugovk Despite all the things I said about GitHub actions, I plan to accept this PR. One think I liked about the project you showed me was your release checklist - if you were to update this PR to include one of those (minus the GitHub releases thing) I will merge. So long as you don't mind if I tweak the release checklist after-the-fact as I settle on this more automated release method 😺 |
All very good points, and I may well ditch Travis in the future. Reasons for keeping it a bit longer:
I can definitely see using only GHA or doing most testing on GHA in the future. Over at Pillow we're in the process of moving testing from Travis (5 parallel jobs) and AppVeyor (1 serial job) to GHA (20). I expect we'll still keep some basic testing on Travis and AppVeyor, maybe a recent Python version and things which are unique to those platforms. |
Added! I definitely recommend a checklist, it's handy to refer to something when releasing, and useful if someone else does a release. Sure, please do tweak and change it to fit your needs! |
@hugovk So I am finally getting around to creating the API token, and I am being bitten by travis-ci/travis.rb#221 (which I see by the thumbs-up on various comments you are aware of). FWIW, I just migrated my .org accounts to .com... Any suggestions on working around this? |
Oh, that's a pain... Travis The workaround is to use your own username and encrypted password, like this: (If you wanted to limit it to a single package, I suppose you could create a new user and add it to just natsort.) |
Thank you so much for your help! As an FYI, I ended up modifying your code slightly so that the |
You're very welcome, thank you for natsort! Good idea about the extra stage. |
This should help make releasing easier.
Will only trigger when run from the
SethMMorton/natsort
repo, onmaster
, so not for forks or PRs.The
on:
section shows the conditions for triggering an upload. This should be set up so only a single build job qualifies.Right now, there's only a single Python 3.8 job, so select on
python: 3.8
. If 3.7 and 3.8 are switched, this can also so there's only a single 3.7. It's possible to select on other conditions too:https://docs.travis-ci.com/user/deployment/#conditional-releases-with-on
skip_existing: true
should in any case prevent trying to re-upload existing ones.TODO:
natsort-ci
at https://test.pypi.org/manage/account/token/travis encrypt
pypi-
password: secure: "TODO"
value"TODO"
More info on PyPI API tokens: https://pypi.org/help/#apitoken