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(core/onboarding): support manual rebase/retry #17633

Merged
merged 47 commits into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
664f474
add onboarding rebase checkbox support
Gabriel-Ladzaretti Sep 5, 2022
9dd40af
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Sep 5, 2022
6d956d7
add onboarding rebase checkbox support
Gabriel-Ladzaretti Sep 5, 2022
457c8f3
Merge branch 'rebase-onboarding' of https://github.com/Gabriel-Ladzar…
Gabriel-Ladzaretti Sep 5, 2022
10cef71
massageMarkdown for other than git(Hub|Lab)
Gabriel-Ladzaretti Sep 6, 2022
a7c9611
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Sep 6, 2022
acd4bb5
update unit tests and code coverage
Gabriel-Ladzaretti Sep 6, 2022
cf01c67
Merge branch 'rebase-onboarding' of https://github.com/Gabriel-Ladzar…
Gabriel-Ladzaretti Sep 6, 2022
f455072
update unit tests
Gabriel-Ladzaretti Sep 6, 2022
7d387bc
Apply code review suggestions
Gabriel-Ladzaretti Sep 7, 2022
fde9b7c
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Sep 7, 2022
4dbf135
extracted to #17673
Gabriel-Ladzaretti Sep 7, 2022
69c1a94
Merge branch 'rebase-onboarding' of https://github.com/Gabriel-Ladzar…
Gabriel-Ladzaretti Sep 7, 2022
80aae0a
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Sep 12, 2022
5d8f463
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Sep 14, 2022
89c9ddc
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Sep 19, 2022
df76740
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Sep 20, 2022
0b6f6d4
typo fix
Gabriel-Ladzaretti Sep 20, 2022
c3b5e6d
add feature flag
Gabriel-Ladzaretti Sep 20, 2022
aa5b4b9
update tests
Gabriel-Ladzaretti Sep 21, 2022
8507988
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Sep 21, 2022
075c42e
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Sep 22, 2022
0e9aef8
Update lib/config/options/index.ts
Gabriel-Ladzaretti Sep 25, 2022
2b34f85
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Sep 26, 2022
68b74b1
branch/index.spec - remove redundant afterAll block
Gabriel-Ladzaretti Sep 26, 2022
b63b48c
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Oct 5, 2022
d024bd5
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Oct 6, 2022
0074621
Merge branch 'rebase-onboarding' of https://github.com/Gabriel-Ladzar…
Gabriel-Ladzaretti Oct 6, 2022
f1a9205
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Oct 7, 2022
8d68a66
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Oct 9, 2022
958a657
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Oct 11, 2022
97051c2
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Oct 23, 2022
114e936
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Oct 25, 2022
d1f07c2
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Oct 29, 2022
3cb92f3
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Nov 8, 2022
df421d8
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Nov 9, 2022
f339a98
use memCache to store onboarding state
Gabriel-Ladzaretti Nov 9, 2022
f0d21ea
move toSha256 to lib/util
Gabriel-Ladzaretti Nov 9, 2022
42f8e0c
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Nov 13, 2022
af4c05e
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Nov 23, 2022
67ffdf6
Merge branch 'rebase-onboarding' of https://github.com/Gabriel-Ladzar…
Gabriel-Ladzaretti Nov 23, 2022
baed10d
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Nov 25, 2022
3f28aaf
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Nov 28, 2022
7b82b1f
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Jan 8, 2023
8e8f948
Merge branch 'main' into rebase-onboarding
Gabriel-Ladzaretti Jan 8, 2023
d0e6af1
Merge branch 'main' into rebase-onboarding
rarkins Jan 11, 2023
1f34cd2
Merge branch 'main' into rebase-onboarding
rarkins Jan 11, 2023
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
2 changes: 2 additions & 0 deletions docs/usage/self-hosted-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,8 @@ Otherwise, Renovate skips onboarding a repository if it finds no dependencies in

Similarly to `onboardingBranch`, if you have an existing Renovate installation and you change `onboardingPrTitle` then it's possible that you'll get onboarding PRs for repositories that had previously closed the onboarding PR unmerged.

## onboardingRebaseCheckbox

## optimizeForDisabled

## password
Expand Down
11 changes: 11 additions & 0 deletions lib/config/options/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,17 @@ const options: RenovateOptions[] = [
globalOnly: true,
mergeable: true,
},
{
name: 'onboardingRebaseCheckbox',
description:
'Set to enable rebase/retry markdown checkbox for onboarding PRs.',
type: 'boolean',
default: false,
supportedPlatforms: ['github', 'gitlab', 'gitea'],
globalOnly: true,
experimental: true,
experimentalIssues: [17633],
},
{
name: 'includeForks',
description:
Expand Down
1 change: 1 addition & 0 deletions lib/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ export interface LegacyAdminConfig {
onboardingBranch?: string;
onboardingCommitMessage?: string;
onboardingNoDeps?: boolean;
onboardingRebaseCheckbox?: boolean;
onboardingPrTitle?: string;
onboardingConfig?: RenovateSharedConfig;
onboardingConfigFileName?: string;
Expand Down
5 changes: 5 additions & 0 deletions lib/util/hasha.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import hasha from 'hasha';

export function toSha256(input: string): string {
return hasha(input, { algorithm: 'sha256' });
}
26 changes: 21 additions & 5 deletions lib/workers/repository/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ import { ensureDependencyDashboard } from './dependency-dashboard';
import handleError from './error';
import { finaliseRepo } from './finalise';
import { initRepo } from './init';
import { OnboardingState } from './onboarding/common';
import { ensureOnboardingPr } from './onboarding/pr';
import { extractDependencies, updateRepo } from './process';
import type { ExtractResult } from './process/extract-update';
import { ProcessResult, processResult } from './result';
import { printRequestStats } from './stats';

Expand All @@ -45,10 +47,13 @@ export async function renovateRepository(
logger.debug('Using localDir: ' + localDir);
config = await initRepo(config);
addSplit('init');
const { branches, branchList, packageFiles } = await instrument(
'extract',
() => extractDependencies(config)
);
const performExtract =
config.repoIsOnboarded! ||
!config.onboardingRebaseCheckbox ||
OnboardingState.prUpdateRequested;
const { branches, branchList, packageFiles } = performExtract
? await instrument('extract', () => extractDependencies(config))
: emptyExtract(config);
if (
GlobalConfig.get('dryRun') !== 'lookup' &&
GlobalConfig.get('dryRun') !== 'extract'
Expand All @@ -63,7 +68,9 @@ export async function renovateRepository(
);
setMeta({ repository: config.repository });
addSplit('update');
await setBranchCache(branches);
if (performExtract) {
await setBranchCache(branches); // update branch cache if performed extraction
rarkins marked this conversation as resolved.
Show resolved Hide resolved
}
if (res === 'automerged') {
if (canRetry) {
logger.info('Renovating repository again after automerge result');
Expand Down Expand Up @@ -105,3 +112,12 @@ export async function renovateRepository(
logger.info({ cloned, durationMs: splits.total }, 'Repository finished');
return repoResult;
}

// istanbul ignore next: renovateRepository is ignored
viceice marked this conversation as resolved.
Show resolved Hide resolved
function emptyExtract(config: RenovateConfig): ExtractResult {
return {
branches: [],
branchList: [config.onboardingBranch!], // to prevent auto closing
packageFiles: {},
};
}
121 changes: 101 additions & 20 deletions lib/workers/repository/onboarding/branch/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,17 @@ import {
platform,
} from '../../../../../test/util';
import { configFileNames } from '../../../../config/app-strings';
import { GlobalConfig } from '../../../../config/global';
import {
REPOSITORY_FORKED,
REPOSITORY_NO_PACKAGE_FILES,
} from '../../../../constants/error-messages';
import { logger } from '../../../../logger';
import type { Pr } from '../../../../modules/platform';
import * as memCache from '../../../../util/cache/memory';
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 _rebase from './rebase';
import { checkOnboardingBranch } from '.';
Expand All @@ -36,9 +39,11 @@ describe('workers/repository/onboarding/branch/index', () => {
let config: RenovateConfig;

beforeEach(() => {
memCache.init();
jest.resetAllMocks();
config = getConfig();
config.repository = 'some/repo';
OnboardingState.prUpdateRequested = false;
viceice marked this conversation as resolved.
Show resolved Hide resolved
git.getFileList.mockResolvedValue([]);
cache.getCache.mockReturnValue({});
});
Expand All @@ -63,26 +68,36 @@ describe('workers/repository/onboarding/branch/index', () => {
);
});

it('has default onboarding config', async () => {
configModule.getOnboardingConfig.mockResolvedValue(
config.onboardingConfig
);
configModule.getOnboardingConfigContents.mockResolvedValue(
'{\n' +
' "$schema": "https://docs.renovatebot.com/renovate-schema.json"\n' +
'}\n'
);
git.getFileList.mockResolvedValue(['package.json']);
fs.readLocalFile.mockResolvedValue('{}');
await checkOnboardingBranch(config);
const file = git.commitFiles.mock.calls[0][0].files[0] as FileAddition;
const contents = file.contents?.toString();
expect(contents).toBeJsonString();
// TODO #7154
expect(JSON.parse(contents!)).toEqual({
$schema: 'https://docs.renovatebot.com/renovate-schema.json',
});
});
it.each`
checkboxEnabled | expected
${true} | ${true}
${false} | ${false}
`(
'has default onboarding config' +
'(config.onboardingRebaseCheckbox="$checkboxEnabled")',
async ({ checkboxEnabled, expected }) => {
config.onboardingRebaseCheckbox = checkboxEnabled;
configModule.getOnboardingConfig.mockResolvedValue(
config.onboardingConfig
);
configModule.getOnboardingConfigContents.mockResolvedValue(
'{\n' +
' "$schema": "https://docs.renovatebot.com/renovate-schema.json"\n' +
'}\n'
);
git.getFileList.mockResolvedValue(['package.json']);
fs.readLocalFile.mockResolvedValue('{}');
await checkOnboardingBranch(config);
const file = git.commitFiles.mock.calls[0][0].files[0] as FileAddition;
const contents = file.contents?.toString();
expect(contents).toBeJsonString();
// TODO #7154
expect(JSON.parse(contents!)).toEqual({
$schema: 'https://docs.renovatebot.com/renovate-schema.json',
});
expect(OnboardingState.prUpdateRequested).toBe(expected);
}
);

it('uses discovered onboarding config', async () => {
configModule.getOnboardingConfig.mockResolvedValue({
Expand Down Expand Up @@ -244,5 +259,71 @@ describe('workers/repository/onboarding/branch/index', () => {
expect(git.checkoutBranch).toHaveBeenCalledTimes(1);
expect(git.commitFiles).toHaveBeenCalledTimes(0);
});

describe('tests onboarding rebase/retry checkbox handling', () => {
beforeEach(() => {
GlobalConfig.set({ platform: 'github' });
config.onboardingRebaseCheckbox = true;
OnboardingState.prUpdateRequested = false;
git.getFileList.mockResolvedValueOnce(['package.json']);
platform.findPr.mockResolvedValueOnce(null);
rebase.rebaseOnboardingBranch.mockResolvedValueOnce(null);
});

it('detects unsupported platfom', async () => {
const pl = 'bitbucket';
GlobalConfig.set({ platform: pl });
platform.getBranchPr.mockResolvedValueOnce(mock<Pr>({}));

await checkOnboardingBranch(config);

expect(logger.trace).toHaveBeenCalledWith(
`Platform '${pl}' does not support extended markdown`
);
expect(OnboardingState.prUpdateRequested).toBeTrue();
expect(git.checkoutBranch).toHaveBeenCalledTimes(1);
expect(git.commitFiles).toHaveBeenCalledTimes(0);
});

it('detects missing rebase checkbox', async () => {
const pr = { bodyStruct: { rebaseRequested: undefined } };
platform.getBranchPr.mockResolvedValueOnce(mock<Pr>(pr));

await checkOnboardingBranch(config);

expect(logger.debug).toHaveBeenCalledWith(
`No rebase checkbox was found in the onboarding PR`
);
expect(OnboardingState.prUpdateRequested).toBeTrue();
expect(git.checkoutBranch).toHaveBeenCalledTimes(1);
expect(git.commitFiles).toHaveBeenCalledTimes(0);
});

it('detects manual pr update requested', async () => {
const pr = { bodyStruct: { rebaseRequested: true } };
platform.getBranchPr.mockResolvedValueOnce(mock<Pr>(pr));

await checkOnboardingBranch(config);

expect(logger.debug).toHaveBeenCalledWith(
`Manual onboarding PR update requested`
);
expect(OnboardingState.prUpdateRequested).toBeTrue();
``;
expect(git.checkoutBranch).toHaveBeenCalledTimes(1);
expect(git.commitFiles).toHaveBeenCalledTimes(0);
});

it('handles unchecked rebase checkbox', async () => {
const pr = { bodyStruct: { rebaseRequested: false } };
platform.getBranchPr.mockResolvedValueOnce(mock<Pr>(pr));

await checkOnboardingBranch(config);

expect(OnboardingState.prUpdateRequested).toBeFalse();
expect(git.checkoutBranch).toHaveBeenCalledTimes(1);
expect(git.commitFiles).toHaveBeenCalledTimes(0);
});
});
});
});
29 changes: 26 additions & 3 deletions lib/workers/repository/onboarding/branch/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import is from '@sindresorhus/is';
import { mergeChildConfig } from '../../../../config';
import { GlobalConfig } from '../../../../config/global';
import type { RenovateConfig } from '../../../../config/types';
Expand All @@ -6,10 +7,11 @@ import {
REPOSITORY_NO_PACKAGE_FILES,
} from '../../../../constants/error-messages';
import { logger } from '../../../../logger';
import { platform } from '../../../../modules/platform';
import { Pr, platform } from '../../../../modules/platform';
import { checkoutBranch, 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';
Expand All @@ -34,8 +36,12 @@ export async function checkOnboardingBranch(
setGitAuthor(config.gitAuthor);
const onboardingPr = await getOnboardingPr(config);
if (onboardingPr) {
if (config.onboardingRebaseCheckbox) {
handleOnboardingManualRebase(onboardingPr);
}
logger.debug('Onboarding PR already exists');
const commit = await rebaseOnboardingBranch(config);
const { rawConfigHash } = onboardingPr.bodyStruct ?? {};
const commit = await rebaseOnboardingBranch(config, rawConfigHash);
if (commit) {
logger.info(
{ branch: config.onboardingBranch, commit, onboarding: true },
Expand All @@ -44,7 +50,6 @@ export async function checkOnboardingBranch(
}
// istanbul ignore if
if (platform.refreshPr) {
// TODO #7154
await platform.refreshPr(onboardingPr.number);
}
} else {
Expand All @@ -62,6 +67,9 @@ export async function checkOnboardingBranch(
}
}
logger.debug('Need to create onboarding PR');
if (config.onboardingRebaseCheckbox) {
OnboardingState.prUpdateRequested = true;
}
const commit = await createOnboardingBranch(mergedConfig);
// istanbul ignore if
if (commit) {
Expand All @@ -80,3 +88,18 @@ export async function checkOnboardingBranch(
const branchList = [onboardingBranch!];
return { ...config, repoIsOnboarded, onboardingBranch, branchList };
}

function handleOnboardingManualRebase(onboardingPr: Pr): void {
const pl = GlobalConfig.get('platform')!;
const { rebaseRequested } = onboardingPr.bodyStruct ?? {};
if (!['github', 'gitlab', 'gitea'].includes(pl)) {
logger.trace(`Platform '${pl}' does not support extended markdown`);
OnboardingState.prUpdateRequested = true;
} else if (is.nullOrUndefined(rebaseRequested)) {
logger.debug('No rebase checkbox was found in the onboarding PR');
OnboardingState.prUpdateRequested = true;
} else if (rebaseRequested) {
logger.debug('Manual onboarding PR update requested');
OnboardingState.prUpdateRequested = true;
}
}
Loading