diff --git a/lib/platform/github/__snapshots__/index.spec.ts.snap b/lib/platform/github/__snapshots__/index.spec.ts.snap
index 8694755cc923de746c5edb6279e0fa4e33a9d400..94255613d0d741fbbe0b0a2364a35d728bf70155 100644
--- a/lib/platform/github/__snapshots__/index.spec.ts.snap
+++ b/lib/platform/github/__snapshots__/index.spec.ts.snap
@@ -4544,6 +4544,14 @@ Array [
 ]
 `;
 
+exports[`platform/github initPlatform() should support gitAuthor and username 1`] = `
+Object {
+  "endpoint": "https://api.github.com/",
+  "gitAuthor": "renovate@whitesourcesoftware.com",
+  "renovateUsername": "renovate-bot",
+}
+`;
+
 exports[`platform/github initPlatform() should throw if user failure 1`] = `
 Array [
   Object {
diff --git a/lib/platform/github/index.spec.ts b/lib/platform/github/index.spec.ts
index 1310d3bfeb292d6f0e7c64b1ded36d805bebd351..ea8df4b18bc746eb8878e619978c1dbc0109e0be 100644
--- a/lib/platform/github/index.spec.ts
+++ b/lib/platform/github/index.spec.ts
@@ -93,6 +93,15 @@ describe('platform/github', () => {
       ).toMatchSnapshot();
       expect(httpMock.getTrace()).toMatchSnapshot();
     });
+    it('should support gitAuthor and username', async () => {
+      expect(
+        await github.initPlatform({
+          token: 'abc123',
+          username: 'renovate-bot',
+          gitAuthor: 'renovate@whitesourcesoftware.com',
+        } as any)
+      ).toMatchSnapshot();
+    });
     it('should support default endpoint with email', async () => {
       httpMock
         .scope(githubApiHost)
diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts
index 9fcf7bac12190ff243481ff4df1b04a670e2829d..b98c505df50c204f8c82d3ba669ead3587ce7b3a 100644
--- a/lib/platform/github/index.ts
+++ b/lib/platform/github/index.ts
@@ -55,6 +55,7 @@ import {
   LocalRepoConfig,
   PrList,
 } from './types';
+import { UserDetails, getUserDetails, getUserEmail } from './user';
 
 const githubApi = new githubHttp.GithubHttp();
 
@@ -73,9 +74,13 @@ const escapeHash = (input: string): string =>
 export async function initPlatform({
   endpoint,
   token,
+  username,
+  gitAuthor,
 }: {
   endpoint: string;
   token: string;
+  username?: string;
+  gitAuthor?: string;
 }): Promise<PlatformResult> {
   if (!token) {
     throw new Error('Init: You must configure a GitHub personal access token');
@@ -87,48 +92,26 @@ export async function initPlatform({
   } else {
     logger.debug('Using default github endpoint: ' + defaults.endpoint);
   }
-  let gitAuthor: string;
+  let userDetails: UserDetails;
   let renovateUsername: string;
-  try {
-    const userData = (
-      await githubApi.getJson<{ login: string; name: string }>(
-        defaults.endpoint + 'user',
-        {
-          token,
-        }
-      )
-    ).body;
-    renovateUsername = userData.login;
-    gitAuthor = userData.name;
-  } catch (err) {
-    logger.debug({ err }, 'Error authenticating with GitHub');
-    throw new Error('Init: Authentication failure');
+  if (username) {
+    renovateUsername = username;
+  } else {
+    userDetails = await getUserDetails(defaults.endpoint, token);
+    renovateUsername = userDetails.username;
   }
-  try {
-    const userEmail = (
-      await githubApi.getJson<{ email: string }[]>(
-        defaults.endpoint + 'user/emails',
-        {
-          token,
-        }
-      )
-    ).body;
-    if (userEmail.length && userEmail[0].email) {
-      gitAuthor += ` <${userEmail[0].email}>`;
-    } else {
-      logger.debug('Cannot find an email address for Renovate user');
-      gitAuthor = undefined;
+  let discoveredGitAuthor: string;
+  if (!gitAuthor) {
+    userDetails = await getUserDetails(defaults.endpoint, token);
+    const userEmail = await getUserEmail(defaults.endpoint, token);
+    if (userEmail) {
+      discoveredGitAuthor = `${userDetails.name} <${userEmail}>`;
     }
-  } catch (err) {
-    logger.debug(
-      'Cannot read user/emails endpoint on GitHub to retrieve gitAuthor'
-    );
-    gitAuthor = undefined;
   }
   logger.debug('Authenticated as GitHub user: ' + renovateUsername);
   const platformConfig: PlatformResult = {
     endpoint: defaults.endpoint,
-    gitAuthor,
+    gitAuthor: gitAuthor || discoveredGitAuthor,
     renovateUsername,
   };
   return platformConfig;
diff --git a/lib/platform/github/user.ts b/lib/platform/github/user.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fb7f2a08d18cc0b123e20f25caf3082cc4c69ca8
--- /dev/null
+++ b/lib/platform/github/user.ts
@@ -0,0 +1,60 @@
+import { logger } from '../../logger';
+import * as githubHttp from '../../util/http/github';
+
+const githubApi = new githubHttp.GithubHttp();
+
+export interface UserDetails {
+  username: string;
+  name: string;
+}
+
+let userDetails: UserDetails;
+
+export async function getUserDetails(
+  endpoint: string,
+  token: string
+): Promise<UserDetails> {
+  if (userDetails) {
+    return userDetails;
+  }
+  try {
+    const userData = (
+      await githubApi.getJson<{ login: string; name: string }>(
+        endpoint + 'user',
+        {
+          token,
+        }
+      )
+    ).body;
+    userDetails = {
+      username: userData.login,
+      name: userData.name,
+    };
+    return userDetails;
+  } catch (err) {
+    logger.debug({ err }, 'Error authenticating with GitHub');
+    throw new Error('Init: Authentication failure');
+  }
+}
+
+let userEmail: string;
+
+export async function getUserEmail(
+  endpoint: string,
+  token: string
+): Promise<string | null> {
+  try {
+    const emails = (
+      await githubApi.getJson<{ email: string }[]>(endpoint + 'user/emails', {
+        token,
+      })
+    ).body;
+    userEmail = emails?.[0].email || null;
+    return userEmail;
+  } catch (err) {
+    logger.debug(
+      'Cannot read user/emails endpoint on GitHub to retrieve gitAuthor'
+    );
+    return null;
+  }
+}