diff --git a/lib/versioning/index.spec.ts b/lib/versioning/index.spec.ts
index 8cb9aba9541ebe7f61783b0bd3640fb106fb8c15..9cebaf8a0fe11eb5bf3135a6fc65be2de3b1c2af 100644
--- a/lib/versioning/index.spec.ts
+++ b/lib/versioning/index.spec.ts
@@ -2,6 +2,12 @@ import * as allVersioning from '.';
 import { getOptions } from '../config/definitions';
 import { GenericVersioningApi, GenericVersion } from './loose/generic';
 import * as semverVersioning from './semver';
+import { loadModules } from '../util/modules';
+import {
+  VersioningApi,
+  VersioningApiConstructor,
+  isVersioningApiConstructor,
+} from './common';
 
 const supportedSchemes = getOptions().find(
   option => option.name === 'versioning'
@@ -11,6 +17,31 @@ describe('allVersioning.get(versioning)', () => {
   it('has api', () => {
     expect(Object.keys(allVersioning.get('semver')).sort()).toMatchSnapshot();
   });
+  it('validates', () => {
+    function validate(
+      module: VersioningApi | VersioningApiConstructor,
+      name: string
+    ): boolean {
+      // eslint-disable-next-line new-cap
+      const mod = isVersioningApiConstructor(module) ? new module() : module;
+
+      // TODO: test required api
+      if (!mod.isValid || !mod.isVersion) {
+        fail(`Missing api on ${name}`);
+      }
+
+      return true;
+    }
+    const vers = allVersioning.getVersionings();
+
+    const loadedVers = loadModules(__dirname);
+    expect(Array.from(vers.keys())).toEqual(Object.keys(loadedVers));
+
+    for (const name of vers.keys()) {
+      const ver = vers.get(name);
+      expect(validate(ver, name)).toBe(true);
+    }
+  });
 
   it('should fallback to semver', () => {
     expect(allVersioning.get(undefined)).toBe(
diff --git a/lib/versioning/index.ts b/lib/versioning/index.ts
index f015d34f4ec7b635ab006bfa42d61812881a7bbc..66ca4d94039bfbcb61b22e951ac3112c491876e0 100644
--- a/lib/versioning/index.ts
+++ b/lib/versioning/index.ts
@@ -1,42 +1,26 @@
-import fs from 'fs';
 import { logger } from '../logger';
 import {
   VersioningApi,
-  VersioningApiConstructor,
   isVersioningApiConstructor,
+  VersioningApiConstructor,
 } from './common';
+import versionings from './api.generated';
 
 export * from './common';
 
-const allVersioning: Record<
+export const getVersioningList = (): string[] => Array.from(versionings.keys());
+/**
+ * Get versioning map. Can be used to dynamically add new versionig type
+ */
+export const getVersionings = (): Map<
   string,
   VersioningApi | VersioningApiConstructor
-> = {};
-
-const versioningList: string[] = [];
-
-export const getVersioningList = (): string[] => versioningList;
-
-const versionings = fs
-  .readdirSync(__dirname, { withFileTypes: true })
-  .filter(dirent => dirent.isDirectory() && !dirent.name.startsWith('_'))
-  .map(dirent => dirent.name)
-  .sort();
-
-for (const versioning of versionings) {
-  try {
-    allVersioning[versioning] = require('./' + versioning).api; // eslint-disable-line
-    versioningList.push(versioning);
-  } catch (err) /* istanbul ignore next */ {
-    logger.fatal({ err }, `Can not load versioning "${versioning}".`);
-    process.exit(1);
-  }
-}
+> => versionings;
 
 export function get(versioning: string): VersioningApi {
   if (!versioning) {
     logger.debug('Missing versioning');
-    return allVersioning.semver as VersioningApi;
+    return versionings.get('semver') as VersioningApi;
   }
   let versioningName: string;
   let versioningConfig: string;
@@ -48,12 +32,11 @@ export function get(versioning: string): VersioningApi {
   } else {
     versioningName = versioning;
   }
-  const theVersioning = allVersioning[versioningName];
+  const theVersioning = versionings.get(versioningName);
   if (!theVersioning) {
     logger.warn({ versioning }, 'Unknown versioning');
-    return allVersioning.semver as VersioningApi;
+    return versionings.get('semver') as VersioningApi;
   }
-  // istanbul ignore if: needs an implementation
   if (isVersioningApiConstructor(theVersioning)) {
     // eslint-disable-next-line new-cap
     return new theVersioning(versioningConfig);
diff --git a/tools/generate-imports.ts b/tools/generate-imports.ts
index c3f470ddfaca7f768dc6113a4faa00cd9cbe36e0..5e1379890951439e924a5e00e03e1e868276a981 100644
--- a/tools/generate-imports.ts
+++ b/tools/generate-imports.ts
@@ -25,8 +25,41 @@ async function updateFile(file: string, code: string): Promise<void> {
   }
   newFiles.add(file);
 }
+
+async function generate({
+  path,
+  types,
+  map = '',
+  excludes = [],
+}: {
+  path: string;
+  types: string[];
+  map?: string;
+  excludes?: string[];
+}): Promise<void> {
+  shell.echo(`> ${path}`);
+  let imports = '';
+  let maps = '';
+  for (const ds of findModules(`lib/${path}`).filter(
+    n => !excludes?.includes(n)
+  )) {
+    const name = _.camelCase(ds);
+    imports += `import * as ${name} from './${ds}';\n`;
+    maps += `api.set('${ds}', ${name}${map});\n`;
+  }
+
+  const code = `import { ${types.join(', ')} } from './common';
+    ${imports}\n
+    const api = new Map<string, ${types.join(' | ')}>();
+    export default api;
+    ${maps}`;
+
+  await updateFile(`lib/${path}/api.generated.ts`, code.replace(/^\s+/gm, ''));
+}
+
 (async () => {
   try {
+    // datasources
     shell.echo('> datasources');
     let code = `
 import { Datasource } from './common';
@@ -38,22 +71,15 @@ export default api;
     }
     await updateFile('lib/datasource/api.generated.ts', code);
 
-    shell.echo('> managers');
-    let imports = '';
-    let maps = '';
-    for (const ds of findModules('lib/manager')) {
-      const name = _.camelCase(ds);
-      imports += `import * as ${name} from './${ds}';\n`;
-      maps += `api.set('${ds}', ${name});\n`;
-    }
-
-    code = `import { ManagerApi } from './common';
-${imports}
-const api = new Map<string, ManagerApi>();
-export default api;
-${maps}`;
+    // managers
+    await generate({ path: 'manager', types: ['ManagerApi'] });
 
-    await updateFile('lib/manager/api.generated.ts', code);
+    // versioning
+    await generate({
+      path: 'versioning',
+      types: ['VersioningApi', 'VersioningApiConstructor'],
+      map: '.api',
+    });
 
     await Promise.all(
       shell