Repository: pypa/twine
Pull request #232 (2017-02-22 01:15:16)

Allow passing custom CA bundle with environment variable
Add new `TWINE_CERT` environment variable so that a custom CA bundle
can be passed via an environment variable.

Also added brief documentation for the existing environment variables.
This could probably use some work with regards to the behavior of custom  
repository URLs (see #206).

sigmavirus24: Thanks @milas. This looks good!

Patch:
diff --git a/README.rst b/README.rst
index 3e6d75c..60c54da 100644
--- a/README.rst
+++ b/README.rst
@@ -115,6 +115,22 @@ Options
                             The .pypirc config file to use
       --skip-existing       Continue uploading files if one already exists
 
+Environment Variables
+`````````````````````
+
+Twine also supports configuration via environment variables. Options passed on
+the command line will take precedence over options set via environment
+variables. Definition via environment variable is helpful in environments where
+it is not convenient to create a `.pypirc` file, such as a CI/build server, for
+example.
+
+* ``TWINE_USERNAME`` - the username to use for authentication to the repository
+* ``TWINE_PASSWORD`` - the password to use for authentication to the repository
+* ``TWINE_REPOSITORY`` - the repository configuration, either defined as a
+  section in `.pypirc` or provided as a full URL
+* ``TWINE_REPOSITORY_URL`` - the repository URL to use
+* ``TWINE_CERT`` - custom CA certificate to use for repositories with
+  self-signed or untrusted certificates
 
 Resources
 ---------
diff --git a/twine/commands/register.py b/twine/commands/register.py
index 83ce99c..95a5e76 100644
--- a/twine/commands/register.py
+++ b/twine/commands/register.py
@@ -114,8 +114,13 @@ def main(args):
     )
     parser.add_argument(
         "--cert",
+        action=utils.EnvironmentDefault,
+        env="TWINE_CERT",
+        default=None,
+        required=False,
         metavar="path",
-        help="Path to alternate CA bundle",
+        help="Path to alternate CA bundle (can also be set via %(env)s "
+             "environment variable)",
     )
     parser.add_argument(
         "--client-cert",
diff --git a/twine/commands/upload.py b/twine/commands/upload.py
index ac8a950..222ec42 100644
--- a/twine/commands/upload.py
+++ b/twine/commands/upload.py
@@ -225,8 +225,13 @@ def main(args):
     )
     parser.add_argument(
         "--cert",
+        action=utils.EnvironmentDefault,
+        env="TWINE_CERT",
+        default=None,
+        required=False,
         metavar="path",
-        help="Path to alternate CA bundle",
+        help="Path to alternate CA bundle (can also be set via %(env)s "
+             "environment variable)",
     )
     parser.add_argument(
         "--client-cert",


Test patch:
diff --git a/tests/test_upload.py b/tests/test_upload.py
index e134f82..0d6c126 100644
--- a/tests/test_upload.py
+++ b/tests/test_upload.py
@@ -132,20 +132,23 @@ def test_skip_upload_respects_skip_existing(monkeypatch):
                               package=pkg) is False
 
 
-def test_password_and_username_from_env(monkeypatch):
+def test_values_from_env(monkeypatch):
     def none_upload(*args, **kwargs):
         pass
 
     replaced_upload = pretend.call_recorder(none_upload)
     monkeypatch.setattr(twine.commands.upload, "upload", replaced_upload)
     testenv = {"TWINE_USERNAME": "pypiuser",
-               "TWINE_PASSWORD": "pypipassword"}
+               "TWINE_PASSWORD": "pypipassword",
+               "TWINE_CERT": "/foo/bar.crt"}
     with helpers.set_env(**testenv):
         cli.dispatch(["upload", "path/to/file"])
     cli.dispatch(["upload", "path/to/file"])
     result_kwargs = replaced_upload.calls[0].kwargs
     assert "pypipassword" == result_kwargs["password"]
     assert "pypiuser" == result_kwargs["username"]
+    assert "/foo/bar.crt" == result_kwargs["cert"]
     result_kwargs = replaced_upload.calls[1].kwargs
     assert None is result_kwargs["password"]
     assert None is result_kwargs["username"]
+    assert None is result_kwargs["cert"]