From 23e2508897156b76d124a58dd617d3750f55e5cd Mon Sep 17 00:00:00 2001 From: Gabriel-Ladzaretti <97394622+Gabriel-Ladzaretti@users.noreply.github.com> Date: Tue, 20 Sep 2022 10:09:05 +0300 Subject: [PATCH] feat(code/onboarding): infrastructure for onboarding PR rebase/retry checkbox (#17673) Co-authored-by: Michael Kriese <michael.kriese@visualon.de> --- lib/modules/platform/azure/index.spec.ts | 9 ++-- lib/modules/platform/azure/index.ts | 2 +- lib/modules/platform/bitbucket/index.spec.ts | 9 ++-- lib/modules/platform/bitbucket/index.ts | 2 +- lib/modules/platform/pr-body.spec.ts | 44 ++++++++++++++++++-- lib/modules/platform/pr-body.ts | 28 +++++++++++-- lib/modules/platform/types.ts | 1 + 7 files changed, 78 insertions(+), 17 deletions(-) diff --git a/lib/modules/platform/azure/index.spec.ts b/lib/modules/platform/azure/index.spec.ts index c234df8795..08774ad666 100644 --- a/lib/modules/platform/azure/index.spec.ts +++ b/lib/modules/platform/azure/index.spec.ts @@ -1087,10 +1087,11 @@ describe('modules/platform/azure/index', () => { describe('massageMarkdown(input)', () => { it('returns updated pr body', () => { - const input = - '\n---\n\n - [ ] <!-- rebase-check --> rebase\nplus also [a link](https://github.com/foo/bar/issues/5)'; - expect(azure.massageMarkdown(input)).toMatchInlineSnapshot( - `"plus also [a link](https://github.com/foo/bar/issues/5)"` + const prBody = + '\n---\n\n - [ ] <!-- rebase-check --> rebase\n<!--renovate-config-hash:-->' + + 'plus also [a link](https://github.com/foo/bar/issues/5)'; + expect(azure.massageMarkdown(prBody)).toBe( + 'plus also [a link](https://github.com/foo/bar/issues/5)' ); }); }); diff --git a/lib/modules/platform/azure/index.ts b/lib/modules/platform/azure/index.ts index 5119106235..0730237afb 100644 --- a/lib/modules/platform/azure/index.ts +++ b/lib/modules/platform/azure/index.ts @@ -746,7 +746,7 @@ export function massageMarkdown(input: string): string { 'rename PR to start with "rebase!"' ) .replace(regEx(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), '') - .replace(regEx(/<!--renovate-debug:.*?-->/), ''); + .replace(regEx(/<!--renovate-(?:debug|config-hash):.*?-->/g), ''); } /* istanbul ignore next */ diff --git a/lib/modules/platform/bitbucket/index.spec.ts b/lib/modules/platform/bitbucket/index.spec.ts index 35aef41c28..ceb70ab7a7 100644 --- a/lib/modules/platform/bitbucket/index.spec.ts +++ b/lib/modules/platform/bitbucket/index.spec.ts @@ -996,11 +996,10 @@ describe('modules/platform/bitbucket/index', () => { describe('massageMarkdown()', () => { it('returns diff files', () => { - expect( - bitbucket.massageMarkdown( - '<details><summary>foo</summary>bar</details>text<details>' - ) - ).toMatchSnapshot(); + const prBody = + '<details><summary>foo</summary>bar</details>text<details>' + + '\n---\n\n - [ ] <!-- rebase-check --> rebase\n<!--renovate-config-hash:-->'; + expect(bitbucket.massageMarkdown(prBody)).toMatchSnapshot(); }); }); diff --git a/lib/modules/platform/bitbucket/index.ts b/lib/modules/platform/bitbucket/index.ts index b839c2ecdf..6d63ecf1a2 100644 --- a/lib/modules/platform/bitbucket/index.ts +++ b/lib/modules/platform/bitbucket/index.ts @@ -488,7 +488,7 @@ export function massageMarkdown(input: string): string { .replace(regEx(/<\/?details>/g), '') .replace(regEx(`\n---\n\n.*?<!-- rebase-check -->.*?\n`), '') .replace(regEx(/\]\(\.\.\/pull\//g), '](../../pull-requests/') - .replace(regEx(/<!--renovate-debug:.*?-->/), ''); + .replace(regEx(/<!--renovate-(?:debug|config-hash):.*?-->/g), ''); } export async function ensureIssue({ diff --git a/lib/modules/platform/pr-body.spec.ts b/lib/modules/platform/pr-body.spec.ts index 1439ee6156..89967f8a31 100644 --- a/lib/modules/platform/pr-body.spec.ts +++ b/lib/modules/platform/pr-body.spec.ts @@ -1,3 +1,4 @@ +import hasha from 'hasha'; import { getPrBodyStruct, hashBody } from './pr-body'; describe('modules/platform/pr-body', () => { @@ -47,13 +48,50 @@ describe('modules/platform/pr-body', () => { ); }); - it('returns rebaseRequested flag', () => { - expect(getPrBodyStruct('- [x] <!-- rebase-check -->')).toEqual({ - hash: '023952693e1e00a52a71b65d9b4804bca6ca9f215c20f6e029dbf420f322d541', + it('hashes an undefined body', () => { + // nullish operator branch coverage + const hash = + 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'; + expect(hashBody(undefined)).toBe(hash); + }); + + it('returns rebaseRequested=true flag', () => { + const input = '- [x] <!-- rebase-check -->'; + const hash = hashBody(input); + expect(getPrBodyStruct(input)).toEqual({ + hash, rebaseRequested: true, }); }); + it('returns rebaseRequested=false flag', () => { + const input = '- [ ] <!-- rebase-check -->'; + const hash = hashBody(input); + expect(getPrBodyStruct(input)).toEqual({ + hash, + rebaseRequested: false, + }); + }); + + it('returns rebaseRequested=undefined flag', () => { + const input = '- <!-- rebase-check -->'; + const hash = hashBody(input); + expect(getPrBodyStruct(input)).toEqual({ + hash, + }); + }); + + it('returns raw config hash', () => { + const config = '{}'; + const rawConfigHash = hasha(config, { algorithm: 'sha256' }); + const input = `<!--renovate-config-hash:${rawConfigHash}-->`; + const hash = hashBody(input); + expect(getPrBodyStruct(input)).toEqual({ + hash, + rawConfigHash, + }); + }); + it('strips reviewable section', () => { expect(getPrBodyStruct('foo<!-- Reviewable:start -->bar')).toEqual({ hash: hashBody('foo'), diff --git a/lib/modules/platform/pr-body.ts b/lib/modules/platform/pr-body.ts index 5fe70dd8dd..88f28826bc 100644 --- a/lib/modules/platform/pr-body.ts +++ b/lib/modules/platform/pr-body.ts @@ -1,3 +1,4 @@ +import is from '@sindresorhus/is'; import hasha from 'hasha'; import { logger } from '../../logger'; import { stripEmojis } from '../../util/emoji'; @@ -9,6 +10,12 @@ export const prDebugDataRe = regEx( /\n?<!--renovate-debug:(?<payload>.*?)-->\n?/ ); +const renovateConfigHashRe = regEx( + /\n?<!--renovate-config-hash:(?<payload>.*?)-->\n?/ +); + +const prCheckboxRe = regEx(/- (?<checkbox>\[[\sx]]) <!-- rebase-check -->/); + function noWhitespaceOrHeadings(input: string): string { return input.replace(regEx(/\r?\n|\r|\s|#/g), ''); } @@ -28,8 +35,12 @@ export function hashBody(body: string | undefined): string { return result; } -function isRebaseRequested(body: string | undefined): boolean { - return !!body?.includes(`- [x] <!-- rebase-check -->`); +function isRebaseRequested(body: string): boolean | undefined { + const match = prCheckboxRe.exec(body); + if (!match) { + return undefined; + } + return match.groups?.checkbox === '[x]'; } export function getRenovateDebugPayload(body: string): string | undefined { @@ -37,6 +48,11 @@ export function getRenovateDebugPayload(body: string): string | undefined { return match?.groups?.payload; } +export function getRenovateConfigHashPayload(body: string): string | undefined { + const match = renovateConfigHashRe.exec(body); + return match?.groups?.payload; +} + export function getPrBodyStruct( input: string | undefined | null ): PrBodyStruct { @@ -45,10 +61,16 @@ export function getPrBodyStruct( const result: PrBodyStruct = { hash }; const rebaseRequested = isRebaseRequested(body); - if (rebaseRequested) { + + if (!is.undefined(rebaseRequested)) { result.rebaseRequested = rebaseRequested; } + const rawConfigHash = getRenovateConfigHashPayload(body); + if (rawConfigHash) { + result.rawConfigHash = rawConfigHash; + } + const debugPayload = getRenovateDebugPayload(body); if (debugPayload) { try { diff --git a/lib/modules/platform/types.ts b/lib/modules/platform/types.ts index ff2b266f2c..56a625eab0 100644 --- a/lib/modules/platform/types.ts +++ b/lib/modules/platform/types.ts @@ -52,6 +52,7 @@ export interface PrDebugData { export interface PrBodyStruct { hash: string; + rawConfigHash?: string; rebaseRequested?: boolean; debugData?: PrDebugData; } -- GitLab