Repository: canonical/snapcraft

Issue:
Make script aware of 407 when downloading gradle
builds.snapcraft.io rejects downloading gradle.

```
Downloading https://services.gradle.org/distributions/gradle-4.0.2-bin.zip

Exception in thread "main" java.io.IOException: Unable to tunnel through proxy. Proxy returns "HTTP/1.1 407 Proxy Authentication Required"
```

Source: https://build.snapcraft.io/user/JabRef/jabref/67152

An issue has been submitted - see https://github.com/canonical-websites/build.snapcraft.io/issues/918. I don't know, if this will be fixed or if it is easier to quickyl adapt `gradle.py`.

I assume, gradle.py has to be adapted accordingly? https://github.com/snapcore/snapcraft/blob/master/snapcraft/plugins/gradle.py#L88; if gradlew exists, execute it. If that fails with proxy 407 error (grepping stdout?), execute gradle


Discussion:

Resolving patch:
diff --git a/snapcraft/plugins/ant.py b/snapcraft/plugins/ant.py
--- a/snapcraft/plugins/ant.py
+++ b/snapcraft/plugins/ant.py
@@ -105,6 +105,10 @@ def get_proxy_options(self, scheme):
                 yield '-D{}.proxyHost={}'.format(scheme, parsed.hostname)
             if parsed.port is not None:
                 yield '-D{}.proxyPort={}'.format(scheme, parsed.port)
+            if parsed.username is not None:
+                yield '-D{}.proxyUser={}'.format(scheme, parsed.username)
+            if parsed.password is not None:
+                yield '-D{}.proxyPassword={}'.format(scheme, parsed.password)
 
     def env(self, root):
         env = super().env(root)
diff --git a/snapcraft/plugins/gradle.py b/snapcraft/plugins/gradle.py
--- a/snapcraft/plugins/gradle.py
+++ b/snapcraft/plugins/gradle.py
@@ -112,8 +112,6 @@ def build(self):
                 snapcraft.file_utils.link_or_copy(src, dst, self.installdir))
 
     def _get_proxy_options(self):
-        # XXX This doesn't yet support username and password.
-        # -- elopio - 2016-11-17
         proxy_options = []
         for var in ('http', 'https'):
             proxy = os.environ.get('{}_proxy'.format(var), False)
@@ -124,4 +122,11 @@ def _get_proxy_options(self):
                 if parsed_url.port:
                     proxy_options.append(
                         '-D{}.proxyPort={}'.format(var, parsed_url.port))
+                if parsed_url.username:
+                    proxy_options.append(
+                        '-D{}.proxyUser={}'.format(var, parsed_url.username))
+                if parsed_url.password:
+                    proxy_options.append(
+                        '-D{}.proxyPassword={}'.format(
+                            var, parsed_url.password))
         return proxy_options


Test patch:
diff --git a/snapcraft/tests/plugins/test_ant.py b/snapcraft/tests/plugins/test_ant.py
--- a/snapcraft/tests/plugins/test_ant.py
+++ b/snapcraft/tests/plugins/test_ant.py
@@ -123,11 +123,11 @@ def test_env(self):
 
     def test_env_proxies(self):
         env_vars = (
-            ('http_proxy', 'http://localhost:3132'),
-            ('https_proxy', 'http://localhost2:3133'),
+            ('http_proxy', 'http://user:pass@localhost:3132'),
+            ('https_proxy', 'http://user2:pass2@localhost2:3133'),
         )
-        for v in env_vars:
-            self.useFixture(fixtures.EnvironmentVariable(v[0], v[1]))
+        for key, value in env_vars:
+            self.useFixture(fixtures.EnvironmentVariable(key, value))
         plugin = ant.AntPlugin('test-part', self.options,
                                self.project_options)
 
@@ -135,5 +135,7 @@ def test_env_proxies(self):
         self.assertIn(
             "ANT_OPTS='"
             "-Dhttp.proxyHost=localhost -Dhttp.proxyPort=3132 "
-            "-Dhttps.proxyHost=localhost2 -Dhttps.proxyPort=3133'",
+            "-Dhttp.proxyUser=user -Dhttp.proxyPassword=pass "
+            "-Dhttps.proxyHost=localhost2 -Dhttps.proxyPort=3133 "
+            "-Dhttps.proxyUser=user2 -Dhttps.proxyPassword=pass2'",
             env)
diff --git a/snapcraft/tests/plugins/test_gradle.py b/snapcraft/tests/plugins/test_gradle.py
--- a/snapcraft/tests/plugins/test_gradle.py
+++ b/snapcraft/tests/plugins/test_gradle.py
@@ -217,6 +217,12 @@ class GradleProxyTestCase(BaseGradlePluginTestCase):
             env_var=('http_proxy', 'http://test_proxy:3000'),
             expected_args=['-Dhttp.proxyHost=test_proxy',
                            '-Dhttp.proxyPort=3000'])),
+        ('authenticated http proxy url', dict(
+            env_var=('http_proxy', 'http://user:pass@test_proxy:3000'),
+            expected_args=['-Dhttp.proxyHost=test_proxy',
+                           '-Dhttp.proxyPort=3000',
+                           '-Dhttp.proxyUser=user',
+                           '-Dhttp.proxyPassword=pass'])),
         ('https proxy url', dict(
             env_var=('https_proxy', 'https://test_proxy'),
             expected_args=['-Dhttps.proxyHost=test_proxy'])),
@@ -224,6 +230,12 @@ class GradleProxyTestCase(BaseGradlePluginTestCase):
             env_var=('https_proxy', 'https://test_proxy:3000'),
             expected_args=['-Dhttps.proxyHost=test_proxy',
                            '-Dhttps.proxyPort=3000'])),
+        ('authenticated https proxy url', dict(
+            env_var=('https_proxy', 'http://user:pass@test_proxy:3000'),
+            expected_args=['-Dhttps.proxyHost=test_proxy',
+                           '-Dhttps.proxyPort=3000',
+                           '-Dhttps.proxyUser=user',
+                           '-Dhttps.proxyPassword=pass'])),
     ]
 
     @mock.patch.object(gradle.GradlePlugin, 'run')
@@ -234,8 +246,7 @@ def test_build_with_http_proxy_gradle(self, run_mock):
                                      self.project_options)
 
         def side(l):
-            os.makedirs(os.path.join(plugin.builddir,
-                        'build', 'libs'))
+            os.makedirs(os.path.join(plugin.builddir, 'build', 'libs'))
             open(os.path.join(plugin.builddir,
                  'build', 'libs', 'dummy.war'), 'w').close()