diff --git a/lib/modules/manager/bazel/common.ts b/lib/modules/manager/bazel/common.ts
deleted file mode 100644
index 7bb8c95b4f5f5b73f66511594e1fa8167653b1e4..0000000000000000000000000000000000000000
--- a/lib/modules/manager/bazel/common.ts
+++ /dev/null
@@ -1,287 +0,0 @@
-import is from '@sindresorhus/is';
-import parseGithubUrl from 'github-url-from-git';
-import { logger } from '../../../logger';
-import { regEx } from '../../../util/regex';
-import { parseUrl } from '../../../util/url';
-import { DockerDatasource } from '../../datasource/docker';
-import { GithubReleasesDatasource } from '../../datasource/github-releases';
-import { GithubTagsDatasource } from '../../datasource/github-tags';
-import { GoDatasource } from '../../datasource/go';
-import { id as dockerVersioning } from '../../versioning/docker';
-import type { PackageDependency } from '../types';
-import type {
-  Fragment,
-  StringFragment,
-  Target,
-  TargetAttribute,
-  UrlParsedResult,
-} from './types';
-
-function isTarget(x: Record<string, TargetAttribute>): x is Target {
-  return is.string(x.name) && is.string(x.rule);
-}
-
-export function coerceFragmentToTarget(fragment: Fragment): Target | null {
-  if (fragment.type === 'record') {
-    const { children } = fragment;
-    const target: Record<string, TargetAttribute> = {};
-    for (const [key, value] of Object.entries(children)) {
-      if (value.type === 'array') {
-        const values = value.children
-          .filter((x): x is StringFragment => x.type === 'string')
-          .map((x) => x.value);
-        target[key] = values;
-      } else if (value.type === 'string') {
-        target[key] = value.value;
-      }
-    }
-
-    if (isTarget(target)) {
-      return target;
-    }
-  }
-
-  return null;
-}
-
-export function parseArchiveUrl(
-  urlString: string | undefined | null
-): UrlParsedResult | null {
-  if (!urlString) {
-    return null;
-  }
-  const url = parseUrl(urlString);
-  if (!url || url.host !== 'github.com' || !url.pathname) {
-    return null;
-  }
-  const path = url.pathname.split('/').slice(1);
-  const repo = path[0] + '/' + path[1];
-  let datasource = '';
-  let currentValue: string | null = null;
-  if (path[2] === 'releases' && path[3] === 'download') {
-    datasource = GithubReleasesDatasource.id;
-    currentValue = path[4];
-  } else if (
-    path[2] === 'archive' &&
-    path[3] === 'refs' &&
-    path[4] === 'tags'
-  ) {
-    datasource = GithubTagsDatasource.id;
-    currentValue = path[5];
-  } else if (path[2] === 'archive') {
-    datasource = GithubTagsDatasource.id;
-    currentValue = path[3];
-  }
-
-  if (currentValue) {
-    // Strip archive extension to get hash or tag.
-    // Tolerates formats produced by Git(Hub|Lab) and allowed by http_archive
-    // Note: Order matters in suffix list to strip, e.g. .tar.gz.
-    for (const extension of ['.gz', '.bz2', '.xz', '.tar', '.tgz', '.zip']) {
-      if (currentValue.endsWith(extension)) {
-        currentValue = currentValue.slice(0, -extension.length);
-      }
-    }
-
-    return { datasource, repo, currentValue };
-  }
-  return null;
-}
-
-export function gitDependency({
-  rule: depType,
-  name: depName,
-  tag: currentValue,
-  commit: currentDigest,
-  remote,
-}: Target): PackageDependency | null {
-  let dep: PackageDependency | null = null;
-
-  if (
-    depType === 'git_repository' &&
-    is.string(depName) &&
-    (is.string(currentValue) || is.string(currentDigest)) &&
-    is.string(remote)
-  ) {
-    dep = {
-      datasource: GithubReleasesDatasource.id,
-      depType,
-      depName,
-    };
-
-    if (is.string(currentValue)) {
-      dep.currentValue = currentValue;
-    }
-
-    if (is.string(currentDigest)) {
-      dep.currentDigest = currentDigest;
-    }
-
-    // TODO: Check if we really need to use parse here or if it should always be a plain https url (#9605)
-    const packageName = parseGithubUrl(remote)?.substring(
-      'https://github.com/'.length
-    );
-
-    // istanbul ignore else
-    if (packageName) {
-      dep.packageName = packageName;
-    } else {
-      dep.skipReason = 'unsupported-remote';
-    }
-  }
-
-  return dep;
-}
-
-export function goDependency({
-  rule: depType,
-  name: depName,
-  tag: currentValue,
-  commit: currentDigest,
-  importpath: packageName,
-  remote,
-}: Target): PackageDependency | null {
-  let dep: PackageDependency | null = null;
-
-  if (
-    depType === 'go_repository' &&
-    is.string(depName) &&
-    (is.string(currentValue) || is.string(currentDigest)) &&
-    is.string(packageName)
-  ) {
-    dep = {
-      datasource: GoDatasource.id,
-      depType,
-      depName,
-      packageName,
-    };
-
-    if (is.string(currentValue)) {
-      dep.currentValue = currentValue;
-    }
-
-    if (is.string(currentDigest)) {
-      dep.currentValue = 'v0.0.0';
-      dep.currentDigest = currentDigest;
-      dep.currentDigestShort = currentDigest.substring(0, 7);
-      dep.digestOneAndOnly = true;
-    }
-
-    if (is.string(remote)) {
-      const remoteMatch = regEx(
-        /https:\/\/github\.com(?:.*\/)(([a-zA-Z]+)([-])?([a-zA-Z]+))/
-      ).exec(remote);
-      if (remoteMatch && remoteMatch[0].length === remote.length) {
-        dep.packageName = remote.replace('https://', '');
-      } else {
-        dep.skipReason = 'unsupported-remote';
-      }
-    }
-  }
-
-  return dep;
-}
-
-export function httpDependency({
-  rule: depType,
-  name: depName,
-  url,
-  urls,
-  sha256,
-}: Target): PackageDependency | null {
-  let dep: PackageDependency | null = null;
-
-  if (
-    (depType === 'http_archive' || depType === 'http_file') &&
-    is.string(depName) &&
-    is.string(sha256)
-  ) {
-    let parsedUrl: UrlParsedResult | null = null;
-    if (is.string(url)) {
-      parsedUrl = parseArchiveUrl(url);
-    } else if (is.array(urls, is.string)) {
-      for (const u of urls) {
-        parsedUrl = parseArchiveUrl(u);
-        if (parsedUrl) {
-          break;
-        }
-      }
-    }
-
-    if (parsedUrl) {
-      dep = {
-        datasource: parsedUrl.datasource,
-        depType,
-        depName,
-        packageName: parsedUrl.repo,
-      };
-
-      if (regEx(/^[a-f0-9]{40}$/i).test(parsedUrl.currentValue)) {
-        dep.currentDigest = parsedUrl.currentValue;
-      } else {
-        dep.currentValue = parsedUrl.currentValue;
-      }
-    }
-  }
-
-  return dep;
-}
-
-export function dockerDependency({
-  rule: depType,
-  name: depName,
-  tag: currentValue,
-  digest: currentDigest,
-  repository: packageName,
-  registry,
-}: Target): PackageDependency | null {
-  let dep: PackageDependency | null = null;
-
-  if (
-    depType === 'container_pull' &&
-    is.string(depName) &&
-    is.string(currentValue) &&
-    is.string(currentDigest) &&
-    is.string(packageName) &&
-    is.string(registry)
-  ) {
-    dep = {
-      datasource: DockerDatasource.id,
-      versioning: dockerVersioning,
-      depType,
-      depName,
-      packageName,
-      currentValue,
-      currentDigest,
-      registryUrls: [registry],
-    };
-  }
-
-  return dep;
-}
-
-type DependencyExtractor = (_: Target) => PackageDependency | null;
-type DependencyExtractorRegistry = Record<string, DependencyExtractor>;
-
-const dependencyExtractorRegistry: DependencyExtractorRegistry = {
-  git_repository: gitDependency,
-  go_repository: goDependency,
-  http_archive: httpDependency,
-  http_file: httpDependency,
-  container_pull: dockerDependency,
-};
-
-const supportedRules = Object.keys(dependencyExtractorRegistry);
-
-export const supportedRulesRegex = regEx(`^${supportedRules.join('|')}$`);
-
-export function extractDepFromTarget(target: Target): PackageDependency | null {
-  const dependencyExtractor = dependencyExtractorRegistry[target.rule];
-  if (!dependencyExtractor) {
-    logger.debug(
-      `Bazel dependency extractor function not found for ${target.rule}`
-    );
-    return null;
-  }
-  return dependencyExtractor(target);
-}
diff --git a/lib/modules/manager/bazel/extract.ts b/lib/modules/manager/bazel/extract.ts
index 15ef0d970852b20d22cdb499a0c5eefc3fd8d086..f266ded95fa31b2caa6fbf8631e8d0e842519d74 100644
--- a/lib/modules/manager/bazel/extract.ts
+++ b/lib/modules/manager/bazel/extract.ts
@@ -1,7 +1,7 @@
 import { logger } from '../../../logger';
 import type { PackageDependency, PackageFile } from '../types';
-import { coerceFragmentToTarget, extractDepFromTarget } from './common';
 import { parse } from './parser';
+import { extractDepFromFragment } from './rules';
 import type { ArrayFragment } from './types';
 
 export function extractPackageFile(
@@ -23,12 +23,8 @@ export function extractPackageFile(
 
   for (let idx = 0; idx < parsed.children.length; idx += 1) {
     const fragment = parsed.children[idx];
-    const target = coerceFragmentToTarget(fragment);
-    if (!target) {
-      continue;
-    }
 
-    const dep = extractDepFromTarget(target);
+    const dep = extractDepFromFragment(fragment);
     if (!dep) {
       continue;
     }
diff --git a/lib/modules/manager/bazel/parser.ts b/lib/modules/manager/bazel/parser.ts
index 6fcb7ce21b8652187cabe0d543eda7f7600810d8..70f5090145b364be9e3fb47862c079e5e5a04151 100644
--- a/lib/modules/manager/bazel/parser.ts
+++ b/lib/modules/manager/bazel/parser.ts
@@ -1,7 +1,7 @@
 import { lang, lexer, parser, query as q } from 'good-enough-parser';
 import hasha from 'hasha';
 import * as memCache from '../../../util/cache/memory';
-import { supportedRulesRegex } from './common';
+import { supportedRulesRegex } from './rules/index';
 import type { ArrayFragment, NestedFragment, RecordFragment } from './types';
 
 interface Ctx {
diff --git a/lib/modules/manager/bazel/rules/docker.ts b/lib/modules/manager/bazel/rules/docker.ts
new file mode 100644
index 0000000000000000000000000000000000000000..797c8c013562f5fbbec5c96edf55e596bc2d3e93
--- /dev/null
+++ b/lib/modules/manager/bazel/rules/docker.ts
@@ -0,0 +1,38 @@
+import is from '@sindresorhus/is';
+import { DockerDatasource } from '../../../datasource/docker';
+import { id as dockerVersioning } from '../../../versioning/docker';
+import type { PackageDependency } from '../../types';
+import type { Target } from '../types';
+
+export function dockerDependency({
+  rule: depType,
+  name: depName,
+  tag: currentValue,
+  digest: currentDigest,
+  repository: packageName,
+  registry,
+}: Target): PackageDependency | null {
+  let dep: PackageDependency | null = null;
+
+  if (
+    depType === 'container_pull' &&
+    is.string(depName) &&
+    is.string(currentValue) &&
+    is.string(currentDigest) &&
+    is.string(packageName) &&
+    is.string(registry)
+  ) {
+    dep = {
+      datasource: DockerDatasource.id,
+      versioning: dockerVersioning,
+      depType,
+      depName,
+      packageName,
+      currentValue,
+      currentDigest,
+      registryUrls: [registry],
+    };
+  }
+
+  return dep;
+}
diff --git a/lib/modules/manager/bazel/rules/git.ts b/lib/modules/manager/bazel/rules/git.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c5ee9affb5476dd1634351cdf5a65d68dd8cd477
--- /dev/null
+++ b/lib/modules/manager/bazel/rules/git.ts
@@ -0,0 +1,50 @@
+import is from '@sindresorhus/is';
+import parseGithubUrl from 'github-url-from-git';
+import { GithubReleasesDatasource } from '../../../datasource/github-releases';
+import type { PackageDependency } from '../../types';
+import type { Target } from '../types';
+
+export function gitDependency({
+  rule: depType,
+  name: depName,
+  tag: currentValue,
+  commit: currentDigest,
+  remote,
+}: Target): PackageDependency | null {
+  let dep: PackageDependency | null = null;
+
+  if (
+    depType === 'git_repository' &&
+    is.string(depName) &&
+    (is.string(currentValue) || is.string(currentDigest)) &&
+    is.string(remote)
+  ) {
+    dep = {
+      datasource: GithubReleasesDatasource.id,
+      depType,
+      depName,
+    };
+
+    if (is.string(currentValue)) {
+      dep.currentValue = currentValue;
+    }
+
+    if (is.string(currentDigest)) {
+      dep.currentDigest = currentDigest;
+    }
+
+    // TODO: Check if we really need to use parse here or if it should always be a plain https url (#9605)
+    const packageName = parseGithubUrl(remote)?.substring(
+      'https://github.com/'.length
+    );
+
+    // istanbul ignore else
+    if (packageName) {
+      dep.packageName = packageName;
+    } else {
+      dep.skipReason = 'unsupported-remote';
+    }
+  }
+
+  return dep;
+}
diff --git a/lib/modules/manager/bazel/rules/go.ts b/lib/modules/manager/bazel/rules/go.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d82036fe04d4119f1fe42d276687bc724dcde41a
--- /dev/null
+++ b/lib/modules/manager/bazel/rules/go.ts
@@ -0,0 +1,54 @@
+import is from '@sindresorhus/is';
+import { regEx } from '../../../../util/regex';
+import { GoDatasource } from '../../../datasource/go';
+import type { PackageDependency } from '../../types';
+import type { Target } from '../types';
+
+export function goDependency({
+  rule: depType,
+  name: depName,
+  tag: currentValue,
+  commit: currentDigest,
+  importpath: packageName,
+  remote,
+}: Target): PackageDependency | null {
+  let dep: PackageDependency | null = null;
+
+  if (
+    depType === 'go_repository' &&
+    is.string(depName) &&
+    (is.string(currentValue) || is.string(currentDigest)) &&
+    is.string(packageName)
+  ) {
+    dep = {
+      datasource: GoDatasource.id,
+      depType,
+      depName,
+      packageName,
+    };
+
+    if (is.string(currentValue)) {
+      dep.currentValue = currentValue;
+    }
+
+    if (is.string(currentDigest)) {
+      dep.currentValue = 'v0.0.0';
+      dep.currentDigest = currentDigest;
+      dep.currentDigestShort = currentDigest.substring(0, 7);
+      dep.digestOneAndOnly = true;
+    }
+
+    if (is.string(remote)) {
+      const remoteMatch = regEx(
+        /https:\/\/github\.com(?:.*\/)(([a-zA-Z]+)([-])?([a-zA-Z]+))/
+      ).exec(remote);
+      if (remoteMatch && remoteMatch[0].length === remote.length) {
+        dep.packageName = remote.replace('https://', '');
+      } else {
+        dep.skipReason = 'unsupported-remote';
+      }
+    }
+  }
+
+  return dep;
+}
diff --git a/lib/modules/manager/bazel/rules/http.ts b/lib/modules/manager/bazel/rules/http.ts
new file mode 100644
index 0000000000000000000000000000000000000000..10dbcfbe03aa9f11d65aecc622c645257dc79293
--- /dev/null
+++ b/lib/modules/manager/bazel/rules/http.ts
@@ -0,0 +1,96 @@
+import is from '@sindresorhus/is';
+import { regEx } from '../../../../util/regex';
+import { parseUrl } from '../../../../util/url';
+import { GithubReleasesDatasource } from '../../../datasource/github-releases';
+import { GithubTagsDatasource } from '../../../datasource/github-tags';
+import type { PackageDependency } from '../../types';
+import type { Target, UrlParsedResult } from '../types';
+
+export function parseArchiveUrl(
+  urlString: string | undefined | null
+): UrlParsedResult | null {
+  if (!urlString) {
+    return null;
+  }
+  const url = parseUrl(urlString);
+  if (!url || url.host !== 'github.com' || !url.pathname) {
+    return null;
+  }
+  const path = url.pathname.split('/').slice(1);
+  const repo = path[0] + '/' + path[1];
+  let datasource = '';
+  let currentValue: string | null = null;
+  if (path[2] === 'releases' && path[3] === 'download') {
+    datasource = GithubReleasesDatasource.id;
+    currentValue = path[4];
+  } else if (
+    path[2] === 'archive' &&
+    path[3] === 'refs' &&
+    path[4] === 'tags'
+  ) {
+    datasource = GithubTagsDatasource.id;
+    currentValue = path[5];
+  } else if (path[2] === 'archive') {
+    datasource = GithubTagsDatasource.id;
+    currentValue = path[3];
+  }
+
+  if (currentValue) {
+    // Strip archive extension to get hash or tag.
+    // Tolerates formats produced by Git(Hub|Lab) and allowed by http_archive
+    // Note: Order matters in suffix list to strip, e.g. .tar.gz.
+    for (const extension of ['.gz', '.bz2', '.xz', '.tar', '.tgz', '.zip']) {
+      if (currentValue.endsWith(extension)) {
+        currentValue = currentValue.slice(0, -extension.length);
+      }
+    }
+
+    return { datasource, repo, currentValue };
+  }
+  return null;
+}
+
+export function httpDependency({
+  rule: depType,
+  name: depName,
+  url,
+  urls,
+  sha256,
+}: Target): PackageDependency | null {
+  let dep: PackageDependency | null = null;
+
+  if (
+    (depType === 'http_archive' || depType === 'http_file') &&
+    is.string(depName) &&
+    is.string(sha256)
+  ) {
+    let parsedUrl: UrlParsedResult | null = null;
+    if (is.string(url)) {
+      parsedUrl = parseArchiveUrl(url);
+    } else if (is.array(urls, is.string)) {
+      for (const u of urls) {
+        parsedUrl = parseArchiveUrl(u);
+        if (parsedUrl) {
+          break;
+        }
+      }
+    }
+
+    if (parsedUrl) {
+      dep = {
+        datasource: parsedUrl.datasource,
+        depType,
+        depName,
+        packageName: parsedUrl.repo,
+      };
+
+      if (regEx(/^[a-f0-9]{40}$/i).test(parsedUrl.currentValue)) {
+        dep.currentDigest = parsedUrl.currentValue;
+      } else {
+        dep.currentValue = parsedUrl.currentValue;
+      }
+    }
+  }
+
+  return dep;
+}
diff --git a/lib/modules/manager/bazel/common.spec.ts b/lib/modules/manager/bazel/rules/index.spec.ts
similarity index 80%
rename from lib/modules/manager/bazel/common.spec.ts
rename to lib/modules/manager/bazel/rules/index.spec.ts
index 10c25c67fe0ba2322859e59c79b2eba294895984..f0b268641db0831d9687b02bafe3f043135b6169 100644
--- a/lib/modules/manager/bazel/common.spec.ts
+++ b/lib/modules/manager/bazel/rules/index.spec.ts
@@ -1,13 +1,10 @@
-import {
-  dockerDependency,
-  extractDepFromTarget,
-  gitDependency,
-  goDependency,
-  httpDependency,
-  parseArchiveUrl,
-} from './common';
+import { dockerDependency } from './docker';
+import { gitDependency } from './git';
+import { goDependency } from './go';
+import { httpDependency, parseArchiveUrl } from './http';
+import { extractDepFromFragment } from '.';
 
-describe('modules/manager/bazel/common', () => {
+describe('modules/manager/bazel/rules/index', () => {
   test('parseUrl', () => {
     expect(parseArchiveUrl('')).toBeNull();
     expect(parseArchiveUrl(null)).toBeNull();
@@ -291,18 +288,37 @@ describe('modules/manager/bazel/common', () => {
     });
   });
 
-  describe('extractDepFromTarget', () => {
+  describe('extractDepFromFragment', () => {
     it('returns null for unknown rule type', () => {
-      expect(extractDepFromTarget({ rule: 'foo', name: 'bar' })).toBeNull();
+      expect(
+        extractDepFromFragment({
+          type: 'record',
+          value: '',
+          offset: 0,
+          children: {
+            rule: { type: 'string', value: 'foo', offset: 0 },
+            name: { type: 'string', value: 'bar', offset: 0 },
+          },
+        })
+      ).toBeNull();
     });
 
     it('extracts from git_repository', () => {
       expect(
-        extractDepFromTarget({
-          rule: 'git_repository',
-          name: 'foo_bar',
-          tag: '1.2.3',
-          remote: 'https://github.com/foo/bar',
+        extractDepFromFragment({
+          type: 'record',
+          value: '',
+          offset: 0,
+          children: {
+            rule: { type: 'string', value: 'git_repository', offset: 0 },
+            name: { type: 'string', value: 'foo_bar', offset: 0 },
+            tag: { type: 'string', value: '1.2.3', offset: 0 },
+            remote: {
+              type: 'string',
+              value: 'https://github.com/foo/bar',
+              offset: 0,
+            },
+          },
         })
       ).toEqual({
         datasource: 'github-releases',
@@ -315,14 +331,33 @@ describe('modules/manager/bazel/common', () => {
 
     it('extracts from http_archive', () => {
       expect(
-        extractDepFromTarget({
-          rule: 'http_archive',
-          name: 'rules_nodejs',
-          sha256:
-            '5aef09ed3279aa01d5c928e3beb248f9ad32dde6aafe6373a8c994c3ce643064',
-          urls: [
-            'https://github.com/bazelbuild/rules_nodejs/releases/download/5.5.3/rules_nodejs-core-5.5.3.tar.gz',
-          ],
+        extractDepFromFragment({
+          type: 'record',
+          value: '',
+          offset: 0,
+          children: {
+            rule: { type: 'string', value: 'http_archive', offset: 0 },
+            name: { type: 'string', value: 'rules_nodejs', offset: 0 },
+            sha256: {
+              type: 'string',
+              value:
+                '5aef09ed3279aa01d5c928e3beb248f9ad32dde6aafe6373a8c994c3ce643064',
+              offset: 0,
+            },
+            urls: {
+              type: 'array',
+              value: '',
+              offset: 0,
+              children: [
+                {
+                  type: 'string',
+                  offset: 0,
+                  value:
+                    'https://github.com/bazelbuild/rules_nodejs/releases/download/5.5.3/rules_nodejs-core-5.5.3.tar.gz',
+                },
+              ],
+            },
+          },
         })
       ).toEqual({
         datasource: 'github-releases',
diff --git a/lib/modules/manager/bazel/rules/index.ts b/lib/modules/manager/bazel/rules/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ec9c7966541da2580e97b5fe06db3fd342371e3e
--- /dev/null
+++ b/lib/modules/manager/bazel/rules/index.ts
@@ -0,0 +1,74 @@
+import is from '@sindresorhus/is';
+import { logger } from '../../../../logger';
+import { regEx } from '../../../../util/regex';
+import type { PackageDependency } from '../../types';
+import type {
+  Fragment,
+  StringFragment,
+  Target,
+  TargetAttribute,
+} from '../types';
+import { dockerDependency } from './docker';
+import { gitDependency } from './git';
+import { goDependency } from './go';
+import { httpDependency } from './http';
+
+type DependencyExtractor = (_: Target) => PackageDependency | null;
+type DependencyExtractorRegistry = Record<string, DependencyExtractor>;
+
+const dependencyExtractorRegistry: DependencyExtractorRegistry = {
+  git_repository: gitDependency,
+  go_repository: goDependency,
+  http_archive: httpDependency,
+  http_file: httpDependency,
+  container_pull: dockerDependency,
+};
+
+const supportedRules = Object.keys(dependencyExtractorRegistry);
+export const supportedRulesRegex = regEx(`^${supportedRules.join('|')}$`);
+
+function isTarget(x: Record<string, TargetAttribute>): x is Target {
+  return is.string(x.name) && is.string(x.rule);
+}
+
+export function coerceFragmentToTarget(fragment: Fragment): Target | null {
+  if (fragment.type === 'record') {
+    const { children } = fragment;
+    const target: Record<string, TargetAttribute> = {};
+    for (const [key, value] of Object.entries(children)) {
+      if (value.type === 'array') {
+        const values = value.children
+          .filter((x): x is StringFragment => x.type === 'string')
+          .map((x) => x.value);
+        target[key] = values;
+      } else if (value.type === 'string') {
+        target[key] = value.value;
+      }
+    }
+
+    if (isTarget(target)) {
+      return target;
+    }
+  }
+
+  return null;
+}
+
+export function extractDepFromFragment(
+  fragment: Fragment
+): PackageDependency | null {
+  const target = coerceFragmentToTarget(fragment);
+  if (!target) {
+    return null;
+  }
+
+  const dependencyExtractor = dependencyExtractorRegistry[target.rule];
+  if (!dependencyExtractor) {
+    logger.debug(
+      `Bazel dependency extractor function not found for ${target.rule}`
+    );
+    return null;
+  }
+
+  return dependencyExtractor(target);
+}