Repository: intuit/auto
Pull request #969 (2020-02-22 00:26:08)

ensure remote can be pushed to
# What Changed

Make sure we can push to the remote 

# Why

This will make it so you don't have to configure known hosts for `auto` and will not have to fuss with the remote url + tokens at all.

Todo:

- [ ] Add tests
- [x] Add docs

<!-- GITHUB_RELEASE PR BODY: canary-version -->
<details>
  <summary>📦 Published PR as canary version: <code>under canary scope @auto-canary@9.12.0-canary.969.12658.0</code></summary>
  <br />
  
  :sparkles: Test out this PR locally via:
  
  ```sh
  npm install @auto-canary/auto@9.12.0-canary.969.12658.0
  npm install @auto-canary/core@9.12.0-canary.969.12658.0
  npm install @auto-canary/all-contributors@9.12.0-canary.969.12658.0
  npm install @auto-canary/chrome@9.12.0-canary.969.12658.0
  npm install @auto-canary/conventional-commits@9.12.0-canary.969.12658.0
  npm install @auto-canary/crates@9.12.0-canary.969.12658.0
  npm install @auto-canary/first-time-contributor@9.12.0-canary.969.12658.0
  npm install @auto-canary/git-tag@9.12.0-canary.969.12658.0
  npm install @auto-canary/gradle@9.12.0-canary.969.12658.0
  npm install @auto-canary/jira@9.12.0-canary.969.12658.0
  npm install @auto-canary/maven@9.12.0-canary.969.12658.0
  npm install @auto-canary/npm@9.12.0-canary.969.12658.0
  npm install @auto-canary/omit-commits@9.12.0-canary.969.12658.0
  npm install @auto-canary/omit-release-notes@9.12.0-canary.969.12658.0
  npm install @auto-canary/released@9.12.0-canary.969.12658.0
  npm install @auto-canary/s3@9.12.0-canary.969.12658.0
  npm install @auto-canary/slack@9.12.0-canary.969.12658.0
  npm install @auto-canary/twitter@9.12.0-canary.969.12658.0
  npm install @auto-canary/upload-assets@9.12.0-canary.969.12658.0
  # or 
  yarn add @auto-canary/auto@9.12.0-canary.969.12658.0
  yarn add @auto-canary/core@9.12.0-canary.969.12658.0
  yarn add @auto-canary/all-contributors@9.12.0-canary.969.12658.0
  yarn add @auto-canary/chrome@9.12.0-canary.969.12658.0
  yarn add @auto-canary/conventional-commits@9.12.0-canary.969.12658.0
  yarn add @auto-canary/crates@9.12.0-canary.969.12658.0
  yarn add @auto-canary/first-time-contributor@9.12.0-canary.969.12658.0
  yarn add @auto-canary/git-tag@9.12.0-canary.969.12658.0
  yarn add @auto-canary/gradle@9.12.0-canary.969.12658.0
  yarn add @auto-canary/jira@9.12.0-canary.969.12658.0
  yarn add @auto-canary/maven@9.12.0-canary.969.12658.0
  yarn add @auto-canary/npm@9.12.0-canary.969.12658.0
  yarn add @auto-canary/omit-commits@9.12.0-canary.969.12658.0
  yarn add @auto-canary/omit-release-notes@9.12.0-canary.969.12658.0
  yarn add @auto-canary/released@9.12.0-canary.969.12658.0
  yarn add @auto-canary/s3@9.12.0-canary.969.12658.0
  yarn add @auto-canary/slack@9.12.0-canary.969.12658.0
  yarn add @auto-canary/twitter@9.12.0-canary.969.12658.0
  yarn add @auto-canary/upload-assets@9.12.0-canary.969.12658.0
  ```
</details>
<!-- GITHUB_RELEASE PR BODY: canary-version -->



Patch:
diff --git a/docs/pages/build-platforms/github-actions.md b/docs/pages/build-platforms/github-actions.md
index 60ae9f36..8221a040 100644
--- a/docs/pages/build-platforms/github-actions.md
+++ b/docs/pages/build-platforms/github-actions.md
@@ -23,16 +23,6 @@ jobs:
     steps:
       - uses: actions/checkout@v1
 
-      - name: Prepare repository
-        env:
-          GH_TOKEN: ${{ secrets.GH_TOKEN }}
-        run: |
-          git checkout ${GITHUB_REF:11} --
-          git remote rm origin
-          git remote add origin "https://x-access-token:$GH_TOKEN@github.com/<owner>/<repo>.git"
-          git fetch origin --tags
-          git branch --set-upstream-to origin/${GITHUB_REF:11} ${GITHUB_REF:11}
-
       - name: Use Node.js 12.x
         uses: actions/setup-node@v1
         with:
diff --git a/docs/pages/build-platforms/jenkins.md b/docs/pages/build-platforms/jenkins.md
index 40ac2c6c..95a19d7d 100644
--- a/docs/pages/build-platforms/jenkins.md
+++ b/docs/pages/build-platforms/jenkins.md
@@ -32,16 +32,6 @@ pipeline {
         }
       }
     }
-    stage('Auth') {
-      steps {
-        sh '''
-          echo "https://${GH_USER}:${GH_TOKEN}@github.com" >> /tmp/gitcredfile
-          git config --global user.name "Andrew Lisowski"
-          git config --global user.email "lisowski54@gmail.com"
-          git config --global credential.helper "store --file=/tmp/gitcredfile"
-        '''
-      }
-    }
     stage('Install') {
       steps {
         sh 'yarn install --frozen-lockfile'
diff --git a/docs/pages/build-platforms/travis.md b/docs/pages/build-platforms/travis.md
index 727c4a58..785aff20 100644
--- a/docs/pages/build-platforms/travis.md
+++ b/docs/pages/build-platforms/travis.md
@@ -5,7 +5,7 @@ The following config declares the `deploy` job that run on all branches. The job
 - a new `latest` version from `master`
 - a `canary` build from a pull request (if your package manager plugin implements them)
 
-**`.circleci/config.yml`**
+**`.travis.yml`**
 
 ```yaml
 language: node_js
@@ -20,14 +20,6 @@ script:
   - yarn test
   - yarn build
 
-before_deploy:
-  - git config --local user.name "${GIT_NAME}"
-  - git config --local user.email "${GIT_EMAIL}"
-  - git remote rm origin
-  - git remote add origin https://${GH_TOKEN}@github.com/hipstersmoothie/my-test-project
-  - git fetch origin --tags
-  - git checkout master
-  - git branch --set-upstream-to origin/master master
 deploy:
   skip_cleanup: true
   provider: script
diff --git a/docs/pages/writing-plugins.md b/docs/pages/writing-plugins.md
index a5adbedc..ca022d74 100644
--- a/docs/pages/writing-plugins.md
+++ b/docs/pages/writing-plugins.md
@@ -329,7 +329,7 @@ auto.hooks.publish.tapPromise('NPM', async (version: SEMVER) => {
     'push',
     '--follow-tags',
     '--set-upstream',
-    'origin',
+    auto.remote,
     '$branch'
   ]);
 });
@@ -632,7 +632,7 @@ export default class NPMPlugin {
         'push',
         '--follow-tags',
         '--set-upstream',
-        'origin',
+        auto.remote,
         '$branch'
       ]);
     });
diff --git a/packages/core/src/auto.ts b/packages/core/src/auto.ts
index 548b9665..62544671 100644
--- a/packages/core/src/auto.ts
+++ b/packages/core/src/auto.ts
@@ -16,6 +16,7 @@ import {
   AsyncSeriesWaterfallHook
 } from 'tapable';
 import endent from 'endent';
+import { parse as parseUrl, format } from 'url';
 import on from 'await-to-js';
 
 import createHttpsProxyAgent from 'https-proxy-agent';
@@ -310,6 +311,8 @@ export default class Auto {
   options: ApiOptions;
   /** The branch auto uses as master. */
   baseBranch: string;
+  /** The remote git to push changes to */
+  remote!: string;
   /** The user configuration of auto (.autorc) */
   config?: IAutoConfig;
 
@@ -364,7 +367,7 @@ export default class Auto {
             'branch',
             await this.git?.getLatestTagInBranch()
           ]);
-          await execPromise('git', ['push', 'origin', branch]);
+          await execPromise('git', ['push', this.remote, branch]);
         }
       }
     );
@@ -448,10 +451,58 @@ export default class Auto {
 
     this.git = this.startGit(githubOptions as IGitOptions);
     this.release = new Release(this.git, config, this.logger);
-
+    this.remote = await this.getRemote();
+    this.logger.verbose.info(
+      `Using remote: ${this.remote.replace(token, `****${token.substring(0, 4)}`)}`
+    );
     this.hooks.onCreateRelease.call(this.release);
   }
 
+  /** Determine the remote we have auth to push to. */
+  private async getRemote(): Promise<string> {
+    const [, configuredRemote = 'origin'] = await on(execPromise('git', [
+      'remote',
+      'get-url',
+      'origin'
+    ]));
+
+    if (!this.git) {
+      return configuredRemote;
+    }
+
+    const { html_url } = (await this.git.getProject()) || { html_url: '' };
+
+    if (html_url && (await this.git.verifyAuth(html_url))) {
+      return html_url;
+    }
+
+    const GIT_TOKENS: Record<string, string | undefined> = {
+      // GitHub Actions require the "x-access-token:" prefix for git access
+      // https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#http-based-git-access-by-an-installation
+      GITHUB_TOKEN: process.env.GITHUB_ACTION ? 'x-access-token:' : undefined
+    };
+    const envVar = Object.keys(GIT_TOKENS).find(v => process.env[v]) || '';
+    const gitCredentials = GIT_TOKENS[envVar]
+      ? `${GIT_TOKENS[envVar] || ''}${process.env[envVar] || ''}`
+      : process.env.GH_TOKEN;
+
+    if (gitCredentials) {
+      const { port, hostname, ...parsed } = parseUrl(html_url);
+
+      const urlWithAuth = format({
+        ...parsed,
+        auth: gitCredentials,
+        host: `${hostname}${port ? `:${port}` : ''}`
+      });
+
+      if (await this.git.verifyAuth(urlWithAuth)) {
+        return urlWithAuth;
+      }
+    }
+
+    return configuredRemote;
+  }
+
   /** Interactive prompt for initializing an .autorc */
   async init() {
     const init = new InteractiveInit(this);
@@ -1089,7 +1140,7 @@ export default class Auto {
 
   /** Force a release to latest and bypass `shipit` safeguards. */
   async latest(options: IShipItOptions = {}) {
-    await this.publishFullRelease(options)
+    await this.publishFullRelease(options);
   }
 
   /**
diff --git a/packages/core/src/git.ts b/packages/core/src/git.ts
index d1ab0544..32b2925b 100644
--- a/packages/core/src/git.ts
+++ b/packages/core/src/git.ts
@@ -135,6 +135,19 @@ export default class Git {
     });
   }
 
+  /** Verify the write access authorization to remote repository with push dry-run. */
+  async verifyAuth(url: string) {
+    try {
+      await execPromise(
+        'git',
+        ['push', '--dry-run', '--no-verify', url, `HEAD:${this.options.baseBranch}`, '-q']
+      );
+      return true;
+    } catch (error) {
+      return false;
+    }
+  }
+
   /** Get the "Latest Release" from GitHub */
   @memoize()
   async getLatestReleaseInfo() {
diff --git a/plugins/chrome/src/index.ts b/plugins/chrome/src/index.ts
index ca11d86c..a5678b60 100644
--- a/plugins/chrome/src/index.ts
+++ b/plugins/chrome/src/index.ts
@@ -171,7 +171,7 @@ export default class ChromeWebStorePlugin implements IPlugin {
         'push',
         '--follow-tags',
         '--set-upstream',
-        'origin',
+        auto.remote,
         auto.baseBranch
       ]);
     });
diff --git a/plugins/crates/src/index.ts b/plugins/crates/src/index.ts
index 48981b80..6d3d35ef 100644
--- a/plugins/crates/src/index.ts
+++ b/plugins/crates/src/index.ts
@@ -110,7 +110,7 @@ export default class CratesPlugin implements IPlugin {
         'push',
         '--follow-tags',
         '--set-upstream',
-        'origin',
+        auto.remote,
         auto.baseBranch
       ]);
       auto.logger.log.info('Push complete');
diff --git a/plugins/git-tag/src/index.ts b/plugins/git-tag/src/index.ts
index 3d7377a8..36b0afef 100644
--- a/plugins/git-tag/src/index.ts
+++ b/plugins/git-tag/src/index.ts
@@ -62,7 +62,7 @@ export default class GitTagPlugin implements IPlugin {
         'push',
         '--follow-tags',
         '--set-upstream',
-        'origin',
+        auto.remote,
         branch || auto.baseBranch
       ]);
     });
@@ -94,7 +94,7 @@ export default class GitTagPlugin implements IPlugin {
         '-m',
         `"Tag pre-release: ${prerelease}"`
       ]);
-      await execPromise('git', ['push', '--tags']);
+      await execPromise('git', ['push', auto.remote, '--tags']);
 
       return preReleaseVersions;
     });
diff --git a/plugins/gradle/src/index.ts b/plugins/gradle/src/index.ts
index 20f93d84..8edf7b83 100644
--- a/plugins/gradle/src/index.ts
+++ b/plugins/gradle/src/index.ts
@@ -114,7 +114,7 @@ export default class GradleReleasePluginPlugin implements IPlugin {
         'push',
         '--follow-tags',
         '--set-upstream',
-        'origin',
+        auto.remote,
         auto.baseBranch
       ]);
     });
diff --git a/plugins/maven/src/index.ts b/plugins/maven/src/index.ts
index dcee28ba..9fd7a681 100644
--- a/plugins/maven/src/index.ts
+++ b/plugins/maven/src/index.ts
@@ -156,7 +156,7 @@ export default class MavenPlugin implements IPlugin {
         'push',
         '--follow-tags',
         '--set-upstream',
-        'origin',
+        auto.remote,
         auto.baseBranch
       ]);
 
@@ -174,7 +174,7 @@ export default class MavenPlugin implements IPlugin {
       // prepare for next development iteration
       await execPromise('git', ['reset', '--hard', 'dev-snapshot']);
       await execPromise('git', ['branch', '-d', 'dev-snapshot']);
-      await execPromise('git', ['push', 'origin', auto.baseBranch]);
+      await execPromise('git', ['push', auto.remote, auto.baseBranch]);
     });
   }
 }
diff --git a/plugins/npm/src/index.ts b/plugins/npm/src/index.ts
index ade8cfd6..bf8e1355 100644
--- a/plugins/npm/src/index.ts
+++ b/plugins/npm/src/index.ts
@@ -848,7 +848,7 @@ export default class NPMPlugin implements IPlugin {
         preReleaseVersions.push(auto.prefixRelease(version!));
       }
 
-      await execPromise('git', ['push', '--tags']);
+      await execPromise('git', ['push', auto.remote, '--tags']);
       return preReleaseVersions;
     });
 
@@ -897,7 +897,7 @@ export default class NPMPlugin implements IPlugin {
         'push',
         '--follow-tags',
         '--set-upstream',
-        'origin',
+        auto.remote,
         branch || auto.baseBranch
       ]);
       auto.logger.verbose.info('Successfully published repo');


Test patch:
diff --git a/packages/core/src/__tests__/auto-canary-local.test.ts b/packages/core/src/__tests__/auto-canary-local.test.ts
index 1d2c15b5..3e4a20f6 100644
--- a/packages/core/src/__tests__/auto-canary-local.test.ts
+++ b/packages/core/src/__tests__/auto-canary-local.test.ts
@@ -12,6 +12,24 @@ const defaults = {
   token: 'XXXX'
 };
 
+jest.mock('@octokit/rest', () => {
+  const Octokit = class MockOctokit {
+    static plugin = () => Octokit;
+
+    authenticate = () => undefined;
+
+    repos = {
+      get: jest.fn().mockReturnValue({})
+    }
+
+    hook = {
+      error: () => undefined
+    };
+  };
+
+  return { Octokit };
+});
+
 test('shipit should publish canary in locally when not on master', async () => {
   const auto = new Auto({ ...defaults, plugins: [] });
   auto.logger = dummyLog();
diff --git a/packages/core/src/__tests__/auto-comment.test.ts b/packages/core/src/__tests__/auto-comment.test.ts
index fa627924..cdf7062a 100644
--- a/packages/core/src/__tests__/auto-comment.test.ts
+++ b/packages/core/src/__tests__/auto-comment.test.ts
@@ -9,6 +9,24 @@ const defaults = {
   token: 'XXXX'
 };
 
+jest.mock('@octokit/rest', () => {
+  const Octokit = class MockOctokit {
+    static plugin = () => Octokit;
+
+    authenticate = () => undefined;
+
+    repos = {
+      get: jest.fn().mockReturnValue({})
+    }
+
+    hook = {
+      error: () => undefined
+    };
+  };
+
+  return { Octokit };
+});
+
 describe('comment', () => {
   test('should find PR number from CI', async () => {
     const auto = new Auto(defaults);
diff --git a/packages/core/src/__tests__/auto-in-pr-ci.test.ts b/packages/core/src/__tests__/auto-in-pr-ci.test.ts
index 92029f49..1f2e5664 100644
--- a/packages/core/src/__tests__/auto-in-pr-ci.test.ts
+++ b/packages/core/src/__tests__/auto-in-pr-ci.test.ts
@@ -18,6 +18,24 @@ const defaults = {
   token: 'XXXX'
 };
 
+jest.mock('@octokit/rest', () => {
+  const Octokit = class MockOctokit {
+    static plugin = () => Octokit;
+
+    authenticate = () => undefined;
+
+    repos = {
+      get: jest.fn().mockReturnValue({})
+    }
+
+    hook = {
+      error: () => undefined
+    };
+  };
+
+  return { Octokit };
+});
+
 describe('canary in ci', () => {
   test('calls the canary hook with the canary version', async () => {
     const auto = new Auto({ ...defaults, plugins: [] });
diff --git a/packages/core/src/__tests__/auto-make-changelog.test.ts b/packages/core/src/__tests__/auto-make-changelog.test.ts
index f38d199d..65b8cd64 100644
--- a/packages/core/src/__tests__/auto-make-changelog.test.ts
+++ b/packages/core/src/__tests__/auto-make-changelog.test.ts
@@ -11,7 +11,7 @@ jest
 const importMock = jest.fn();
 jest.mock('import-cwd', () => (path: string) => importMock(path));
 jest.mock('env-ci', () => () => ({ isCi: false, branch: 'master' }));
-jest.mock('../utils/exec-promise', () => () => '');
+jest.mock('../utils/exec-promise', () => () => Promise.resolve(''));
 
 const defaults = {
   owner: 'foo',
@@ -36,6 +36,10 @@ jest.mock('@octokit/rest', () => {
       issuesAndPullRequests: () => ({ data: { items: [] } })
     };
 
+    repos = {
+      get: jest.fn().mockReturnValue(Promise.resolve({}))
+    }
+
     hook = {
       error: () => undefined
     };
diff --git a/packages/core/src/__tests__/auto.test.ts b/packages/core/src/__tests__/auto.test.ts
index 39306dc8..d25f87cd 100644
--- a/packages/core/src/__tests__/auto.test.ts
+++ b/packages/core/src/__tests__/auto.test.ts
@@ -46,6 +46,10 @@ jest.mock('@octokit/rest', () => {
       issuesAndPullRequests: () => ({ data: { items: [] } })
     };
 
+    repos = {
+      get: jest.fn().mockReturnValue({})
+    };
+
     hook = {
       error: () => undefined
     };
diff --git a/packages/core/src/__tests__/remote.test.ts b/packages/core/src/__tests__/remote.test.ts
new file mode 100644
index 00000000..957415b1
--- /dev/null
+++ b/packages/core/src/__tests__/remote.test.ts
@@ -0,0 +1,117 @@
+import Auto from '../auto';
+import { dummyLog } from '../utils/logger';
+
+const defaultRemote = 'git@github.foo.com'
+const defaults = {
+  owner: 'foo',
+  repo: 'bar',
+  token: 'XXXX'
+};
+
+const reposGet = jest.fn();
+
+jest.mock('@octokit/rest', () => {
+  const Octokit = class MockOctokit {
+    static plugin = () => Octokit;
+
+    authenticate = () => undefined;
+
+    repos = {
+      get: reposGet
+    };
+
+    hook = {
+      error: () => undefined
+    };
+  };
+
+  return { Octokit };
+});
+
+const execSpy = jest.fn();
+// @ts-ignore
+jest.mock('../utils/exec-promise.ts', () => (...args) => execSpy(...args));
+
+
+describe('remote parsing', () => {
+  test('should fall back to origin when no git', async () => {
+    const auto = new Auto(defaults);
+    auto.logger = dummyLog();
+
+    execSpy.mockReturnValue(Promise.resolve())
+
+    // @ts-ignore
+    expect(await auto.getRemote()).toBe('origin');
+  });
+
+
+  test('should fall back to configured remote when no git', async () => {
+    const auto = new Auto(defaults);
+    auto.logger = dummyLog();
+
+    execSpy.mockReturnValue(Promise.resolve(defaultRemote))
+
+    // @ts-ignore
+    expect(await auto.getRemote()).toBe(defaultRemote);
+  });
+
+  test('should fall back to configured remote', async () => {
+    const auto = new Auto(defaults);
+    auto.logger = dummyLog();
+
+    execSpy.mockReturnValue(Promise.resolve(defaultRemote))
+    auto.git = {
+      getProject: () => {},
+      verifyAuth: () => false
+    } as any
+
+    // @ts-ignore
+    expect(await auto.getRemote()).toBe(defaultRemote);
+  });
+
+  test('use html_url when authed', async () => {
+    const html_url = 'https://my.repo'
+    const auto = new Auto(defaults);
+    auto.logger = dummyLog();
+
+    execSpy.mockReturnValue(Promise.resolve(defaultRemote))
+    auto.git = {
+      getProject: () => ({ html_url }),
+      verifyAuth: () => true
+    } as any
+
+    // @ts-ignore
+    expect(await auto.getRemote()).toBe(html_url);
+  });
+
+  test('use fall back to default when not authed', async () => {
+    const html_url = 'https://my.repo'
+    const auto = new Auto(defaults);
+    auto.logger = dummyLog();
+
+    execSpy.mockReturnValue(Promise.resolve(defaultRemote))
+    auto.git = {
+      getProject: () => ({ html_url }),
+      verifyAuth: () => false
+    } as any
+
+    // @ts-ignore
+    expect(await auto.getRemote()).toBe(defaultRemote);
+  });
+
+  test('add token to url if html doesn\'t auth', async () => {
+    const html_url = 'https://my.repo'
+    const auto = new Auto(defaults);
+    process.env.GH_TOKEN = 'XXXX'
+    auto.logger = dummyLog();
+
+    execSpy.mockReturnValue(Promise.resolve(defaultRemote))
+    auto.git = {
+      getProject: () => ({ html_url }),
+      verifyAuth: (url: string) => url !== html_url
+    } as any
+
+    // @ts-ignore
+    expect(await auto.getRemote()).toBe("https://XXXX@my.repo/");
+  });
+});
diff --git a/plugins/crates/__tests__/crates.test.ts b/plugins/crates/__tests__/crates.test.ts
index b8d4574d..6e42475d 100644
--- a/plugins/crates/__tests__/crates.test.ts
+++ b/plugins/crates/__tests__/crates.test.ts
@@ -221,6 +221,7 @@ describe('CratesPlugin', () => {
         plugin.apply({
           hooks,
           logger: dummyLog(),
+          remote: 'origin',
           baseBranch: 'master'
         } as Auto.Auto);
         await hooks.publish.promise(Auto.SEMVER.patch);
diff --git a/plugins/git-tag/__tests__/git-tag.test.ts b/plugins/git-tag/__tests__/git-tag.test.ts
index 60a795a3..657ae3da 100644
--- a/plugins/git-tag/__tests__/git-tag.test.ts
+++ b/plugins/git-tag/__tests__/git-tag.test.ts
@@ -14,6 +14,7 @@ const setup = (mockGit?: any) => {
   plugin.apply(({
     hooks,
     git: mockGit,
+    remote: 'origin',
     logger: dummyLog(),
     prefixRelease: (r: string) => r,
     config: { prereleaseBranches: ['next'] },
@@ -99,7 +100,7 @@ describe('Git Tag Plugin', () => {
         '-m',
         '"Tag pre-release: 1.0.1-next.0"'
       ]);
-      expect(exec).toHaveBeenCalledWith('git', ['push', '--tags']);
+      expect(exec).toHaveBeenCalledWith('git', ['push', 'origin', '--tags']);
     });
   });
 });
diff --git a/plugins/npm/__tests__/npm.test.ts b/plugins/npm/__tests__/npm.test.ts
index 760654ae..bae69b52 100644
--- a/plugins/npm/__tests__/npm.test.ts
+++ b/plugins/npm/__tests__/npm.test.ts
@@ -163,6 +163,7 @@ describe('getAuthor', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -182,6 +183,7 @@ describe('getAuthor', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -208,6 +210,7 @@ describe('getAuthor', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -233,6 +236,7 @@ describe('getRepository', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -264,6 +268,7 @@ describe('getPreviousVersion', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog(),
       prefixRelease: str => str
@@ -286,6 +291,7 @@ describe('getPreviousVersion', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog(),
       prefixRelease: str => str
@@ -309,6 +315,7 @@ describe('getPreviousVersion', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog(),
       prefixRelease: str => str
@@ -342,6 +349,7 @@ describe('getPreviousVersion', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog(),
       prefixRelease: str => str
@@ -377,6 +385,7 @@ describe('publish', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger
     } as Auto.Auto);
@@ -406,6 +415,7 @@ describe('publish', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -433,6 +443,7 @@ describe('publish', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -468,6 +479,7 @@ describe('publish', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -503,6 +515,7 @@ describe('publish', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -538,6 +551,7 @@ describe('publish', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -560,6 +574,7 @@ describe('publish', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -590,6 +605,7 @@ describe('publish', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -626,6 +642,7 @@ describe('publish', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -654,6 +671,7 @@ describe('canary', () => {
     plugin.apply(({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog(),
       getCurrentVersion: () => '1.2.3',
@@ -681,6 +699,7 @@ describe('canary', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog(),
       git: {
@@ -724,6 +743,7 @@ describe('canary', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog(),
       git: {
@@ -767,6 +787,7 @@ describe('canary', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog()
     } as Auto.Auto);
@@ -816,6 +837,7 @@ describe('canary', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog(),
       git: {
@@ -866,6 +888,7 @@ describe('next', () => {
     plugin.apply(({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog(),
       getCurrentVersion: () => '1.2.3',
@@ -898,7 +921,7 @@ describe('next', () => {
       '-m',
       '"Update version to 1.2.4-next.0"'
     ]);
-    expect(exec).toHaveBeenCalledWith('git', ['push', '--tags']);
+    expect(exec).toHaveBeenCalledWith('git', ['push', 'origin', '--tags']);
     expect(exec).toHaveBeenCalledWith('npm', ['publish', '--tag', 'next']);
   });
 
@@ -915,6 +938,7 @@ describe('next', () => {
     plugin.apply(({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog(),
       getCurrentVersion: () => '1.2.3',
@@ -933,7 +957,7 @@ describe('next', () => {
       'npx',
       expect.arrayContaining(['lerna', 'publish', '1.2.4-next.0'])
     );
-    expect(exec).toHaveBeenCalledWith('git', ['push', '--tags']);
+    expect(exec).toHaveBeenCalledWith('git', ['push', 'origin', '--tags']);
   });
 
   test('works in monorepo - independent', async () => {
@@ -949,6 +973,7 @@ describe('next', () => {
     plugin.apply(({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog(),
       prefixRelease: (v: string) => v,
@@ -967,7 +992,7 @@ describe('next', () => {
       'npx',
       expect.arrayContaining(['lerna', 'publish', 'prerelease'])
     );
-    expect(exec).toHaveBeenCalledWith('git', ['push', '--tags']);
+    expect(exec).toHaveBeenCalledWith('git', ['push', 'origin', '--tags']);
   });
 });
 
@@ -987,6 +1012,7 @@ describe('makeRelease', () => {
     plugin.apply({
       config: { prereleaseBranches: ['next'] },
       hooks,
+      remote: 'origin',
       baseBranch: 'master',
       logger: dummyLog(),
       prefixRelease: str => str,