diff --git a/lib/config/definitions.js b/lib/config/definitions.js
index dde22ceab759b46a54f710ac72ee8686cc335a1d..6f8dc3aadf7ad214a1cfc03911a4b9de46be4008 100644
--- a/lib/config/definitions.js
+++ b/lib/config/definitions.js
@@ -202,7 +202,6 @@ const options = [
   {
     name: 'platform',
     description: 'Platform type of repository',
-    stage: 'repository',
     type: 'string',
     default: 'github',
     admin: true,
@@ -602,7 +601,12 @@ const options = [
       'Configuration to apply when updating a Docker digest (same tag)',
     stage: 'package',
     type: 'json',
-    default: {},
+    default: {
+      branchTopic: '{{{depNameSanitized}}}-digest',
+      commitMessageExtra: 'to {{newDigestShort}}',
+      commitMessageTopic: '{{{depName}}} commit hash',
+      prBody: template('prBody', 'digest'),
+    },
     cli: false,
     mergeable: true,
   },
diff --git a/lib/config/templates/digest/pr-body.hbs b/lib/config/templates/digest/pr-body.hbs
new file mode 100644
index 0000000000000000000000000000000000000000..7c1e6ab51bf4587bffb9eb48cf9564daef9a8e1d
--- /dev/null
+++ b/lib/config/templates/digest/pr-body.hbs
@@ -0,0 +1,33 @@
+This Pull Request updates dependency `{{{depName}}}` to the latest sha (`{{{newDigest}}}`).
+
+If you wish to disable digest updates, add `":disableDigestUpdates" to the `extends` array in your config.
+
+{{#if schedule}}
+**Note**: This PR was created on a configured schedule ("{{{schedule}}}"{{#if timezone}} in timezone `{{{timezone}}}`{{/if}}) and will not receive updates outside those times.
+{{/if}}
+
+{{#if hasErrors}}
+
+---
+
+# Errors
+
+Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.
+
+{{#each errors as |error|}}
+-   `{{error.depName}}`: {{error.message}}
+{{/each}}
+{{/if}}
+
+{{#if hasWarnings}}
+
+---
+
+# Warnings
+
+Please make sure the following warnings are safe to ignore:
+
+{{#each warnings as |warning|}}
+-   `{{warning.depName}}`: {{warning.message}}
+{{/each}}
+{{/if}}
diff --git a/lib/datasource/github.js b/lib/datasource/github.js
index 3512506ff58a1efb6c4c76831e09128012db3e20..44f1ba40af0358a835c77e569d40964664dbc4f4 100644
--- a/lib/datasource/github.js
+++ b/lib/datasource/github.js
@@ -3,6 +3,7 @@ const versioning = require('../versioning');
 
 module.exports = {
   getPreset,
+  getDigest,
   getPkgReleases,
 };
 
@@ -36,6 +37,39 @@ function getCacheKey(repo, type) {
   return `${repo}:${type}`;
 }
 
+async function getDigest(config) {
+  const cachedResult = await renovateCache.get(
+    cacheNamespace,
+    getCacheKey(config.githubRepo, 'commit')
+  );
+  if (cachedResult) {
+    return cachedResult;
+  }
+  let digest;
+  try {
+    const url = `https://api.github.com/repos/${
+      config.githubRepo
+    }/commits?per_page=1`;
+    digest = (await ghGot(url)).body[0].sha;
+  } catch (err) {
+    logger.info(
+      { githubRepo: config.githubRepo, err },
+      'Error getting latest commit from GitHub repo'
+    );
+  }
+  if (!digest) {
+    return null;
+  }
+  const cacheMinutes = 10;
+  await renovateCache.set(
+    cacheNamespace,
+    getCacheKey(config.githubRepo, 'commit'),
+    digest,
+    cacheMinutes
+  );
+  return digest;
+}
+
 async function getPkgReleases(purl, config) {
   const { versionScheme } = config || {};
   const { fullname: repo, qualifiers: options } = purl;
diff --git a/lib/manager/npm/extract/index.js b/lib/manager/npm/extract/index.js
index 639fdabc31a3bd26ebce2cca10cea395b35e0c17..5cf44ee96b36e59a3fce52602b8b0d7306d2b358 100644
--- a/lib/manager/npm/extract/index.js
+++ b/lib/manager/npm/extract/index.js
@@ -176,9 +176,22 @@ async function extractDependencies(content, fileName, config) {
       dep.currentRawValue = dep.currentValue;
       dep.currentValue = depRefPart;
       dep.purl = `pkg:github/${githubOwnerRepo}?ref=tags`;
+      dep.pinDigests = false;
+    } else if (
+      depRefPart.match(/^[0-9a-f]{7}$/) ||
+      depRefPart.match(/^[0-9a-f]{40}$/)
+    ) {
+      dep.currentRawValue = dep.currentValue;
+      dep.currentValue = null;
+      dep.currentDigest = depRefPart;
+      dep.purl = `pkg:github/${githubOwnerRepo}`;
+    } else {
+      dep.skipReason = 'unversioned-reference';
       return dep;
     }
-    dep.skipReason = 'unversioned-reference';
+    dep.githubRepo = githubOwnerRepo;
+    dep.repositoryUrl = `https://github.com/${githubOwnerRepo}`;
+    dep.gitRef = true;
     return dep;
   }
 
diff --git a/lib/manager/npm/post-update/index.js b/lib/manager/npm/post-update/index.js
index 04dbf257cf28cf9e0f8c078a591cb0af63c9162e..cb451f0e99530b0a2ee9cf6ff4029e414b5c6f53 100644
--- a/lib/manager/npm/post-update/index.js
+++ b/lib/manager/npm/post-update/index.js
@@ -5,6 +5,7 @@ const npm = require('./npm');
 const lerna = require('./lerna');
 const yarn = require('./yarn');
 const pnpm = require('./pnpm');
+const hostRules = require('../../../util/host-rules');
 
 module.exports = {
   determineLockFileDirs,
@@ -256,6 +257,21 @@ async function writeUpdatedPackageFiles(config) {
     }
     delete massagedFile.engines;
     delete massagedFile.scripts;
+    try {
+      const { token } = hostRules.find({ platform: config.platform });
+      for (const upgrade of config.upgrades) {
+        if (upgrade.gitRef && upgrade.packageFile === packageFile.name) {
+          massagedFile[upgrade.depType][upgrade.depName] = massagedFile[
+            upgrade.depType
+          ][upgrade.depName].replace(
+            'git+https://github.com',
+            `git+https://${token}@github.com`
+          );
+        }
+      }
+    } catch (err) {
+      logger.warn({ err }, 'Error adding token to package files');
+    }
     await fs.outputFile(
       upath.join(config.localDir, packageFile.name),
       JSON.stringify(massagedFile)
@@ -295,6 +311,13 @@ async function getAdditionalFiles(config, packageFiles) {
       : { HOME: process.env.HOME, PATH: process.env.PATH };
   env.NODE_ENV = 'dev';
 
+  let token = '';
+  try {
+    ({ token } = hostRules.find({ platform: config.platform }));
+    token += '@';
+  } catch (err) {
+    logger.warn({ err }, 'Error getting token for packageFile');
+  }
   for (const lockFile of dirs.npmLockDirs) {
     const lockFileDir = path.dirname(lockFile);
     const fileName = path.basename(lockFile);
@@ -341,7 +364,7 @@ async function getAdditionalFiles(config, packageFiles) {
         logger.debug(`${lockFile} needs updating`);
         updatedLockFiles.push({
           name: lockFile,
-          contents: res.lockFile,
+          contents: res.lockFile.replace(new RegExp(`${token}`, 'g'), ''),
         });
       } else {
         logger.debug(`${lockFile} hasn't changed`);
diff --git a/lib/manager/npm/update.js b/lib/manager/npm/update.js
index 3b030fab48d70c1919636b1d3ccdedb7522cc011..e518fd67335009386a0b795fc716c760398c3ea0 100644
--- a/lib/manager/npm/update.js
+++ b/lib/manager/npm/update.js
@@ -10,11 +10,19 @@ function updateDependency(fileContent, upgrade) {
   const { depType, depName } = upgrade;
   let { newValue } = upgrade;
   if (upgrade.currentRawValue) {
-    logger.info('Replacing package.json git reference');
-    newValue = upgrade.currentRawValue.replace(
-      upgrade.currentValue,
-      upgrade.newValue
-    );
+    if (upgrade.currentDigest) {
+      logger.info('Updating package.json git digest');
+      newValue = upgrade.currentRawValue.replace(
+        upgrade.currentDigest,
+        upgrade.newDigest.substring(0, upgrade.currentDigest.length)
+      );
+    } else {
+      logger.info('Updating package.json git version tag');
+      newValue = upgrade.currentRawValue.replace(
+        upgrade.currentValue,
+        upgrade.newValue
+      );
+    }
   }
   logger.debug(`npm.updateDependency(): ${depType}.${depName} = ${newValue}`);
   try {
diff --git a/test/datasource/github.spec.js b/test/datasource/github.spec.js
index f942a52b1ec448cd3cc9e5858528769763ec088b..4c382e83de57b4bbffd34031af4f100386a3f1f4 100644
--- a/test/datasource/github.spec.js
+++ b/test/datasource/github.spec.js
@@ -7,6 +7,40 @@ jest.mock('got');
 
 describe('datasource/github', () => {
   beforeEach(() => global.renovateCache.rmAll());
+  describe('getDigest', () => {
+    beforeEach(() => {
+      jest.resetAllMocks();
+      return global.renovateCache.rmAll();
+    });
+    it('returns null if no token', async () => {
+      ghGot.mockReturnValueOnce({ body: [] });
+      const res = await github.getDigest(
+        { depName: 'some-dep', githubRepo: 'some/dep' },
+        null
+      );
+      expect(res).toBe(null);
+    });
+    it('returns digest', async () => {
+      ghGot.mockReturnValueOnce({ body: [{ sha: 'abcdef' }] });
+      const res = await github.getDigest(
+        { depName: 'some-dep', githubRepo: 'some/dep' },
+        null
+      );
+      expect(res).toBe('abcdef');
+    });
+    it('returns cached digest', async () => {
+      ghGot.mockReturnValueOnce({ body: [{ sha: '12345' }] });
+      await github.getDigest(
+        { depName: 'some-dep', githubRepo: 'some/dep' },
+        null
+      );
+      const res = await github.getDigest(
+        { depName: 'some-dep', githubRepo: 'some/dep' },
+        null
+      );
+      expect(res).toBe('12345');
+    });
+  });
   describe('getPreset()', () => {
     it('throws if non-default', async () => {
       await expect(
diff --git a/test/manager/npm/__snapshots__/update.spec.js.snap b/test/manager/npm/__snapshots__/update.spec.js.snap
index 62a8a6473e6a884eaab5dadd552cb561f955c62a..95785e2f7e0f978cdb267678ab1b674b9d08ffd3 100644
--- a/test/manager/npm/__snapshots__/update.spec.js.snap
+++ b/test/manager/npm/__snapshots__/update.spec.js.snap
@@ -7,3 +7,5 @@ exports[`workers/branch/package-json .bumpPackageVersion() updates 1`] = `"{\\"n
 exports[`workers/branch/package-json .updateDependency(fileContent, depType, depName, newValue) replaces a github dependency value 1`] = `"{\\"dependencies\\":{\\"gulp\\":\\"gulpjs/gulp#v4.0.0\\"}}"`;
 
 exports[`workers/branch/package-json .updateDependency(fileContent, depType, depName, newValue) replaces a github fully specified version 1`] = `"{\\"dependencies\\":{\\"n\\":\\"git+https://github.com/owner/n#v1.1.0\\"}}"`;
+
+exports[`workers/branch/package-json .updateDependency(fileContent, depType, depName, newValue) replaces a github short hash 1`] = `"{\\"dependencies\\":{\\"gulp\\":\\"gulpjs/gulp#0000000\\"}}"`;
diff --git a/test/manager/npm/extract/__snapshots__/index.spec.js.snap b/test/manager/npm/extract/__snapshots__/index.spec.js.snap
index f08a8bf20f861bb75ebcf4339d07b48351f9fffe..9e52a784e130f54ea9a78a055977010940d96725 100644
--- a/test/manager/npm/extract/__snapshots__/index.spec.js.snap
+++ b/test/manager/npm/extract/__snapshots__/index.spec.js.snap
@@ -133,8 +133,12 @@ Object {
       "currentValue": "v1.1.0",
       "depName": "c",
       "depType": "dependencies",
+      "gitRef": true,
+      "githubRepo": "owner/c",
+      "pinDigests": false,
       "prettyDepType": "dependency",
       "purl": "pkg:github/owner/c?ref=tags",
+      "repositoryUrl": "https://github.com/owner/c",
       "versionScheme": "semver",
     },
     Object {
@@ -146,11 +150,16 @@ Object {
       "versionScheme": "semver",
     },
     Object {
-      "currentValue": "github:owner/e#49b5aca613b33c5b626ae68c03a385f25c142f55",
+      "currentDigest": "49b5aca613b33c5b626ae68c03a385f25c142f55",
+      "currentRawValue": "github:owner/e#49b5aca613b33c5b626ae68c03a385f25c142f55",
+      "currentValue": null,
       "depName": "e",
       "depType": "dependencies",
+      "gitRef": true,
+      "githubRepo": "owner/e",
       "prettyDepType": "dependency",
-      "skipReason": "unversioned-reference",
+      "purl": "pkg:github/owner/e",
+      "repositoryUrl": "https://github.com/owner/e",
       "versionScheme": "semver",
     },
     Object {
@@ -158,8 +167,12 @@ Object {
       "currentValue": "v2.0.0",
       "depName": "f",
       "depType": "dependencies",
+      "gitRef": true,
+      "githubRepo": "owner/f",
+      "pinDigests": false,
       "prettyDepType": "dependency",
       "purl": "pkg:github/owner/f?ref=tags",
+      "repositoryUrl": "https://github.com/owner/f",
       "versionScheme": "semver",
     },
     Object {
@@ -195,19 +208,29 @@ Object {
       "versionScheme": "semver",
     },
     Object {
-      "currentValue": "github:owner/k#49b5aca",
+      "currentDigest": "49b5aca",
+      "currentRawValue": "github:owner/k#49b5aca",
+      "currentValue": null,
       "depName": "k",
       "depType": "dependencies",
+      "gitRef": true,
+      "githubRepo": "owner/k",
       "prettyDepType": "dependency",
-      "skipReason": "unversioned-reference",
+      "purl": "pkg:github/owner/k",
+      "repositoryUrl": "https://github.com/owner/k",
       "versionScheme": "semver",
     },
     Object {
-      "currentValue": "github:owner/l.git#abcdef0",
+      "currentDigest": "abcdef0",
+      "currentRawValue": "github:owner/l.git#abcdef0",
+      "currentValue": null,
       "depName": "l",
       "depType": "dependencies",
+      "gitRef": true,
+      "githubRepo": "owner/l",
       "prettyDepType": "dependency",
-      "skipReason": "unversioned-reference",
+      "purl": "pkg:github/owner/l",
+      "repositoryUrl": "https://github.com/owner/l",
       "versionScheme": "semver",
     },
     Object {
@@ -215,8 +238,12 @@ Object {
       "currentValue": "v1.0.0",
       "depName": "m",
       "depType": "dependencies",
+      "gitRef": true,
+      "githubRepo": "owner/m",
+      "pinDigests": false,
       "prettyDepType": "dependency",
       "purl": "pkg:github/owner/m?ref=tags",
+      "repositoryUrl": "https://github.com/owner/m",
       "versionScheme": "semver",
     },
     Object {
@@ -224,8 +251,12 @@ Object {
       "currentValue": "v2.0.0",
       "depName": "n",
       "depType": "dependencies",
+      "gitRef": true,
+      "githubRepo": "owner/n",
+      "pinDigests": false,
       "prettyDepType": "dependency",
       "purl": "pkg:github/owner/n?ref=tags",
+      "repositoryUrl": "https://github.com/owner/n",
       "versionScheme": "semver",
     },
   ],
diff --git a/test/manager/npm/update.spec.js b/test/manager/npm/update.spec.js
index 93fc10fe2832842d3dca8790c8ef655822cf4f43..b53582f58ce1b6bb05227f6c8c53dbc4b608925d 100644
--- a/test/manager/npm/update.spec.js
+++ b/test/manager/npm/update.spec.js
@@ -40,6 +40,22 @@ describe('workers/branch/package-json', () => {
       const res = npmUpdater.updateDependency(input, upgrade);
       expect(res).toMatchSnapshot();
     });
+    it('replaces a github short hash', () => {
+      const upgrade = {
+        depType: 'dependencies',
+        depName: 'gulp',
+        currentDigest: 'abcdef7',
+        currentRawValue: 'gulpjs/gulp#abcdef7',
+        newDigest: '0000000000111111111122222222223333333333',
+      };
+      const input = JSON.stringify({
+        dependencies: {
+          gulp: 'gulpjs/gulp#abcdef7',
+        },
+      });
+      const res = npmUpdater.updateDependency(input, upgrade);
+      expect(res).toMatchSnapshot();
+    });
     it('replaces a github fully specified version', () => {
       const upgrade = {
         depType: 'dependencies',
diff --git a/test/workers/branch/lock-files/index.spec.js b/test/workers/branch/lock-files/index.spec.js
index 6767c1fdaa0fe26b6f00aeaacb93092f2457b76b..c07a9c9ea84f6ef60557c2ea0a9cb200291fc007 100644
--- a/test/workers/branch/lock-files/index.spec.js
+++ b/test/workers/branch/lock-files/index.spec.js
@@ -8,6 +8,10 @@ const yarn = require('../../../../lib/manager/npm/post-update/yarn');
 const pnpm = require('../../../../lib/manager/npm/post-update/pnpm');
 const lerna = require('../../../../lib/manager/npm/post-update/lerna');
 
+const hostRules = require('../../../../lib/util/host-rules');
+
+hostRules.find = jest.fn(() => 'token-abc');
+
 const {
   // determineLockFileDirs,
   // writeExistingFiles,
@@ -275,6 +279,7 @@ describe('manager/npm/post-update', () => {
             '{ "name": "some-other-name", "engines": { "node": "^6.0.0" }}',
         },
       ];
+      config.upgrades = [];
       await writeUpdatedPackageFiles(config);
       expect(fs.outputFile.mock.calls).toHaveLength(2);
       expect(fs.outputFile.mock.calls[1][1].includes('"engines"')).toBe(false);
diff --git a/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap b/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap
index 865e28a287990f899f945beaa6fadcd441d1c419..50debd4670622ed828830fbb7bd421bae345b5d6 100644
--- a/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap
+++ b/test/workers/repository/updates/__snapshots__/flatten.spec.js.snap
@@ -40,6 +40,7 @@ Array [
     "npmToken": null,
     "npmrc": null,
     "packageFile": "package.json",
+    "platform": "github",
     "prBody": "This Pull Request {{#if isRollback}}rolls back{{else}}updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`{{#if isRollback}}. This is necessary and important because \`v{{{currentValue}}}\` cannot currently be found in the package's registry.{{/if}}\\n{{#if hasTypes}}\\n\\nThis PR also includes an upgrade to the corresponding [@types/{{{depName}}}](https://npmjs.com/package/@types/{{{depName}}}) package.\\n{{/if}}\\n{{#if releases.length}}\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n{{#if hasReleaseNotes}}\\n\\n<details>\\n<summary>Release Notes</summary>\\n\\n{{#each releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [{{#if release.releaseNotes.name}}{{{release.releaseNotes.name}}}{{else}}\`v{{{release.version}}}\`{{/if}}]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n</details>\\n{{/if}}\\n\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
@@ -112,6 +113,7 @@ Array [
     "npmToken": null,
     "npmrc": null,
     "packageFile": "package.json",
+    "platform": "github",
     "prBody": "This Pull Request {{#if isRollback}}rolls back{{else}}updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`{{#if isRollback}}. This is necessary and important because \`v{{{currentValue}}}\` cannot currently be found in the package's registry.{{/if}}\\n{{#if hasTypes}}\\n\\nThis PR also includes an upgrade to the corresponding [@types/{{{depName}}}](https://npmjs.com/package/@types/{{{depName}}}) package.\\n{{/if}}\\n{{#if releases.length}}\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n{{#if hasReleaseNotes}}\\n\\n<details>\\n<summary>Release Notes</summary>\\n\\n{{#each releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [{{#if release.releaseNotes.name}}{{{release.releaseNotes.name}}}{{else}}\`v{{{release.version}}}\`{{/if}}]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n</details>\\n{{/if}}\\n\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
@@ -181,6 +183,7 @@ Array [
     "npmToken": null,
     "npmrc": null,
     "packageFile": "package.json",
+    "platform": "github",
     "prBody": "This Pull Request updates \`package.json\` lock files to use the latest dependency versions.\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
@@ -256,6 +259,7 @@ Array [
     "npmToken": null,
     "npmrc": null,
     "packageFile": "backend/package.json",
+    "platform": "github",
     "prBody": "This Pull Request {{#if isRollback}}rolls back{{else}}updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`{{#if isRollback}}. This is necessary and important because \`v{{{currentValue}}}\` cannot currently be found in the package's registry.{{/if}}\\n{{#if hasTypes}}\\n\\nThis PR also includes an upgrade to the corresponding [@types/{{{depName}}}](https://npmjs.com/package/@types/{{{depName}}}) package.\\n{{/if}}\\n{{#if releases.length}}\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n{{#if hasReleaseNotes}}\\n\\n<details>\\n<summary>Release Notes</summary>\\n\\n{{#each releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [{{#if release.releaseNotes.name}}{{{release.releaseNotes.name}}}{{else}}\`v{{{release.version}}}\`{{/if}}]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n</details>\\n{{/if}}\\n\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
@@ -325,6 +329,7 @@ Array [
     "npmToken": null,
     "npmrc": null,
     "packageFile": "backend/package.json",
+    "platform": "github",
     "prBody": "This Pull Request updates \`package.json\` lock files to use the latest dependency versions.\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
@@ -400,6 +405,7 @@ Array [
     "npmToken": null,
     "npmrc": null,
     "packageFile": "frontend/package.json",
+    "platform": "github",
     "prBody": "This Pull Request {{#if isRollback}}rolls back{{else}}updates{{/if}} {{#if prettyDepType}}{{{prettyDepType}}}{{else}}dependency{{/if}} \`{{{depName}}}\` {{#if hasUrls}}({{#if homepage}}[homepage]({{{homepage}}}){{#if repositoryUrl}}, [source]({{{repositoryUrl}}}){{/if}}{{else}}[source]({{{repositoryUrl}}}){{/if}}{{#if changelogUrl}}, [changelog]({{{changelogUrl}}}){{/if}}){{/if}} from \`{{#unless isRange}}{{#unless isPin}}v{{/unless}}{{/unless}}{{{currentValue}}}\` to \`{{#unless isRange}}v{{/unless}}{{{newValue}}}\`{{#if isRollback}}. This is necessary and important because \`v{{{currentValue}}}\` cannot currently be found in the package's registry.{{/if}}\\n{{#if hasTypes}}\\n\\nThis PR also includes an upgrade to the corresponding [@types/{{{depName}}}](https://npmjs.com/package/@types/{{{depName}}}) package.\\n{{/if}}\\n{{#if releases.length}}\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if isPin}}\\n**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open.\\n{{/if}}\\n{{#if hasReleaseNotes}}\\n\\n<details>\\n<summary>Release Notes</summary>\\n\\n{{#each releases as |release|}}\\n{{#if release.releaseNotes}}\\n### [{{#if release.releaseNotes.name}}{{{release.releaseNotes.name}}}{{else}}\`v{{{release.version}}}\`{{/if}}]({{{release.releaseNotes.url}}})\\n{{#if release.compare.url}}\\n[Compare Source]({{release.compare.url}})\\n\\n{{/if}}\\n{{{release.releaseNotes.body}}}\\n\\n---\\n\\n{{/if}}\\n{{/each}}\\n</details>\\n{{/if}}\\n\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
@@ -472,6 +478,7 @@ Array [
     "npmToken": null,
     "npmrc": null,
     "packageFile": "Dockerfile",
+    "platform": "github",
     "prBody": "This Pull Request updates Docker base image \`{{{depName}}}\` from tag \`{{{currentTag}}}\` to new tag \`{{{newValue}}}{{#if tagSuffix}}-{{{tagSuffix}}}{{/if}}\`. For details on Renovate's Docker support, please visit https://renovatebot.com/docs/docker\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",
@@ -544,6 +551,7 @@ Array [
     "npmToken": null,
     "npmrc": null,
     "packageFile": "Dockerfile",
+    "platform": "github",
     "prBody": "This Pull Request updates Docker base image \`{{{depName}}}\` from tag \`{{{currentTag}}}\` to new tag \`{{{newValue}}}{{#if tagSuffix}}-{{{tagSuffix}}}{{/if}}\`. For details on Renovate's Docker support, please visit https://renovatebot.com/docs/docker\\n\\n{{#if schedule}}\\n**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times.\\n{{/if}}\\n\\n{{#if hasErrors}}\\n\\n---\\n\\n# Errors\\n\\nRenovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR.\\n\\n{{#each errors as |error|}}\\n-   \`{{error.depName}}\`: {{error.message}}\\n{{/each}}\\n{{/if}}\\n\\n{{#if hasWarnings}}\\n\\n---\\n\\n# Warnings\\n\\nPlease make sure the following warnings are safe to ignore:\\n\\n{{#each warnings as |warning|}}\\n-   \`{{warning.depName}}\`: {{warning.message}}\\n{{/each}}\\n{{/if}}",
     "prConcurrentLimit": 0,
     "prCreation": "immediate",