diff --git a/docs/usage/self-hosted-configuration.md b/docs/usage/self-hosted-configuration.md
index 1294dfb24e589c668277a1e5483ece9503dfbc62..417301ffd9cdf4ea7f8f1d01c94a7d483633f33c 100644
--- a/docs/usage/self-hosted-configuration.md
+++ b/docs/usage/self-hosted-configuration.md
@@ -292,6 +292,17 @@ Like this:
 
 ## dryRun
 
+Use `dryRun` to preview the behavior of Renovate in logs, without making any changes to the repository files.
+
+You can choose from the following behaviors for the `dryRun` config option:
+
+- `null`: Default behavior - Performs a regular Renovate run including creating/updating/deleting branches and PRs
+- `"extract"`: Performs a very quick package file scan to identify the extracted dependencies
+- `"lookup"`: Performs a package file scan to identify the extracted dependencies and updates available
+- `"full"`: Performs a dry run by logging messages instead of creating/updating/deleting branches and PRs
+
+Information provided mainly in debug log level.
+
 ## endpoint
 
 ## executionTimeout
diff --git a/lib/config/migration.spec.ts b/lib/config/migration.spec.ts
index b2725bf220465b875ae9731da3ed333f148560b9..3d1e89696ae1122932a478f982338b52872ee9e1 100644
--- a/lib/config/migration.spec.ts
+++ b/lib/config/migration.spec.ts
@@ -711,4 +711,17 @@ describe('config/migration', () => {
       migratedConfig: { automerge: true, platformAutomerge: true },
     });
   });
+
+  it('it migrates dryRun', () => {
+    let config: TestRenovateConfig;
+    let res: MigratedConfig;
+
+    config = { dryRun: true };
+    res = configMigration.migrateConfig(config);
+    expect(res.isMigrated).toBeTrue();
+
+    config = { dryRun: false };
+    res = configMigration.migrateConfig(config);
+    expect(res.isMigrated).toBeTrue();
+  });
 });
diff --git a/lib/config/migrations/custom/dry-run-migration.spec.ts b/lib/config/migrations/custom/dry-run-migration.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f8256f5b1cc2cf54457254c73027f55c870d6bf8
--- /dev/null
+++ b/lib/config/migrations/custom/dry-run-migration.spec.ts
@@ -0,0 +1,25 @@
+import { DryRunMigration } from './dry-run-migration';
+
+describe('config/migrations/custom/dry-run-migration', () => {
+  it('should migrate dryRun=true to dryRun=full', () => {
+    expect(DryRunMigration).toMigrate(
+      {
+        dryRun: true,
+      },
+      {
+        dryRun: 'full',
+      }
+    );
+  });
+
+  it('should migrate dryRun=false to dryRun=null', () => {
+    expect(DryRunMigration).toMigrate(
+      {
+        dryRun: false,
+      },
+      {
+        dryRun: null,
+      }
+    );
+  });
+});
diff --git a/lib/config/migrations/custom/dry-run-migration.ts b/lib/config/migrations/custom/dry-run-migration.ts
new file mode 100644
index 0000000000000000000000000000000000000000..8ed754831ab1e77acfea23f770419a57d77269c6
--- /dev/null
+++ b/lib/config/migrations/custom/dry-run-migration.ts
@@ -0,0 +1,14 @@
+import { AbstractMigration } from '../base/abstract-migration';
+
+export class DryRunMigration extends AbstractMigration {
+  override readonly propertyName = 'dryRun';
+
+  override run(value: unknown): void {
+    if (value === true) {
+      this.rewrite('full');
+    }
+    if (value === false) {
+      this.rewrite(null);
+    }
+  }
+}
diff --git a/lib/config/migrations/migrations-service.ts b/lib/config/migrations/migrations-service.ts
index dc4b2140364e5ddd2c62b1a4641d5096b73f440c..2aafbeb709f8b267c09c3b5b4e2bc5a168527869 100644
--- a/lib/config/migrations/migrations-service.ts
+++ b/lib/config/migrations/migrations-service.ts
@@ -15,6 +15,7 @@ import { BranchNameMigration } from './custom/branch-name-migration';
 import { BranchPrefixMigration } from './custom/branch-prefix-migration';
 import { CompatibilityMigration } from './custom/compatibility-migration';
 import { ComposerIgnorePlatformReqsMigration } from './custom/composer-ignore-platform-reqs-migration';
+import { DryRunMigration } from './custom/dry-run-migration';
 import { EnabledManagersMigration } from './custom/enabled-managers-migration';
 import { ExtendsMigration } from './custom/extends-migration';
 import { GoModTidyMigration } from './custom/go-mod-tidy-migration';
@@ -110,6 +111,7 @@ export class MigrationsService {
     UnpublishSafeMigration,
     UpgradeInRangeMigration,
     VersionStrategyMigration,
+    DryRunMigration,
   ];
 
   static run(originalConfig: RenovateConfig): RenovateConfig {
diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts
index 6daa3d5af4a99f8f4048ed38315578512721f31e..09ae0656db5c7144bb4058983db6bd6934d4d747 100644
--- a/lib/config/options/index.ts
+++ b/lib/config/options/index.ts
@@ -246,9 +246,10 @@ const options: RenovateOptions[] = [
     name: 'dryRun',
     description:
       'If enabled, perform a dry run by logging messages instead of creating/updating/deleting branches and PRs.',
-    type: 'boolean',
+    type: 'string',
     globalOnly: true,
-    default: false,
+    allowedValues: ['extract', 'lookup', 'full'],
+    default: null,
   },
   {
     name: 'printConfig',
diff --git a/lib/config/types.ts b/lib/config/types.ts
index 8c5a068ac3a6539c9ff31e5444bdef37042474a6..31b399b7931852ec93275d9095d234a3c444a597 100644
--- a/lib/config/types.ts
+++ b/lib/config/types.ts
@@ -11,6 +11,7 @@ export type RenovateConfigStage =
   | 'pr';
 
 export type RepositoryCacheConfig = 'disabled' | 'enabled' | 'reset';
+export type DryRunConfig = 'extract' | 'lookup' | 'full';
 
 export interface GroupConfig extends Record<string, unknown> {
   branchName?: string;
@@ -104,7 +105,7 @@ export interface RepoGlobalConfig {
   dockerChildPrefix?: string;
   dockerImagePrefix?: string;
   dockerUser?: string;
-  dryRun?: boolean;
+  dryRun?: DryRunConfig;
   executionTimeout?: number;
   exposeAllEnv?: boolean;
   migratePresets?: Record<string, string>;
diff --git a/lib/workers/global/config/parse/cli.spec.ts b/lib/workers/global/config/parse/cli.spec.ts
index 2093a706282fe61ffe00368b4db5ba005da66cd0..194f18451ae3f91fec0f41e4e4ec0587f3863ae4 100644
--- a/lib/workers/global/config/parse/cli.spec.ts
+++ b/lib/workers/global/config/parse/cli.spec.ts
@@ -142,5 +142,21 @@ describe('workers/global/config/parse/cli', () => {
         Error("Invalid JSON value: 'Hello_World'")
       );
     });
+    it('dryRun boolean true', () => {
+      argv.push('--dry-run=true');
+      expect(cli.getConfig(argv)).toEqual({ dryRun: 'full' });
+    });
+    it('dryRun no value', () => {
+      argv.push('--dry-run');
+      expect(cli.getConfig(argv)).toEqual({ dryRun: 'full' });
+    });
+    it('dryRun boolean false', () => {
+      argv.push('--dry-run=false');
+      expect(cli.getConfig(argv)).toEqual({ dryRun: null });
+    });
+    it('dryRun  null', () => {
+      argv.push('--dry-run=null');
+      expect(cli.getConfig(argv)).toEqual({ dryRun: null });
+    });
   });
 });
diff --git a/lib/workers/global/config/parse/cli.ts b/lib/workers/global/config/parse/cli.ts
index 6152d961817583416a9abef23ee4917ef584aed4..b9211bfbbaa06b9be146764160ff3df3cd6eb56d 100644
--- a/lib/workers/global/config/parse/cli.ts
+++ b/lib/workers/global/config/parse/cli.ts
@@ -2,6 +2,7 @@ import { Command } from 'commander';
 import { getOptions } from '../../../../config/options';
 import type { AllConfig } from '../../../../config/types';
 import { pkg } from '../../../../expose.cjs';
+import { logger } from '../../../../logger';
 import { regEx } from '../../../../util/regex';
 import type { ParseConfigOptions } from './types';
 
@@ -16,18 +17,18 @@ export function getCliName(option: ParseConfigOptions): string {
 export function getConfig(input: string[]): AllConfig {
   // massage migrated configuration keys
   const argv = input
-    .map(
-      (a) =>
-        a
-          .replace('--endpoints=', '--host-rules=')
-          .replace('--expose-env=true', '--trust-level=high')
-          .replace('--expose-env', '--trust-level=high')
-          .replace('--renovate-fork', '--include-forks')
-          .replace('"platform":"', '"hostType":"')
-          .replace('"endpoint":"', '"matchHost":"')
-          .replace('"host":"', '"matchHost":"')
-          .replace('--azure-auto-complete', '--platform-automerge') // migrate: azureAutoComplete
-          .replace('--git-lab-automerge', '--platform-automerge') // migrate: gitLabAutomerge
+    .map((a) =>
+      a
+        .replace('--endpoints=', '--host-rules=')
+        .replace('--expose-env=true', '--trust-level=high')
+        .replace('--expose-env', '--trust-level=high')
+        .replace('--renovate-fork', '--include-forks')
+        .replace('"platform":"', '"hostType":"')
+        .replace('"endpoint":"', '"matchHost":"')
+        .replace('"host":"', '"matchHost":"')
+        .replace('--azure-auto-complete', '--platform-automerge') // migrate: azureAutoComplete
+        .replace('--git-lab-automerge', '--platform-automerge') // migrate: gitLabAutomerge
+        .replace(/^--dry-run$/, '--dry-run=true')
     )
     .filter((a) => !a.startsWith('--git-fs'));
   const options = getOptions();
@@ -114,6 +115,21 @@ export function getConfig(input: string[]): AllConfig {
         if (option.cli !== false) {
           if (opts[option.name] !== undefined) {
             config[option.name] = opts[option.name];
+            if (option.name === 'dryRun') {
+              if (config[option.name] === 'true') {
+                logger.warn(
+                  'cli config dryRun property has been changed to full'
+                );
+                config[option.name] = 'full';
+              } else if (config[option.name] === 'false') {
+                logger.warn(
+                  'cli config dryRun property has been changed to null'
+                );
+                config[option.name] = null;
+              } else if (config[option.name] === 'null') {
+                config[option.name] = null;
+              }
+            }
           }
         }
       }
diff --git a/lib/workers/global/config/parse/env.spec.ts b/lib/workers/global/config/parse/env.spec.ts
index b30a09b4e80537e693c3c19b7f0f27a89019b0ee..a9f88009bb542267ed27540b8b769603a376e980 100644
--- a/lib/workers/global/config/parse/env.spec.ts
+++ b/lib/workers/global/config/parse/env.spec.ts
@@ -247,5 +247,26 @@ describe('workers/global/config/parse/env', () => {
       };
       expect(env.getEnvName(option)).toBe('RENOVATE_ONE_TWO_THREE');
     });
+    it('dryRun boolean true', () => {
+      const envParam: NodeJS.ProcessEnv = {
+        RENOVATE_DRY_RUN: 'true',
+      };
+      const config = env.getConfig(envParam);
+      expect(config.dryRun).toBe('full');
+    });
+    it('dryRun boolean false', () => {
+      const envParam: NodeJS.ProcessEnv = {
+        RENOVATE_DRY_RUN: 'false',
+      };
+      const config = env.getConfig(envParam);
+      expect(config.dryRun).toBeNull();
+    });
+    it('dryRun null', () => {
+      const envParam: NodeJS.ProcessEnv = {
+        RENOVATE_DRY_RUN: 'null',
+      };
+      const config = env.getConfig(envParam);
+      expect(config.dryRun).toBeNull();
+    });
   });
 });
diff --git a/lib/workers/global/config/parse/env.ts b/lib/workers/global/config/parse/env.ts
index 212ea2f4df7a336a9b97357f3b8475e00131ac3f..4882630cdc8b6a9de2d099540ec62f68ac348f0d 100644
--- a/lib/workers/global/config/parse/env.ts
+++ b/lib/workers/global/config/parse/env.ts
@@ -105,6 +105,21 @@ export function getConfig(inputEnv: NodeJS.ProcessEnv): AllConfig {
         } else {
           const coerce = coersions[option.type];
           config[option.name] = coerce(envVal);
+          if (option.name === 'dryRun') {
+            if (config[option.name] === 'true') {
+              logger.warn(
+                'env config dryRun property has been changed to full'
+              );
+              config[option.name] = 'full';
+            } else if (config[option.name] === 'false') {
+              logger.warn(
+                'env config dryRun property has been changed to null'
+              );
+              config[option.name] = null;
+            } else if (config[option.name] === 'null') {
+              config[option.name] = null;
+            }
+          }
         }
       }
     }
diff --git a/lib/workers/global/config/parse/index.spec.ts b/lib/workers/global/config/parse/index.spec.ts
index 6142ce8f4032109353eb73b540b6adb500183f1b..8cd4fdabe23d89b6a8b0e7d345e5226a74f95069 100644
--- a/lib/workers/global/config/parse/index.spec.ts
+++ b/lib/workers/global/config/parse/index.spec.ts
@@ -135,5 +135,41 @@ describe('workers/global/config/parse/index', () => {
       const parsed = await configParser.parseConfigs(defaultEnv, defaultArgv);
       expect(parsed.hostRules).toContainEqual({ matchHost: 'example.org' });
     });
+
+    it('env dryRun = true replaced to full', async () => {
+      const env: NodeJS.ProcessEnv = {
+        ...defaultEnv,
+        RENOVATE_DRY_RUN: 'true',
+      };
+      const parsedConfig = await configParser.parseConfigs(env, defaultArgv);
+      expect(parsedConfig).toContainEntries([['dryRun', 'full']]);
+    });
+
+    it('cli dryRun = true replaced to full', async () => {
+      defaultArgv = defaultArgv.concat(['--dry-run=true']);
+      const parsed = await configParser.parseConfigs(defaultEnv, defaultArgv);
+      expect(parsed).toContainEntries([['dryRun', 'full']]);
+    });
+
+    it('cli dryRun replaced to full', async () => {
+      defaultArgv = defaultArgv.concat(['--dry-run']);
+      const parsed = await configParser.parseConfigs(defaultEnv, defaultArgv);
+      expect(parsed).toContainEntries([['dryRun', 'full']]);
+    });
+
+    it('env dryRun = false replaced to null', async () => {
+      const env: NodeJS.ProcessEnv = {
+        ...defaultEnv,
+        RENOVATE_DRY_RUN: 'false',
+      };
+      const parsedConfig = await configParser.parseConfigs(env, defaultArgv);
+      expect(parsedConfig).toContainEntries([['dryRun', null]]);
+    });
+
+    it('cli dryRun = false replaced to null', async () => {
+      defaultArgv = defaultArgv.concat(['--dry-run=false']);
+      const parsed = await configParser.parseConfigs(defaultEnv, defaultArgv);
+      expect(parsed).toContainEntries([['dryRun', null]]);
+    });
   });
 });
diff --git a/lib/workers/repository/dependency-dashboard.spec.ts b/lib/workers/repository/dependency-dashboard.spec.ts
index b2d2883d229d3a399312b8fabdb8d99db0c8a90a..c2875f54e6fb540c4c9a8b3587f5adbd35779bb5 100644
--- a/lib/workers/repository/dependency-dashboard.spec.ts
+++ b/lib/workers/repository/dependency-dashboard.spec.ts
@@ -32,7 +32,7 @@ async function dryRun(
   ensureIssueCalls = 0
 ) {
   jest.clearAllMocks();
-  GlobalConfig.set({ dryRun: true });
+  GlobalConfig.set({ dryRun: 'full' });
   await dependencyDashboard.ensureDependencyDashboard(config, branches);
   expect(platform.ensureIssueClosing).toHaveBeenCalledTimes(
     ensureIssueClosingCalls
diff --git a/lib/workers/repository/error-config.spec.ts b/lib/workers/repository/error-config.spec.ts
index 2ee8c520445c4348b4ac76168470ea32553b7915..d662a41fc0a1c62b225c419492934299177c7b4a 100644
--- a/lib/workers/repository/error-config.spec.ts
+++ b/lib/workers/repository/error-config.spec.ts
@@ -32,7 +32,7 @@ describe('workers/repository/error-config', () => {
       error.validationSource = 'package.json';
       error.validationMessage = 'some-message';
       platform.ensureIssue.mockResolvedValueOnce('created');
-      GlobalConfig.set({ dryRun: true });
+      GlobalConfig.set({ dryRun: 'full' });
       const res = await raiseConfigWarningIssue(config, error);
       expect(res).toBeUndefined();
     });
@@ -57,7 +57,7 @@ describe('workers/repository/error-config', () => {
         number: 1,
         state: PrState.Open,
       });
-      GlobalConfig.set({ dryRun: true });
+      GlobalConfig.set({ dryRun: 'full' });
       const res = await raiseConfigWarningIssue(config, error);
       expect(res).toBeUndefined();
     });
diff --git a/lib/workers/repository/finalise/prune.spec.ts b/lib/workers/repository/finalise/prune.spec.ts
index 1374351bbc2bc1160ce9d67b5805d996ec13f7c2..7c73abdc2b41b8010c13d0b6b10866a86112ebc3 100644
--- a/lib/workers/repository/finalise/prune.spec.ts
+++ b/lib/workers/repository/finalise/prune.spec.ts
@@ -69,7 +69,7 @@ describe('workers/repository/finalise/prune', () => {
     });
     it('does nothing on dryRun', async () => {
       config.branchList = ['renovate/a', 'renovate/b'];
-      GlobalConfig.set({ dryRun: true });
+      GlobalConfig.set({ dryRun: 'full' });
       git.getBranchList.mockReturnValueOnce(
         config.branchList.concat(['renovate/c'])
       );
@@ -107,7 +107,7 @@ describe('workers/repository/finalise/prune', () => {
     });
     it('skips comment if dry run', async () => {
       config.branchList = ['renovate/a', 'renovate/b'];
-      GlobalConfig.set({ dryRun: true });
+      GlobalConfig.set({ dryRun: 'full' });
       git.getBranchList.mockReturnValueOnce(
         config.branchList.concat(['renovate/c'])
       );
@@ -122,7 +122,7 @@ describe('workers/repository/finalise/prune', () => {
     });
     it('dry run delete branch no PR', async () => {
       config.branchList = ['renovate/a', 'renovate/b'];
-      GlobalConfig.set({ dryRun: true });
+      GlobalConfig.set({ dryRun: 'full' });
       git.getBranchList.mockReturnValueOnce(
         config.branchList.concat(['renovate/c'])
       );
diff --git a/lib/workers/repository/index.ts b/lib/workers/repository/index.ts
index 2d40b8d46acd909e11118e2d621cfa0976c6b1ea..2e5c9095df5ea8aa0d2ae508050ef49f29301e98 100644
--- a/lib/workers/repository/index.ts
+++ b/lib/workers/repository/index.ts
@@ -42,23 +42,28 @@ export async function renovateRepository(
     const { branches, branchList, packageFiles } = await extractDependencies(
       config
     );
-    await ensureOnboardingPr(config, packageFiles, branches);
-    const res = await updateRepo(config, branches);
-    setMeta({ repository: config.repository });
-    addSplit('update');
-    await setBranchCache(branches);
-    if (res === 'automerged') {
-      if (canRetry) {
-        logger.info('Renovating repository again after automerge result');
-        const recursiveRes = await renovateRepository(repoConfig, false);
-        return recursiveRes;
+    if (
+      GlobalConfig.get('dryRun') !== 'lookup' &&
+      GlobalConfig.get('dryRun') !== 'extract'
+    ) {
+      await ensureOnboardingPr(config, packageFiles, branches);
+      const res = await updateRepo(config, branches);
+      setMeta({ repository: config.repository });
+      addSplit('update');
+      await setBranchCache(branches);
+      if (res === 'automerged') {
+        if (canRetry) {
+          logger.info('Renovating repository again after automerge result');
+          const recursiveRes = await renovateRepository(repoConfig, false);
+          return recursiveRes;
+        }
+        logger.debug(`Automerged but already retried once`);
+      } else {
+        await ensureDependencyDashboard(config, branches);
       }
-      logger.debug(`Automerged but already retried once`);
-    } else {
-      await ensureDependencyDashboard(config, branches);
+      await finaliseRepo(config, branchList);
+      repoResult = processResult(config, res);
     }
-    await finaliseRepo(config, branchList);
-    repoResult = processResult(config, res);
   } catch (err) /* istanbul ignore next */ {
     setMeta({ repository: config.repository });
     const errorRes = await handleError(config, err);
diff --git a/lib/workers/repository/onboarding/pr/index.spec.ts b/lib/workers/repository/onboarding/pr/index.spec.ts
index bb5c61bd4ac8afdbe07ae5aff5e50a1fa3df5e33..ba164bea0eabbb6141ffa4a2da99374d86ec7376 100644
--- a/lib/workers/repository/onboarding/pr/index.spec.ts
+++ b/lib/workers/repository/onboarding/pr/index.spec.ts
@@ -159,7 +159,7 @@ describe('workers/repository/onboarding/pr/index', () => {
       expect(platform.createPr).toHaveBeenCalledTimes(1);
     });
     it('dryrun of updates PR when modified', async () => {
-      GlobalConfig.set({ dryRun: true });
+      GlobalConfig.set({ dryRun: 'full' });
       config.baseBranch = 'some-branch';
       platform.getBranchPr.mockResolvedValueOnce(
         partial<Pr>({
@@ -178,7 +178,7 @@ describe('workers/repository/onboarding/pr/index', () => {
       );
     });
     it('dryrun of creates PR', async () => {
-      GlobalConfig.set({ dryRun: true });
+      GlobalConfig.set({ dryRun: 'full' });
       await ensureOnboardingPr(config, packageFiles, branches);
       expect(logger.info).toHaveBeenCalledWith(
         'DRY-RUN: Would check branch renovate/configure'
diff --git a/lib/workers/repository/process/index.spec.ts b/lib/workers/repository/process/index.spec.ts
index e23b46b05d2db1f421d1e97c1f82e55b254f0509..e9334fa48b21d359af3184b7b14d34e6087a177c 100644
--- a/lib/workers/repository/process/index.spec.ts
+++ b/lib/workers/repository/process/index.spec.ts
@@ -5,9 +5,11 @@ import {
   mocked,
   platform,
 } from '../../../../test/util';
+import { GlobalConfig } from '../../../config/global';
 import { CONFIG_VALIDATION } from '../../../constants/error-messages';
 import { getCache } from '../../../util/cache/repository';
 import * as _extractUpdate from './extract-update';
+import { lookup } from './extract-update';
 import { extractDependencies, updateRepo } from '.';
 
 jest.mock('../../../util/git');
@@ -98,5 +100,17 @@ describe('workers/repository/process/index', () => {
         CONFIG_VALIDATION
       );
     });
+    it('processes baseBranches dryRun extract', async () => {
+      extract.mockResolvedValue({} as never);
+      GlobalConfig.set({ dryRun: 'extract' });
+      const res = await extractDependencies(config);
+      await updateRepo(config, res.branches);
+      expect(res).toEqual({
+        branchList: [],
+        branches: [],
+        packageFiles: {},
+      });
+      expect(lookup).toHaveBeenCalledTimes(0);
+    });
   });
 });
diff --git a/lib/workers/repository/process/index.ts b/lib/workers/repository/process/index.ts
index 7b139ca13dec0838629b0479acaf92a84ecdc4e3..1c93822bad364aca003ade5d2a02980313ece1ae 100644
--- a/lib/workers/repository/process/index.ts
+++ b/lib/workers/repository/process/index.ts
@@ -1,4 +1,5 @@
 import { mergeChildConfig } from '../../../config';
+import { GlobalConfig } from '../../../config/global';
 import type { RenovateConfig } from '../../../config/types';
 import { CONFIG_VALIDATION } from '../../../constants/error-messages';
 import { logger } from '../../../logger';
@@ -103,6 +104,11 @@ export async function extractDependencies(
     logger.debug('No baseBranches');
     const packageFiles = await extract(config);
     addSplit('extract');
+    if (GlobalConfig.get('dryRun') === 'extract') {
+      res.packageFiles = packageFiles;
+      logger.info({ packageFiles }, 'Extracted dependencies');
+      return res;
+    }
     res = await lookup(config, packageFiles);
   }
   addSplit('lookup');
diff --git a/lib/workers/repository/process/write.spec.ts b/lib/workers/repository/process/write.spec.ts
index dbf1a90e9bd0ad6da8b439247aa90c96aa043632..f6056976f6d257ecee63144288454551bab596aa 100644
--- a/lib/workers/repository/process/write.spec.ts
+++ b/lib/workers/repository/process/write.spec.ts
@@ -1,4 +1,5 @@
 import { RenovateConfig, getConfig, git, mocked } from '../../../../test/util';
+import { GlobalConfig } from '../../../config/global';
 import { Limit, isLimitReached } from '../../global/limits';
 import { BranchConfig, BranchResult } from '../../types';
 import * as _branchWorker from '../update/branch';
@@ -48,6 +49,7 @@ describe('workers/repository/process/write', () => {
         branchExists: false,
         result: BranchResult.Automerged,
       });
+      GlobalConfig.set({ dryRun: 'full' });
       const res = await writeUpdates(config, branches);
       expect(res).toBe('automerged');
       expect(branchWorker.processBranch).toHaveBeenCalledTimes(4);
@@ -62,6 +64,7 @@ describe('workers/repository/process/write', () => {
       git.branchExists.mockReturnValueOnce(true);
       limits.getBranchesRemaining.mockResolvedValueOnce(1);
       expect(isLimitReached(Limit.Branches)).toBeFalse();
+      GlobalConfig.set({ dryRun: 'full' });
       await writeUpdates({ config }, branches);
       expect(isLimitReached(Limit.Branches)).toBeTrue();
     });
diff --git a/lib/workers/repository/update/branch/artifacts.spec.ts b/lib/workers/repository/update/branch/artifacts.spec.ts
index d46e36a34e195563154e137df1ef3d4ab1319cf5..fa02e8210debd8401335eea92e63b43d821d0b4b 100644
--- a/lib/workers/repository/update/branch/artifacts.spec.ts
+++ b/lib/workers/repository/update/branch/artifacts.spec.ts
@@ -31,7 +31,7 @@ describe('workers/repository/update/branch/artifacts', () => {
     });
 
     it('skips status (dry-run)', async () => {
-      GlobalConfig.set({ dryRun: true });
+      GlobalConfig.set({ dryRun: 'full' });
       platform.getBranchStatusCheck.mockResolvedValueOnce(null);
       await setArtifactErrorStatus(config);
       expect(platform.setBranchStatus).not.toHaveBeenCalled();
diff --git a/lib/workers/repository/update/branch/automerge.spec.ts b/lib/workers/repository/update/branch/automerge.spec.ts
index e2c14094ed541e4d16467f13b7b3150af4177cc1..12960dd87caf77efbedb771faad8507b66f8977d 100644
--- a/lib/workers/repository/update/branch/automerge.spec.ts
+++ b/lib/workers/repository/update/branch/automerge.spec.ts
@@ -63,7 +63,7 @@ describe('workers/repository/update/branch/automerge', () => {
     it('returns true if automerge succeeds (dry-run)', async () => {
       config.automerge = true;
       config.automergeType = 'branch';
-      GlobalConfig.set({ dryRun: true });
+      GlobalConfig.set({ dryRun: 'full' });
       platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
       expect(await tryBranchAutomerge(config)).toBe('automerged');
     });
diff --git a/lib/workers/repository/update/branch/commit.spec.ts b/lib/workers/repository/update/branch/commit.spec.ts
index 581bcef5531bb2b7334cfc127dc0dc1fd996372a..84d86767b80d0291981bc9706a7e63977c5b34ed 100644
--- a/lib/workers/repository/update/branch/commit.spec.ts
+++ b/lib/workers/repository/update/branch/commit.spec.ts
@@ -55,7 +55,7 @@ describe('workers/repository/update/branch/commit', () => {
       expect(platform.commitFiles.mock.calls).toMatchSnapshot();
     });
     it('dry runs', async () => {
-      GlobalConfig.set({ dryRun: true });
+      GlobalConfig.set({ dryRun: 'full' });
       config.updatedPackageFiles.push({
         type: 'addition',
         path: 'package.json',
diff --git a/lib/workers/repository/update/branch/index.spec.ts b/lib/workers/repository/update/branch/index.spec.ts
index 67cd04883cd9cb6ae6ea99100d5362d26e5cbf4f..eda3f7965440e0faf921bbdbb0dbf1c4f9be0ac9 100644
--- a/lib/workers/repository/update/branch/index.spec.ts
+++ b/lib/workers/repository/update/branch/index.spec.ts
@@ -487,7 +487,7 @@ describe('workers/repository/update/branch/index', () => {
       git.branchExists.mockReturnValue(true);
       commit.commitFilesToBranch.mockResolvedValueOnce(null);
       automerge.tryBranchAutomerge.mockResolvedValueOnce('automerged');
-      GlobalConfig.set({ ...adminConfig, dryRun: true });
+      GlobalConfig.set({ ...adminConfig, dryRun: 'full' });
       await branchWorker.processBranch(config);
       expect(automerge.tryBranchAutomerge).toHaveBeenCalledTimes(1);
       expect(prWorker.ensurePr).toHaveBeenCalledTimes(0);
@@ -831,7 +831,7 @@ describe('workers/repository/update/branch/index', () => {
       checkExisting.prAlreadyExisted.mockResolvedValueOnce({
         state: PrState.Closed,
       } as Pr);
-      GlobalConfig.set({ ...adminConfig, dryRun: true });
+      GlobalConfig.set({ ...adminConfig, dryRun: 'full' });
       expect(await branchWorker.processBranch(config)).toEqual({
         branchExists: false,
         prNo: undefined,
@@ -845,7 +845,7 @@ describe('workers/repository/update/branch/index', () => {
         state: PrState.Open,
       } as Pr);
       git.isBranchModified.mockResolvedValueOnce(true);
-      GlobalConfig.set({ ...adminConfig, dryRun: true });
+      GlobalConfig.set({ ...adminConfig, dryRun: 'full' });
       expect(await branchWorker.processBranch(config)).toEqual({
         branchExists: true,
         prNo: undefined,
@@ -871,7 +871,7 @@ describe('workers/repository/update/branch/index', () => {
       git.isBranchModified.mockResolvedValueOnce(true);
       schedule.isScheduledNow.mockReturnValueOnce(false);
       commit.commitFilesToBranch.mockResolvedValueOnce(null);
-      GlobalConfig.set({ ...adminConfig, dryRun: true });
+      GlobalConfig.set({ ...adminConfig, dryRun: 'full' });
       expect(
         await branchWorker.processBranch({
           ...config,
@@ -908,7 +908,7 @@ describe('workers/repository/update/branch/index', () => {
         pr: {},
       } as ResultWithPr);
       commit.commitFilesToBranch.mockResolvedValueOnce(null);
-      GlobalConfig.set({ ...adminConfig, dryRun: true });
+      GlobalConfig.set({ ...adminConfig, dryRun: 'full' });
       expect(
         await branchWorker.processBranch({
           ...config,
diff --git a/lib/workers/repository/update/pr/automerge.spec.ts b/lib/workers/repository/update/pr/automerge.spec.ts
index 7eda18fbc7d1066826292cb167e5a0370eefcfd9..dcbace11740d374428dd7824b1ccfafad6c2879d 100644
--- a/lib/workers/repository/update/pr/automerge.spec.ts
+++ b/lib/workers/repository/update/pr/automerge.spec.ts
@@ -1,4 +1,5 @@
 import { getConfig, git, mocked, partial } from '../../../../../test/util';
+import { GlobalConfig } from '../../../../config/global';
 import { Pr, platform as _platform } from '../../../../modules/platform';
 import { BranchStatus } from '../../../../types';
 import type { BranchConfig } from '../../../types';
@@ -105,5 +106,28 @@ describe('workers/repository/update/pr/automerge', () => {
       });
       expect(platform.mergePr).toHaveBeenCalledTimes(0);
     });
+    it('dryRun full should not automerge', async () => {
+      config.automerge = true;
+      GlobalConfig.set({ dryRun: 'full' });
+      platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
+      const res = await prAutomerge.checkAutoMerge(pr, config);
+      expect(res).toEqual({
+        automerged: false,
+        prAutomergeBlockReason: 'DryRun',
+      });
+      expect(platform.mergePr).toHaveBeenCalledTimes(0);
+    });
+    it('dryRun full pr-comment', async () => {
+      config.automergeType = 'pr-comment';
+      const expectedResult = {
+        automerged: false,
+        prAutomergeBlockReason: 'DryRun',
+      };
+      platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
+      GlobalConfig.set({ dryRun: 'full' });
+      const res = await prAutomerge.checkAutoMerge(pr, config);
+      expect(res).toEqual(expectedResult);
+      expect(platform.mergePr).toHaveBeenCalledTimes(0);
+    });
   });
 });