fix: Remove repository cache migrations (#18025)

This commit is contained in:
Sergei Zharinov 2022-10-02 08:34:50 +03:00 committed by GitHub
parent 3f0303c167
commit db1086a79f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 29 additions and 247 deletions

View file

@ -1,70 +1,2 @@
import is from '@sindresorhus/is';
import type {
RepoCacheRecordV10,
RepoCacheRecordV11,
RepoCacheRecordV12,
RepoCacheRecordV13,
} from './types';
// Increment this whenever there could be incompatibilities between old and new cache structure
export const CACHE_REVISION = 13;
export function isValidRev10(
input: unknown,
repo?: string
): input is RepoCacheRecordV10 {
return (
is.plainObject(input) &&
is.safeInteger(input.revision) &&
input.revision === 10 &&
is.string(input.repository) &&
(!repo || repo === input.repository)
);
}
export function isValidRev11(
input: unknown,
repo?: string
): input is RepoCacheRecordV11 {
return (
is.plainObject(input) &&
is.safeInteger(input.revision) &&
input.revision === 11 &&
is.string(input.repository) &&
is.plainObject(input.data) &&
(!repo || repo === input.repository)
);
}
function isValidRev12Shape(
input: unknown,
repo?: string
): input is RepoCacheRecordV12 {
return (
is.plainObject(input) &&
is.safeInteger(input.revision) &&
is.string(input.repository) &&
is.string(input.payload) &&
is.string(input.hash)
);
}
export function isValidRev12(
input: unknown,
repo?: string
): input is RepoCacheRecordV12 {
return (
isValidRev12Shape(input, repo) &&
input.revision === 12 &&
(!repo || repo === input.repository)
);
}
export function isValidRev13(input: unknown): input is RepoCacheRecordV13 {
return (
is.plainObject(input) &&
is.string(input.fingerprint) &&
isValidRev12Shape(input) &&
input.revision === 13
);
}

View file

@ -4,23 +4,11 @@ import is from '@sindresorhus/is';
import hasha from 'hasha';
import { GlobalConfig } from '../../../../config/global';
import { logger } from '../../../../logger';
import * as schema from '../../../schema';
import { safeStringify } from '../../../stringify';
import {
CACHE_REVISION,
isValidRev10,
isValidRev11,
isValidRev12,
isValidRev13,
} from '../common';
import type {
RepoCache,
RepoCacheData,
RepoCacheRecord,
RepoCacheRecordV10,
RepoCacheRecordV11,
RepoCacheRecordV12,
RepoCacheRecordV13,
} from '../types';
import { CACHE_REVISION } from '../common';
import { RepoCacheRecord, RepoCacheV13 } from '../schemas';
import type { RepoCache, RepoCacheData } from '../types';
const compress = promisify(zlib.brotliCompress);
const decompress = promisify(zlib.brotliDecompress);
@ -39,17 +27,11 @@ export abstract class RepoCacheBase implements RepoCache {
protected abstract write(data: RepoCacheRecord): Promise<void>;
private restoreFromRev10(oldCache: RepoCacheRecordV10): void {
delete oldCache.repository;
delete oldCache.revision;
this.data = oldCache;
private async restore(oldCache: RepoCacheRecord): Promise<void> {
if (oldCache.fingerprint !== this.fingerprint) {
logger.debug('Repository cache fingerprint is invalid');
return;
}
private restoreFromRev11(oldCache: RepoCacheRecordV11): void {
this.data = oldCache.data;
}
private async restoreFromRev12(oldCache: RepoCacheRecordV12): Promise<void> {
const compressed = Buffer.from(oldCache.payload, 'base64');
const uncompressed = await decompress(compressed);
const jsonStr = uncompressed.toString('utf8');
@ -57,14 +39,6 @@ export abstract class RepoCacheBase implements RepoCache {
this.oldHash = oldCache.hash;
}
private async restoreFromRev13(oldCache: RepoCacheRecordV13): Promise<void> {
if (oldCache.fingerprint !== this.fingerprint) {
logger.debug('Repository cache fingerprint is invalid');
return;
}
await this.restoreFromRev12(oldCache);
}
async load(): Promise<void> {
try {
const rawOldCache = await this.read();
@ -76,30 +50,12 @@ export abstract class RepoCacheBase implements RepoCache {
}
const oldCache = JSON.parse(rawOldCache) as unknown;
if (isValidRev13(oldCache)) {
await this.restoreFromRev13(oldCache);
if (schema.match(RepoCacheV13, oldCache)) {
await this.restore(oldCache);
logger.debug('Repository cache is restored from revision 13');
return;
}
if (isValidRev12(oldCache, this.repository)) {
await this.restoreFromRev12(oldCache);
logger.debug('Repository cache is restored from revision 12');
return;
}
if (isValidRev11(oldCache, this.repository)) {
this.restoreFromRev11(oldCache);
logger.debug('Repository cache is restored from revision 11');
return;
}
if (isValidRev10(oldCache, this.repository)) {
this.restoreFromRev10(oldCache);
logger.debug('Repository cache is restored from revision 10');
return;
}
logger.debug('Repository cache is invalid');
} catch (err) {
logger.debug({ err }, 'Error reading repository cache');

View file

@ -5,7 +5,8 @@ import { fs } from '../../../../../test/util';
import { GlobalConfig } from '../../../../config/global';
import { logger } from '../../../../logger';
import { CACHE_REVISION } from '../common';
import type { RepoCacheData, RepoCacheRecord } from '../types';
import type { RepoCacheRecord } from '../schemas';
import type { RepoCacheData } from '../types';
import { CacheFactory } from './cache-factory';
import { RepoCacheLocal } from './local';
@ -109,102 +110,6 @@ describe('util/cache/repository/impl/local', () => {
expect(cache2.getData()).toBeEmpty();
});
it('migrates revision from 10 to 13', async () => {
fs.readCacheFile.mockResolvedValue(
JSON.stringify({
revision: 10,
repository: 'some/repo',
semanticCommits: 'enabled',
})
);
const localRepoCache = CacheFactory.get(
'some/repo',
'0123456789abcdef',
'local'
);
await localRepoCache.load();
await localRepoCache.save();
const cacheRecord = await createCacheRecord({ semanticCommits: 'enabled' });
expect(fs.outputCacheFile).toHaveBeenCalledWith(
'/tmp/cache/renovate/repository/github/some/repo.json',
JSON.stringify(cacheRecord)
);
});
it('migrates revision from 11 to 13', async () => {
fs.readCacheFile.mockResolvedValue(
JSON.stringify({
revision: 11,
repository: 'some/repo',
data: { semanticCommits: 'enabled' },
})
);
const localRepoCache = CacheFactory.get(
'some/repo',
'0123456789abcdef',
'local'
);
await localRepoCache.load();
await localRepoCache.save();
const cacheRecord = await createCacheRecord({ semanticCommits: 'enabled' });
expect(fs.outputCacheFile).toHaveBeenCalledWith(
'/tmp/cache/renovate/repository/github/some/repo.json',
JSON.stringify(cacheRecord)
);
});
it('migrates revision from 12 to 13', async () => {
const { repository, payload, hash } = await createCacheRecord({
semanticCommits: 'enabled',
});
fs.readCacheFile.mockResolvedValue(
JSON.stringify({ revision: 12, repository, payload, hash })
);
const localRepoCache = CacheFactory.get(
'some/repo',
'0123456789abcdef',
'local'
);
await localRepoCache.load();
const data = localRepoCache.getData();
data.semanticCommits = 'disabled';
await localRepoCache.save();
expect(fs.outputCacheFile).toHaveBeenCalledWith(
'/tmp/cache/renovate/repository/github/some/repo.json',
JSON.stringify(
await createCacheRecord({
semanticCommits: 'disabled',
})
)
);
});
it('does not migrate from older revisions to 11', async () => {
fs.readCacheFile.mockResolvedValueOnce(
JSON.stringify({
revision: 9,
repository: 'some/repo',
semanticCommits: 'enabled',
})
);
const localRepoCache = CacheFactory.get(
'some/repo',
'0123456789abcdef',
'local'
);
await localRepoCache.load();
expect(localRepoCache.getData()).toBeEmpty();
});
it('handles invalid data', async () => {
fs.readCacheFile.mockResolvedValue(JSON.stringify({ foo: 'bar' }));
const localRepoCache = CacheFactory.get(

View file

@ -2,7 +2,7 @@ import upath from 'upath';
import { GlobalConfig } from '../../../../config/global';
import { logger } from '../../../../logger';
import { cachePathExists, outputCacheFile, readCacheFile } from '../../../fs';
import type { RepoCacheRecord } from '../types';
import type { RepoCacheRecord } from '../schemas';
import { RepoCacheBase } from './base';
export class RepoCacheLocal extends RepoCacheBase {

View file

@ -12,7 +12,7 @@ import { partial } from '../../../../../test/util';
import { GlobalConfig } from '../../../../config/global';
import { logger } from '../../../../logger';
import { parseS3Url } from '../../../s3';
import type { RepoCacheRecord } from '../types';
import type { RepoCacheRecord } from '../schemas';
import { CacheFactory } from './cache-factory';
import { RepoCacheS3 } from './s3';

View file

@ -8,7 +8,7 @@ import {
import { logger } from '../../../../logger';
import { getS3Client, parseS3Url } from '../../../s3';
import { streamToString } from '../../../streams';
import type { RepoCacheRecord } from '../types';
import type { RepoCacheRecord } from '../schemas';
import { RepoCacheBase } from './base';
export class RepoCacheS3 extends RepoCacheBase {

13
lib/util/cache/repository/schemas.ts vendored Normal file
View file

@ -0,0 +1,13 @@
import { z } from 'zod';
export const RepoCacheV13 = z
.object({
repository: z.string().min(1),
revision: z.number().refine((v) => v === 13),
payload: z.string().min(1),
hash: z.string().min(1),
fingerprint: z.string().min(1),
})
.strict();
export type RepoCacheRecord = z.infer<typeof RepoCacheV13>;

View file

@ -75,30 +75,6 @@ export interface RepoCacheData {
prComments?: Record<number, Record<string, string>>;
}
export interface RepoCacheRecordV10 extends RepoCacheData {
repository?: string;
revision?: number;
}
export interface RepoCacheRecordV11 {
repository: string;
revision: number;
data: RepoCacheData;
}
export interface RepoCacheRecordV12 {
repository: string;
revision: number;
payload: string;
hash: string;
}
export interface RepoCacheRecordV13 extends RepoCacheRecordV12 {
fingerprint: string;
}
export type RepoCacheRecord = RepoCacheRecordV13;
export interface RepoCache {
load(): Promise<void>;
save(): Promise<void>;