Add basic publish command
Closes #85
How it works:
chrispryer@Chriss-MacBook-Pro ~/g/s/rye-publish> rye publish --repository-url https://test.pypi.org/legacy/
Enter a passphrase (optional):
- Require access token
- Check args (
--token) - Check
~/.rye/credentials - Prompt user ("go to https://upload.pypi.org/legacy/")
- Offer encryption/decryption via passphrase
- Store in
~/.rye/credentialsencoded keyed by--repository(defaults "pypi") - Publish targets via
twine(--repository-url)
See https://github.com/mitsuhiko/rye/pull/86#issuecomment-1531432387
Summary of changes:
- Added
publishcommand
TODO:
- [x] Add command with basic requirements from
twine - [x] Allow pattern and multiple targets for
distpositional arguments - [x] Basic token handling
- [x] Hidden input
- [x] Encode/decode
- [x] Successful https://test.pypi.org/ publish
- [x] Clean up
- [ ] Validated encryption & decryption via passphrase and
~/.rye/credentials
Considerations
- Supporting pypirc in the first-pass
ringis smaller butageis easier to reason about being new to this andkeyringlooks nice (see comment tagged below)- Using
rpasswordfor the phrase prompts or roll own - Should
ryebootstrap with an empty~/.rye/credentials? - Adding a
--no-passphrase/--no-interactionflag - OIDC support
- Using
ryewith env vars
See https://github.com/mitsuhiko/rye/pull/86#issuecomment-1536309461
I think it's reasonable to use twine behind the scenes but I wonder if it wouldn't be better to explicitly handle authentication. The way twine currently works makes it quite user unfriendly to get to the right experience (eg: upload with tokens).
Love it. How does this sound?
rye publish- "No access token found for <url>\nAccess token: <wait for user input>"
IIRC that's roughly how cargo handles it.
I think what makes most sense is to propose something like this:
rye publishif it does not have a token on file, prints a message for the user to go to https://pypi.org/manage/account/token/ and create a global token- It offers to encrypt the token with a passphrase
- It stores the token in
~/.rye/credentailskeyed by repository - Whenever it needs a token, it feeds that token directly to twine, optionally decrypting it with the provided or prompted passphrase
Since it's not possible to restrict a token to a not yet created project, we probably want to create global tokens all the way but it would be possible to only ever store a restricted token by using pypitoken.
Sounds like a plan. Just a heads up I'll be pretty busy until Thursday. If I can't pick this back up before then I'll tackle this into the weekend.
Just want to tag https://github.com/mitsuhiko/rye/pull/86/commits/f4ecb2e9dd6c5bec1fcbf1da1537fd2a9d0f2318 with https://packaging.python.org/en/latest/specifications/pypirc/
> rye publish --repository-url https://test.pypi.org/legacy/
No access token found, generate one at: https://pypi.org/manage/account/token/
Access token: [redacted]
Enter a passphrase (optional):
Uploading distributions to https://test.pypi.org/legacy/
Uploading rye_publish-0.1.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.6/3.6 kB • 00:00 • ?
Uploading rye_publish-0.1.0.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.3/3.3 kB • 00:00 • ?
View at:
https://test.pypi.org/project/rye-publish/0.1.0/
I don't like much interaction but this was nice

fwiw in maturin we use cli args, env vars (e.g. for github actions), system keyring integration (remembers your password after succesful upload), and recently messense implemented OIDC trusted publicher support. A contributor also added .pypirc support (order in https://github.com/PyO3/maturin/blob/ea793e878e3b2e12fb106c07af5a3e54c523abef/src/upload.rs#L190 )
fwiw in maturin we use cli args, env vars (e.g. for github actions), system keyring integration (remembers your password after succesful upload), and recently messense implemented OIDC trusted publicher support. A contributor also added .pypirc support (order in https://github.com/PyO3/maturin/blob/ea793e878e3b2e12fb106c07af5a3e54c523abef/src/upload.rs#L190 )
Oh nice. This looks great. Keyring looks nice too. OIDC would be really nice to support as well. I wanted to include the .pypirc but figured I'd get more feedback on how this all works. Do we prioritize it? Use our configuration? etc.
Thanks this is really helpful!
I'll mark this as ready to review. Struggling to find time, so maybe I can get some feedback for the next window I have to work on this. It might make sense to consider what maturin does. I've added a broader "considerations" list to the issue's description.
Edit: I’ll resolve the conflicts and probably push a few more changes to make this a little more robust. I can do this later, then I’ll mark as ready for review.
I will review this today!
I will review this today!
Thanks! I want to put a little more time into to the url cli argument (eg: https://test.pypi.org/legacy will fail with a redirect due to the missing trailing /) and a couple other house cleaning items, but otherwise it should be structurally ready for some feedback.
I have time today and tomorrow morning to work on any changes here if needed.
Looks good!