Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(onboarding): use cache to check if repo is onboarded #20733

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lib/util/cache/repository/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ export interface BranchUpgradeCache {
sourceUrl?: string;
}

export interface OnboardingBranchCache {
onboardingBranch: string;
defaultBranchSha: string;
onboardingBranchSha: string;
}

export interface PrCache {
fingerprint: string;
/**
Expand Down Expand Up @@ -100,6 +106,7 @@ export interface RepoCacheData {
github?: Record<string, unknown>;
};
prComments?: Record<number, Record<string, string>>;
onboardingBranchCache?: OnboardingBranchCache;
}

export interface RepoCache {
Expand Down
49 changes: 49 additions & 0 deletions lib/workers/repository/onboarding/branch/check.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { RenovateConfig, git, mocked, partial } from '../../../../../test/util';
import { logger } from '../../../../logger';
import * as _cache from '../../../../util/cache/repository';
import { isOnboarded } from './check';

jest.mock('../../../../util/cache/repository');
jest.mock('../../../../util/git');

const cache = mocked(_cache);

describe('workers/repository/onboarding/branch/check', () => {
const config = partial<RenovateConfig>({ requireConfig: 'required' });

it('skips normal onboarding check if onboardingCache is valid', async () => {
cache.getCache.mockReturnValueOnce({
onboardingBranchCache: {
onboardingBranch: 'configure/renovate',
defaultBranchSha: 'default-sha',
onboardingBranchSha: 'onboarding-sha',
},
});
git.getBranchCommit
.mockReturnValueOnce('default-sha')
.mockReturnValueOnce('onboarding-sha');
const res = await isOnboarded(config);
expect(res).toBeFalse();
expect(logger.debug).toHaveBeenCalledWith(
'Onboarding cache is valid. Repo is not onboarded'
);
});

it('continues with normal logic if onboardingCache is invalid', async () => {
cache.getCache.mockReturnValueOnce({
onboardingBranchCache: {
onboardingBranch: 'configure/renovate',
defaultBranchSha: 'default-sha',
onboardingBranchSha: 'onboarding-sha',
},
});
git.getBranchCommit
.mockReturnValueOnce('default-sha-1')
.mockReturnValueOnce('onboarding-sha');
git.getFileList.mockResolvedValue([]);
await isOnboarded(config);
expect(logger.debug).not.toHaveBeenCalledWith(
'Onboarding cache is valid. Repo is not onboarded'
);
});
});
16 changes: 15 additions & 1 deletion lib/workers/repository/onboarding/branch/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Pr, platform } from '../../../../modules/platform';
import { ensureComment } from '../../../../modules/platform/comment';
import { getCache } from '../../../../util/cache/repository';
import { readLocalFile } from '../../../../util/fs';
import { getFileList } from '../../../../util/git';
import { getBranchCommit, getFileList } from '../../../../util/git';

async function findFile(fileName: string): Promise<boolean> {
logger.debug(`findFile(${fileName})`);
Expand Down Expand Up @@ -61,7 +61,21 @@ export async function isOnboarded(config: RenovateConfig): Promise<boolean> {
logger.debug('Config file will be ignored');
return true;
}

const cache = getCache();
const onboardingBranchCache = cache?.onboardingBranchCache;
// if onboarding cache is present and base branch has not been updated branch is not onboarded
if (
onboardingBranchCache &&
onboardingBranchCache.defaultBranchSha ===
getBranchCommit(config.defaultBranch!) &&
onboardingBranchCache.onboardingBranchSha ===
getBranchCommit(config.onboardingBranch!)
) {
logger.debug('Onboarding cache is valid. Repo is not onboarded');
return false;
}

if (cache.configFileName) {
logger.debug('Checking cached config file name');
try {
Expand Down
14 changes: 14 additions & 0 deletions lib/workers/repository/onboarding/branch/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import * as _cache from '../../../../util/cache/repository';
import type { FileAddition } from '../../../../util/git/types';
import { OnboardingState } from '../common';
import * as _config from './config';
import * as _onboardingCache from './onboarding-branch-cache';
import * as _rebase from './rebase';
import { checkOnboardingBranch } from '.';

Expand All @@ -32,12 +33,21 @@ jest.mock('../../../../util/cache/repository');
jest.mock('../../../../util/fs');
jest.mock('../../../../util/git');
jest.mock('./config');
jest.mock('./onboarding-branch-cache');

const cache = mocked(_cache);
const onboardingCache = mocked(_onboardingCache);

describe('workers/repository/onboarding/branch/index', () => {
describe('checkOnboardingBranch', () => {
let config: RenovateConfig;
const dummyCache = {
onboardingBranchCache: {
onboardingBranch: 'configure/renovate',
defaultBranchSha: 'default-sha',
onboardingBranchSha: 'onboarding-sha',
},
};

beforeEach(() => {
memCache.init();
Expand Down Expand Up @@ -168,9 +178,11 @@ describe('workers/repository/onboarding/branch/index', () => {
});

it('detects repo is onboarded via file', async () => {
cache.getCache.mockReturnValue(dummyCache);
git.getFileList.mockResolvedValueOnce(['renovate.json']);
const res = await checkOnboardingBranch(config);
expect(res.repoIsOnboarded).toBeTrue();
expect(onboardingCache.deleteOnboardingCache).toHaveBeenCalledTimes(1); // removes onboarding cache when repo is onboarded
});

it('handles removed cached file name', async () => {
Expand Down Expand Up @@ -251,6 +263,7 @@ describe('workers/repository/onboarding/branch/index', () => {
});

it('updates onboarding branch', async () => {
cache.getCache.mockReturnValue(dummyCache);
git.getFileList.mockResolvedValue(['package.json']);
platform.findPr.mockResolvedValue(null);
platform.getBranchPr.mockResolvedValueOnce(mock<Pr>());
Expand All @@ -259,6 +272,7 @@ describe('workers/repository/onboarding/branch/index', () => {
expect(res.repoIsOnboarded).toBeFalse();
expect(res.branchList).toEqual(['renovate/configure']);
expect(git.checkoutBranch).toHaveBeenCalledTimes(1);
expect(onboardingCache.setOnboardingCache).toHaveBeenCalledTimes(1); // update onboarding cache
expect(scm.commitAndPush).toHaveBeenCalledTimes(0);
});

Expand Down
27 changes: 26 additions & 1 deletion lib/workers/repository/onboarding/branch/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,21 @@ import {
} from '../../../../constants/error-messages';
import { logger } from '../../../../logger';
import { Pr, platform } from '../../../../modules/platform';
import { checkoutBranch, setGitAuthor } from '../../../../util/git';
import {
checkoutBranch,
getBranchCommit,
setGitAuthor,
} from '../../../../util/git';
import { extractAllDependencies } from '../../extract';
import { mergeRenovateConfig } from '../../init/merge';
import { OnboardingState } from '../common';
import { getOnboardingPr, isOnboarded } from './check';
import { getOnboardingConfig } from './config';
import { createOnboardingBranch } from './create';
import {
deleteOnboardingCache,
setOnboardingCache,
} from './onboarding-branch-cache';
import { rebaseOnboardingBranch } from './rebase';

export async function checkOnboardingBranch(
Expand All @@ -26,6 +34,9 @@ export async function checkOnboardingBranch(
const repoIsOnboarded = await isOnboarded(config);
if (repoIsOnboarded) {
logger.debug('Repo is onboarded');

// delete onboarding cache
deleteOnboardingCache();
return { ...config, repoIsOnboarded };
}
if (config.isFork && config.forkProcessing !== 'enabled') {
Expand All @@ -47,6 +58,13 @@ export async function checkOnboardingBranch(
{ branch: config.onboardingBranch, commit, onboarding: true },
'Branch updated'
);

// update onboarding cache
setOnboardingCache(
config.onboardingBranch!,
getBranchCommit(config.defaultBranch!)!,
commit
);
}
// istanbul ignore if
if (platform.refreshPr) {
Expand Down Expand Up @@ -78,6 +96,13 @@ export async function checkOnboardingBranch(
{ branch: onboardingBranch, commit, onboarding: true },
'Branch created'
);

// set onboarding branch cache
setOnboardingCache(
config.onboardingBranch!,
getBranchCommit(config.defaultBranch!)!,
commit
);
}
}
if (!GlobalConfig.get('dryRun')) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { mocked } from '../../../../../test/util';
import * as _cache from '../../../../util/cache/repository';
import type { RepoCacheData } from '../../../../util/cache/repository/types';
import {
deleteOnboardingCache,
setOnboardingCache,
} from './onboarding-branch-cache';

jest.mock('../../../../util/cache/repository');
const cache = mocked(_cache);

describe('workers/repository/onboarding/branch/onboarding-branch-cache', () => {
it('sets new cache', () => {
const dummyCache = {} satisfies RepoCacheData;
cache.getCache.mockReturnValueOnce(dummyCache);
setOnboardingCache('configure/renovate', 'default-sha', 'onboarding-sha');
expect(dummyCache).toEqual({
onboardingBranchCache: {
onboardingBranch: 'configure/renovate',
defaultBranchSha: 'default-sha',
onboardingBranchSha: 'onboarding-sha',
},
});
});

it('updates old cache', () => {
const dummyCache = {
onboardingBranchCache: {
onboardingBranch: 'configure/renovate',
defaultBranchSha: 'default-sha',
onboardingBranchSha: 'onboarding-sha',
},
} satisfies RepoCacheData;
cache.getCache.mockReturnValueOnce(dummyCache);
setOnboardingCache(
'configure/renovate',
'default-sha-1',
'onboarding-sha-1'
);
expect(dummyCache).toEqual({
onboardingBranchCache: {
onboardingBranch: 'configure/renovate',
defaultBranchSha: 'default-sha-1',
onboardingBranchSha: 'onboarding-sha-1',
},
});
});

it('deletes cache', () => {
const dummyCache = {
onboardingBranchCache: {
onboardingBranch: 'configure/renovate',
defaultBranchSha: 'default-sha',
onboardingBranchSha: 'onboarding-sha',
},
} satisfies RepoCacheData;
cache.getCache.mockReturnValueOnce(dummyCache);
deleteOnboardingCache();
expect(dummyCache.onboardingBranchCache).toBeUndefined();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { logger } from '../../../../logger';
import { getCache } from '../../../../util/cache/repository';

export function setOnboardingCache(
onboardingBranch: string,
defaultBranchSha: string,
onboardingBranchSha: string
): void {
const cache = getCache();
const onboardingCache = {
onboardingBranch,
defaultBranchSha,
onboardingBranchSha,
};
if (cache.onboardingBranchCache) {
logger.debug('Update Onboarding Cache');
} else {
logger.debug('Create Onboarding Cache');
}
cache.onboardingBranchCache = onboardingCache;
}

export function deleteOnboardingCache(): void {
const cache = getCache();

if (cache?.onboardingBranchCache) {
logger.debug('Delete Onboarding Cache');
delete cache.onboardingBranchCache;
}
}