Repository: semantic-release/semantic-release
Pull request #1671 (2020-10-28 14:50:34)

Don't parse port as part of the path in repository URLs
See #1670 for details about the issue. Here is a regular expression proposal that supports port parsing :

```
^(?!.+:\/\/)(?:(?<auth>.*)@)?(?<host>.*?):(?<port>\d+)?:?\/?(?<path>.*)$
```

It is parsing as expected the following example URLs :

```
localhost:2080/git/test.git
localhost.null:2080/git/test.git
localhost.null:git/test.git
localhost.null:/git/test.git

localhost:2080/group/git/test.git
localhost.null:2080/group/git/test.git
localhost.null:group/git/test.git
localhost.null:/group/git/test.git

git@localhost:2080/git/test.git
git@localhost.null:2080/git/test.git
git@localhost.null:git/test.git
git@localhost.null:/git/test.git

git:pass@localhost:2080/git/test.git
git:pass@localhost.null:2080/git/test.git
git:pass@localhost.null:git/test.git
git:pass@localhost.null:/git/test.git
```


Patch:
diff --git a/lib/get-git-auth-url.js b/lib/get-git-auth-url.js
index 2ebb84a..c6c3e8b 100644
--- a/lib/get-git-auth-url.js
+++ b/lib/get-git-auth-url.js
@@ -53,10 +53,10 @@ module.exports = async ({cwd, env, branch, options: {repositoryUrl}}) => {
 
     if (gitCredentials) {
       // If credentials are set via environment variables, convert the URL to http/https and add basic auth, otherwise return `repositoryUrl` as is
-      const [match, auth, host, path] =
-        /^(?!.+:\/\/)(?:(?<auth>.*)@)?(?<host>.*?):(?<path>.*)$/.exec(repositoryUrl) || [];
+      const [match, auth, host, basePort, path] =
+        /^(?!.+:\/\/)(?:(?<auth>.*)@)?(?<host>.*?):(?<port>\d+)?:?\/?(?<path>.*)$/.exec(repositoryUrl) || [];
       const {port, hostname, ...parsed} = parse(
-        match ? `ssh://${auth ? `${auth}@` : ''}${host}/${path}` : repositoryUrl
+        match ? `ssh://${auth ? `${auth}@` : ''}${host}${basePort ? `:${basePort}` : ''}/${path}` : repositoryUrl
       );
 
       return format({


Test patch:
diff --git a/test/get-git-auth-url.test.js b/test/get-git-auth-url.test.js
index 67ae935..a571178 100644
--- a/test/get-git-auth-url.test.js
+++ b/test/get-git-auth-url.test.js
@@ -133,6 +133,32 @@ test('Return the "https" formatted URL if "gitCredentials" is defined and reposi
   );
 });
 
+test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git" URL without user and with a custom port', async (t) => {
+  const {cwd} = await gitRepo();
+
+  t.is(
+    await getAuthUrl({
+      cwd,
+      env: {...env, GIT_CREDENTIALS: 'user:pass'},
+      options: {branch: 'master', repositoryUrl: 'host.null:6666:owner/repo.git'},
+    }),
+    'https://user:pass@host.null:6666/owner/repo.git'
+  );
+});
+
+test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git" URL without user and with a custom port followed by a slash', async (t) => {
+  const {cwd} = await gitRepo();
+
+  t.is(
+    await getAuthUrl({
+      cwd,
+      env: {...env, GIT_CREDENTIALS: 'user:pass'},
+      options: {branch: 'master', repositoryUrl: 'host.null:6666:/owner/repo.git'},
+    }),
+    'https://user:pass@host.null:6666/owner/repo.git'
+  );
+});
+
 test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "https" URL', async (t) => {
   const {cwd} = await gitRepo();