Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
GHA: Publish release to test.pypi.org on demand #418
GHA: Publish release to test.pypi.org on demand #418
Changes from all commits
65fdd77
4796967
9f7dc7d
4ba885c
2e7f428
a213a3a
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't recommend using manual CLI invocations for publishing because you'll be missing out on the seamless GHA integrations.
For example, PyPI has recently implemented OIDC, and it's about to be enabled for private beta testing. It will allow to completely remove the GHA secrets and rely on secure short-lived tokens. Getting those tokens requires a few API requests to two different services that are specific to GHA, meaning the CLI tools will likely not implement this.
But the curated action https://github.com/marketplace/actions/pypi-publish will support it the moment OIDC is fully enabled on PyPI. With that, (Test)PyPI uploads will become zero-configuration for free, almost automatically.
Another point I'd like to make is that it's much more secure to perform publishing from a dedicated job — the secrets shouldn't be available to the build scripts or anything else that ends up being executed from the pre-publish jobs.
I also recommend using the
environment:
feature of GHA — it allows one to isolate the secrets, so they are not global and available to any job, but are only accessible from the job that has the proper environment set. Environments can also have branch protection — I usually make them require human approval for the job that publishes to PyPI. A real person needs to click a button on GitHub to allow such a job to start.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, multiple suggestions in here :) I'll definitely consider and probably adopt them.
Thanks, will check it out!
Hmm, I hadn't considered this. Is this because people could be opening a PR that modifies the CI pipeline that runs on every PR and modify it to extract the secrets?
Yup, makes total sense. Facepalm for not considering this, I've used environments before elsewhere.
Yes this makes sense and I've done this before. Would need to check how we can marry that with our auto publishing of dev builds to PyPI on every commit which is already going on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jorisroovers
TL;DR it is possible to smuggle some something that might access the secrets post-merge.
The secrets aren't available for runs triggered by the
pull_request
event. But they will be available for other events, post merge. If you use build tooling that has plugins, I imagine it might be possible to silently add a compromised plugin that would be loaded by said build tooling. It may be hard to track down if such third-party software does anything suspicious. And it's almost impossible to catch during reviews (unless you know to do audit of the entire transitive dependency tree being updated by such a change) — because it's expensive, and it's not the first thing most non-security-experienced reviewers would think of.I've been seeing https://www.stepsecurity.io/products/harden-runner being integrated in many projects lately in an attempt to tighten the possibility of sneaking out sensitive data out of the CI. Maybe you should consider adding it too.
Yeah, they are not advertised as a match for the publishing use-case which is why it took me a while to come up with this approach. But I've started doing this in all of my projects a year (or maybe more) ago. I usually call the environments
pypi
andtestpypi
. Use the same secret namePYPI_API_TOKEN
, meaning that I have two separate jobs publishing to different indexes. One environment needs approvals and the other is unconditional. Hopefully, with the OIDC support, the secrets bit will become unnecessary but the use for pre-approval use-case will still stand. I also like that I can render version URLs as environment params in CI, and they will be clickable in the workflow run summary graph. But this requires pre-calculating the expected version vars at the beginning of the workflow which is why I tend to have a whole separate job that runs first dedicated solely to calculating a number of variables that are shared across the jobs and are used for assertions sometimes.Just a separate environment without protections, and a separate job for that too.