Skip to content
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

Fall back to Twine's keyring support in publish command #759

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

cnpryer
Copy link
Contributor

@cnpryer cnpryer commented Feb 24, 2024

From #741, Rye is unable to publish packages with Twine if users rely on keyring.

I'm not sure if the plan is to implement more of the publish logic ourselves. In case it's not or we're still far off from that, this PR offers a fix for #741 by updating the publish command logic to fall back to Twine's keyring support.

Changes:

  • Dynamic dispatch of --username, --token, and --repository-url to allow keyring fallback.
  • --skip-save-credentials to prevent potential confusing behavior and provide users with an opt-out method.
  • Refactored the credentials resolution, prompting, and save credentials code

Testing:

  • Publish configuration resolution tests
  • Snapshots
  • Manual (see below)

Manual testing:

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.4.0 via 🐍 took 34s 
❯ cat ~/.rye/credentials
[pypi]
token = <token>
username = "__token__"
repository-url = "https://upload.pypi.org/legacy/"

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.4.0 via 🐍 
❯ rye publish -r 'testpypi'
Access token: <token>
Repository URL: https://test.pypi.org/legacy/
Uploading distributions to https://test.pypi.org/legacy/
Uploading testpypi_package-0.4.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.4.0.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.9/3.9 kB β€’ 00:00 β€’ ?

View at:
https://test.pypi.org/project/testpypi-package/0.4.0/

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.4.0 via 🐍 took 6s 
❯ rye publish -r 'testpypi'
? Decrypt with passphrase (optional) β€Ί 

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.4.0 via 🐍 
❯ rye publish -r 'testpypi' --token <token>
? Encrypt with passphrase (optional) β€Ί 

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.4.0 via 🐍 
❯ cat ~/.rye/credentials 
[pypi]
repository-url = "https://upload.pypi.org/legacy/"

[testpypi]
username = "__token__"
repository-url = "https://test.pypi.org/legacy/"
image

Edit: Cleaned up the description for latest changes.

rye/src/cli/publish.rs Outdated Show resolved Hide resolved
@cnpryer
Copy link
Contributor Author

cnpryer commented Feb 24, 2024

For posterity, Konsti suggested to use maturin for inspiration if anyone is interested in taking that up.

@golgor
Copy link

golgor commented Feb 24, 2024

FYI:
This solution works for me when I try to publish to a private repo:

~/Code/rye/target/debug/rye publish --repository rye-development-repo --repository-url https://europe-west4-python.pkg.dev/personal-projects-393014/rye-development-repo/ --username _json_key_base64 --token <KEY> dist/* -y

So instead of letting twine read the .pypirc everything is supplied from the commandline, but I guess that is totally fine. It will at least let me use rye in my github actions instead of having a regular python flow and using twine directly.

Just one thought. In this case you pass the repository-url-argument to twine if you were not able to resolve the credentials. Would it possible to use the repository instead? In that case it should work for me using something like:
rye publish --repository <name>. Or what was the reason for passing the repository-url?

I wish I would be able to help out more, but I have learn more Rust. Might be something I can do on the side, if no one else takes this on.

Thanks a lot @cnpryer for you help!

@cnpryer
Copy link
Contributor Author

cnpryer commented Feb 24, 2024

Thanks for checking it out!

If there's interest in this I'd like to:

  1. PR --non-interactive - User only directly interacts with Rye.
  2. Use something like resolve_credentials(cmd) to clean that up
  3. Require groups of options: Rye either resolves the credentials on its own or the user bypasses Rye for Twine defaults.

Ideally you can do this when it's done and it'll hand off the repository url + username inputs to Twine.

rye publish --repository-url <url> --username <usr> --skip-credentials-save -y

And if you decide to save the username and repo url in Rye's credentials file, then if no token is resolved next time it'd just hand off those same inputs again.

If I can I'll add tests for the credentials resolution. Something like first CLI, then ENV, then Rye or Twine.

@cnpryer
Copy link
Contributor Author

cnpryer commented Feb 24, 2024

To be honest I think the best way to leave this would be to specifically only dish out for Twine's keyring support and then do something more robust.

I'm not really in love with this, but if there's a way to quickly fix this issue for you I'm happy to add to this.

@mitsuhiko
Copy link
Collaborator

For posterity, Konsti suggested to use maturin for inspiration if anyone is interested in taking that up.

Maybe also worth considering ditching twine for maturin?

@cnpryer
Copy link
Contributor Author

cnpryer commented Feb 25, 2024

Maybe also worth considering ditching twine for maturin?

If that's where you want to go with it. I do like the token experience we're going for, but if there's a way to easily incorporate another common and secure method maybe we can start with this?

I was thinking at the least:

  1. Attempt to resolve configuration from ~/.rye/credentials
  2. Override with CLI
  3. If token is not resolved but a repository url and a username are resolved then only dispatch that to Twine.

That way to start at least we're supporting the current token process, CLI-override, and keyring via Twine.

I'll clean up what's going on in this PR, mark this ready for a review, and then we can figure out what makes sense.

@mitsuhiko
Copy link
Collaborator

I think this is a good start. Is there any chance you could add basic tests for this? Maybe by mocking up a dummy endpoint.

@cnpryer
Copy link
Contributor Author

cnpryer commented Feb 25, 2024

I think this is a good start. Is there any chance you could add basic tests for this? Maybe by mocking up a dummy endpoint.

Yea I looked at Twine's tests out of the same interest. I also looked around uv's. I'll try to look at that more today if I can.

For now I'll mark this as ready in case you wanted to play around with it. Also happy to set up a simple test for resolve_repository_credentials. Let me know what you'd prefer to prioritize.

@cnpryer cnpryer marked this pull request as ready for review February 25, 2024 19:28
@mitsuhiko
Copy link
Collaborator

Would be great to add a basic test in. This is the type of code that is easy to break.

@cnpryer cnpryer changed the title Allow Twine to resolve credentials if Rye cannot resolve them Fall back to Twine's keyring support in publish command Feb 25, 2024
@cnpryer
Copy link
Contributor Author

cnpryer commented Feb 25, 2024

Would be great to add a basic test in. This is the type of code that is easy to break.

I tried to crank that out real quick. I didn't finish. I'll come back to it again later. Converting to draft until then.

@cnpryer cnpryer marked this pull request as draft February 25, 2024 20:51
Comment on lines +59 to +66
// write the credentials file
let credentials_file = home.join("credentials");
if !credentials_file.is_file() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we write the home contents how are we managing changes to those contents? I had to remove the file for this to run.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Today the home folder is shared so there is really no way to fuck around in it between tests. One option would be to restructure the code in common/mod.rs to make two homes. One like used by all (concurrent), another one that uses the file lock to ensure only ever one test can use it at the time.

@cnpryer

This comment was marked as resolved.

@cnpryer
Copy link
Contributor Author

cnpryer commented Mar 27, 2024

I'll aim to get back in here this weekend.

@cnpryer
Copy link
Contributor Author

cnpryer commented Mar 29, 2024

So right now the flow this PR will implement will look like this from a fresh environment:

By default Rye doesn't initialize with a credentials file (this is fine).

❯ cat ~/.rye/credentials
cat: /Users/chrispryer/.rye/credentials: No such file or directory

Since we've prioritize auth token usage, your basic usage will invoke a prompt for the token if one isn't provided or found.

❯ rye publish -r 'testpypi' --repository-url https://test.pypi.org/legacy/
Access token:

You can pass -y to skip this and it will attempt the keyring fallback.

Returning to this after a while, my initial reaction to this was that I'd expect for us to use the keyring backend if an entry is already set up. So it's up to you, but in order to do that we'd want to modify this PR to prioritize the keyring backend.

That way the basic usage will avoid prompting the user if they have already set up keyring for the provided repository url.

As for the state of this change and making sure it's definitely ready to be merged I'm going to treat this like it's a PR I want to merge into my own repo. To do that I'll do a full review this weekend and manually verify different use cases.

I added some testing here, but it's not the best.

@cnpryer
Copy link
Contributor Author

cnpryer commented Mar 29, 2024

I've organized the changes into commits for an easier read and provided some details about each change. The refactor makes the diff difficult to reason about since large portions of the cli/publish.rs file is modified in order to make this easier to implement (and maintain).

I'll do a full review either tomorrow or Sunday.

@cnpryer cnpryer force-pushed the cp-publish-twine branch 2 times, most recently from beede8c to 73946d9 Compare March 30, 2024 00:03
We don't want to default to 'pypi'. Keyring backends can be used without this data. Keyring is set up with repo url and username. `--skip-save-credentials` is added to avoid unwanted credentials file usage in environments where keyring might be used directly.
We want to refactor the first step in the resolution logic to find an entry for the provided repository if it exists. If we are given a repository but an entry doesn't exist we can create the entry for the rest of the logic to flow from.
This refactor allows for both credentials and repository data to be resolved independent from eachother. This makes it easier to implement tricky logic that flows from various use-cases.
This refactors the section that handles prompting the user. To avoid tangled logic here, and in other parts of the code, we want to first establish if encryption or decryption should happen. This influences the prompts needed as well as give us the ability to move where these operations end up ocurring -- which cleans this up nicely. Our functions now return `None` if the user decides not to provide an input.
Depending on the data that has been already resolved, we may be able to default certain configuration. For example, if we have enough information for keyring backends we can resolve our default username. However, we don't want to resolve our default username in all use-cases.
If the user doesn't skip the save step, and if we have enough/valid data to save, then we save to the credentials file and encrypt our token if encryption is needed. Encryption and decryption functions are cleaned up for an easier read.
Username and repository url are needed for keyring. So we provide those and the rest of its args dynamically to pass the remaining resolution to Twine. We use `--non-interactive` to avoid invoking Twine prompts (we handle this prompting ourselves).
This adds both unit tests to cli/publish.rs and integration tests. Some of the integration tests are meant to either fail or end early. I'd really like to avoid network calls, but it seems like we're not going the extra mile for this yet in other tests.
@cnpryer
Copy link
Contributor Author

cnpryer commented Mar 30, 2024

@mitsuhiko At this stage the PR should be ready. I'll keep an eye out for any reported issues.

One comment though is what I mentioned here.

Returning to this after a while, my initial reaction to this was that I'd expect for us to use the keyring backend if an entry is already set up. So it's up to you, but in order to do that we'd want to modify this PR to prioritize the keyring backend.

If we are still looking to prioritize Rye's token management then I'd say let's just see if users provide feedback to prioritize keyring. I'll add some documentation on this. You can allow Rye to perform the fallback if you pass -y.

Expand the details below if you'd like to see all the manual testing I just did. Last example uses the encrypted token. Encrypt/decrypt prompts aren't persisted in the output. The "keychain" error is from exiting my keyring prompt.

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 
❯ rye publish --skip-save-credentials
No access token found, generate one at: https://pypi.org/manage/account/token/
Access token: 
Repository URL: 
Uploading distributions to https://upload.pypi.org/legacy/
ERROR    NonInteractive: Credential not found for password.                                                                                                                                            
error: failed to publish files

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 
❯ rye publish --skip-save-credentials -y
Uploading distributions to https://upload.pypi.org/legacy/
ERROR    NonInteractive: Credential not found for password.                                                                                                                                            
error: failed to publish files

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 
❯ rye publish --skip-save-credentials -y -r pypi
Uploading distributions to https://upload.pypi.org/legacy/
ERROR    NonInteractive: Credential not found for password.                                                                                                                                            
error: failed to publish files

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 
❯ rye publish --skip-save-credentials -y -r testpypi
error: failed to resolve configuration for repository 'testpypi'

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 
❯ rye publish --skip-save-credentials -r pypi       
No access token found, generate one at: https://pypi.org/manage/account/token/
Access token: 
Uploading distributions to https://upload.pypi.org/legacy/
ERROR    NonInteractive: Credential not found for password.                                                                                                                                            
error: failed to publish files

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 
❯ rye publish --skip-save-credentials -r testpypi
Access token: 
Repository URL: 
error: failed to resolve configuration for repository 'testpypi'

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 
❯ rye publish --skip-save-credentials -r pypi --repository-url https://upload.pypi.org/legacy/
No access token found, generate one at: https://pypi.org/manage/account/token/
Access token: 
Uploading distributions to https://upload.pypi.org/legacy/
ERROR    NonInteractive: Credential not found for password.                                                                                                                                            
error: failed to publish files

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 
❯ rye publish --skip-save-credentials -r testpypi --repository-url https://test.pypi.org/legacy/  
Access token: 
Uploading distributions to https://test.pypi.org/legacy/
WARNING  Error getting password from keyring                                                                                                                                                           
         Traceback (most recent call last):                                                                                                                                                            
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/keyring/backends/macOS/__init__.py", line 61, in get_password                                                                
             return api.find_generic_password(self.keychain, service, username)                                                                                                                        
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                        
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/keyring/backends/macOS/api.py", line 156, in find_generic_password                                                           
             Error.raise_for_status(status)                                                                                                                                                            
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/keyring/backends/macOS/api.py", line 119, in raise_for_status                                                                
             raise KeychainDenied(status, "Keychain Access Denied")                                                                                                                                    
         keyring.backends.macOS.api.KeychainDenied: (-128, 'Keychain Access Denied')                                                                                                                   
                                                                                                                                                                                                       
         The above exception was the direct cause of the following exception:                                                                                                                          
                                                                                                                                                                                                       
         Traceback (most recent call last):                                                                                                                                                            
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/twine/auth.py", line 74, in get_password_from_keyring                                                                        
             return cast(str, keyring.get_password(system, username))                                                                                                                                  
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                   
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/keyring/core.py", line 56, in get_password                                                                                   
             return get_keyring().get_password(service_name, username)                                                                                                                                 
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                 
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/keyring/backends/macOS/__init__.py", line 21, in wrapper                                                                     
             return func(self, *args, **kwargs)                                                                                                                                                        
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                                        
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/keyring/backends/macOS/__init__.py", line 65, in get_password                                                                
             raise KeyringLocked(f"Can't get password from keychain: {e}") from e                                                                                                                      
         keyring.errors.KeyringLocked: Can't get password from keychain: (-128, 'Keychain Access Denied')                                                                                              
ERROR    NonInteractive: Credential not found for password.                                                                                                                                            
error: failed to publish files

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 took 14s 
❯ rye publish --skip-save-credentials -r testpypi --repository-url https://test.pypi.org/legacy/ -y
Uploading distributions to https://test.pypi.org/legacy/
WARNING  Error getting password from keyring                                                                                                                                                           
         Traceback (most recent call last):                                                                                                                                                            
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/keyring/backends/macOS/__init__.py", line 61, in get_password                                                                
             return api.find_generic_password(self.keychain, service, username)                                                                                                                        
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                        
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/keyring/backends/macOS/api.py", line 156, in find_generic_password                                                           
             Error.raise_for_status(status)                                                                                                                                                            
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/keyring/backends/macOS/api.py", line 119, in raise_for_status                                                                
             raise KeychainDenied(status, "Keychain Access Denied")                                                                                                                                    
         keyring.backends.macOS.api.KeychainDenied: (-128, 'Keychain Access Denied')                                                                                                                   
                                                                                                                                                                                                       
         The above exception was the direct cause of the following exception:                                                                                                                          
                                                                                                                                                                                                       
         Traceback (most recent call last):                                                                                                                                                            
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/twine/auth.py", line 74, in get_password_from_keyring                                                                        
             return cast(str, keyring.get_password(system, username))                                                                                                                                  
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                   
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/keyring/core.py", line 56, in get_password                                                                                   
             return get_keyring().get_password(service_name, username)                                                                                                                                 
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                 
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/keyring/backends/macOS/__init__.py", line 21, in wrapper                                                                     
             return func(self, *args, **kwargs)                                                                                                                                                        
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^                                                                                                                                                        
           File "/Users/chrispryer/.rye/self/lib/python3.12/site-packages/keyring/backends/macOS/__init__.py", line 65, in get_password                                                                
             raise KeyringLocked(f"Can't get password from keychain: {e}") from e                                                                                                                      
         keyring.errors.KeyringLocked: Can't get password from keychain: (-128, 'Keychain Access Denied')                                                                                              
ERROR    NonInteractive: Credential not found for password.                                                                                                                                            
error: failed to publish files

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 took 2s 
❯ rye publish --skip-save-credentials -r testpypi --repository-url https://test.pypi.org/legacy/ --token <token>
Uploading distributions to https://test.pypi.org/legacy/
Uploading testpypi_package-0.3.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.4.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.3.0.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.9/3.9 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.4.0.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.9/3.9 kB β€’ 00:00 β€’ ?

View at:
https://test.pypi.org/project/testpypi-package/0.3.0/
https://test.pypi.org/project/testpypi-package/0.4.0/

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 
❯ touch ~/.rye/credentials

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 
❯ vim ~/.rye/credentials 

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 took 1m11s 
❯ cat ~/.rye/credentials 
[testpypi]
token = <token>
repository-url = "https://test.pypi.org/legacy/"

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 took 9s 
❯ rye publish -r testpypi
Uploading distributions to https://test.pypi.org/legacy/
Uploading testpypi_package-0.3.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.4.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.3.0.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.9/3.9 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.4.0.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.9/3.9 kB β€’ 00:00 β€’ ?

View at:
https://test.pypi.org/project/testpypi-package/0.4.0/
https://test.pypi.org/project/testpypi-package/0.3.0/

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 
❯ rm ~/.rye/credentials  

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 
❯ rye publish -r testpypi
Access token: <token>
Repository URL: https://test.pypi.org/legacy/
Uploading distributions to https://test.pypi.org/legacy/
Uploading testpypi_package-0.3.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.4.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.3.0.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.9/3.9 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.4.0.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.9/3.9 kB β€’ 00:00 β€’ ?

View at:
https://test.pypi.org/project/testpypi-package/0.3.0/
https://test.pypi.org/project/testpypi-package/0.4.0/

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 took 20s 
❯ cat ~/.rye/credentials 
[testpypi]
token = "6167652d656e6372797074696f6e2e6f72672f76310a2d3e207363727970742035536667707a4e6a376e332b386954314248734847412031340a65555330347952705a4a7a33704c5263354c4f7241376c586b6d4e6d7972436644516e673943726e78326f0a2d2d2d206f53796b526f786878474867584d4438776a6164343962646f65786c4e41647275366b397a6d7545666e770ae1cd5b9ba93084c57995eecec9b7f1a734ad58118c50a03beeb1862d1a52ec56f2e4eeeac4881b5df3829d78ee4dd93630cea2347b98065d45233851907910e7d9aab8c4650c973bf781fed0acea133c7ed674237b50959775ac9005ed59bc22a96c016edaa85d88b35b8d52e71b6c929b17336eb671568f468f4281f8d179d30dd8780a1450f205ba8cf57cac9aa71b5b3f3be7da96a6879ef5b543f9e792d5923ba21f718f09bd75ed2d6b895c9e21fc854fabda863118f14a8fb24643729214ab24e9a5d7e2e2c4c4085fd23f12612646370ab206de521db8c0815b7bb73d3d01a3bee5321731656573aede351fafb862c014c83ac04575c9419d070bc33c"
username = "__token__"
repository-url = "https://test.pypi.org/legacy/"

testpypi-package on ξ‚  main [?] is πŸ“¦ v0.3.0 via 🐍 took 2s 
❯ rye publish -r testpypi 
Uploading distributions to https://test.pypi.org/legacy/
Uploading testpypi_package-0.3.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.4.0-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.3.0.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.9/3.9 kB β€’ 00:00 β€’ ?
Uploading testpypi_package-0.4.0.tar.gz
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.9/3.9 kB β€’ 00:00 β€’ ?

View at:
https://test.pypi.org/project/testpypi-package/0.4.0/
https://test.pypi.org/project/testpypi-package/0.3.0/

I really want to ensure is that we are reliably providing encryption if the user opts into it. I did some extra testing around this, but I'll do some more over the next couple of days.

@cnpryer cnpryer requested a review from mitsuhiko March 30, 2024 18:19
We no longer default to 'pypi' for this arg
@camilo-s
Copy link

camilo-s commented Apr 4, 2024

Any chance that Twine's --config-file option could be dispatched as well?
In my current use-case, this would support the TwineAuthenticate@1 task from Azure Pipelines

@cnpryer
Copy link
Contributor Author

cnpryer commented Apr 4, 2024

Any chance that Twine's --config-file option could be dispatched as well? In my current use-case, this would support the TwineAuthenticate@1 task from Azure Pipelines

Feel free to mention that here

@cnpryer
Copy link
Contributor Author

cnpryer commented May 8, 2024

@charliermarsh can I do anything to help make this easier to review and consider? I have time this weekend to work on this.

The majority of this change is a refactor of the publish command's code. Would you prefer I undo the keyring support to start with just the refactor?

I understand some logic might be upstreamed to uv, but I'd prefer if contributors PR any future changes on top of this code rather than its code on main. It should be more extendable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants