From 224d5e771701d111785bb892d8824275c6fe18e0 Mon Sep 17 00:00:00 2001 From: Gabriel-Ladzaretti <97394622+Gabriel-Ladzaretti@users.noreply.github.com> Date: Mon, 16 May 2022 13:20:31 +0300 Subject: [PATCH] feat(core/dashboard): include list of detected package files (#15418) --- .../master-issue_with_2_PR_closed_ignored.txt | 5 + .../master-issue_with_2_PR_edited.txt | 5 + .../master-issue_with_3_PR_in_approval.txt | 5 + .../master-issue_with_3_PR_in_progress.txt | 5 + .../__fixtures__/master-issue_with_8_PR.txt | 5 + .../__fixtures__/package-files.json | 275 +++++++++++++++++ .../dependency-dashboard.spec.ts.snap | 278 ++++++++++++++++++ .../repository/dependency-dashboard.spec.ts | 115 +++++++- .../repository/dependency-dashboard.ts | 3 + lib/workers/repository/finalise/index.ts | 2 + lib/workers/repository/package-files.ts | 66 +++++ lib/workers/repository/process/fetch.ts | 2 + 12 files changed, 758 insertions(+), 8 deletions(-) create mode 100644 lib/workers/repository/__fixtures__/package-files.json create mode 100644 lib/workers/repository/package-files.ts diff --git a/lib/workers/repository/__fixtures__/master-issue_with_2_PR_closed_ignored.txt b/lib/workers/repository/__fixtures__/master-issue_with_2_PR_closed_ignored.txt index fae1e9ad07..fcf12bce59 100644 --- a/lib/workers/repository/__fixtures__/master-issue_with_2_PR_closed_ignored.txt +++ b/lib/workers/repository/__fixtures__/master-issue_with_2_PR_closed_ignored.txt @@ -7,3 +7,8 @@ These are blocked by an existing closed PR and will not be recreated unless you - [ ] <!-- recreate-branch=branchName1 -->pr1 - [ ] <!-- recreate-branch=branchName2 -->pr2 (`dep2`, `dep3`) +## Detected dependencies + +None detected + + diff --git a/lib/workers/repository/__fixtures__/master-issue_with_2_PR_edited.txt b/lib/workers/repository/__fixtures__/master-issue_with_2_PR_edited.txt index 793b2717ad..c1dd60e3ff 100644 --- a/lib/workers/repository/__fixtures__/master-issue_with_2_PR_edited.txt +++ b/lib/workers/repository/__fixtures__/master-issue_with_2_PR_edited.txt @@ -7,3 +7,8 @@ These updates have been manually edited so Renovate will no longer make changes. - [ ] <!-- rebase-branch=branchName1 -->[pr1](../pull/1) - [ ] <!-- rebase-branch=branchName2 -->[pr2](../pull/2) (`dep2`, `dep3`) +## Detected dependencies + +None detected + + diff --git a/lib/workers/repository/__fixtures__/master-issue_with_3_PR_in_approval.txt b/lib/workers/repository/__fixtures__/master-issue_with_3_PR_in_approval.txt index 10a26e9b56..3c6275a9c6 100644 --- a/lib/workers/repository/__fixtures__/master-issue_with_3_PR_in_approval.txt +++ b/lib/workers/repository/__fixtures__/master-issue_with_3_PR_in_approval.txt @@ -14,3 +14,8 @@ These updates await pending status checks. To force their creation now, click th - [ ] <!-- approvePr-branch=branchName4 -->pr4 +## Detected dependencies + +None detected + + diff --git a/lib/workers/repository/__fixtures__/master-issue_with_3_PR_in_progress.txt b/lib/workers/repository/__fixtures__/master-issue_with_3_PR_in_progress.txt index cb6da6175d..e403823a1e 100644 --- a/lib/workers/repository/__fixtures__/master-issue_with_3_PR_in_progress.txt +++ b/lib/workers/repository/__fixtures__/master-issue_with_3_PR_in_progress.txt @@ -9,3 +9,8 @@ These updates have all been created already. Click a checkbox below to force a r - [ ] <!-- rebase-branch=branchName3 -->[pr3](../pull/3) - [ ] <!-- rebase-all-open-prs -->**Click on this checkbox to rebase all open PRs at once** +## Detected dependencies + +None detected + + diff --git a/lib/workers/repository/__fixtures__/master-issue_with_8_PR.txt b/lib/workers/repository/__fixtures__/master-issue_with_8_PR.txt index b8803a5575..c34516c0d3 100644 --- a/lib/workers/repository/__fixtures__/master-issue_with_8_PR.txt +++ b/lib/workers/repository/__fixtures__/master-issue_with_8_PR.txt @@ -34,3 +34,8 @@ These updates await pending status checks before automerging. Click on a checkbo - [ ] <!-- approvePr-branch=branchName9 -->pr9 +## Detected dependencies + +None detected + + diff --git a/lib/workers/repository/__fixtures__/package-files.json b/lib/workers/repository/__fixtures__/package-files.json new file mode 100644 index 0000000000..ae932d13fc --- /dev/null +++ b/lib/workers/repository/__fixtures__/package-files.json @@ -0,0 +1,275 @@ +{ + "dockerfile": [ + { + "packageFile": "Dockerfile", + "deps": [ + { + "depName": "ubuntu", + "currentValue": "20.04", + "replaceString": "ubuntu:20.04", + "autoReplaceStringTemplate": "{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", + "datasource": "docker", + "versioning": "ubuntu", + "depType": "final", + "depIndex": 0, + "updates": [ + { + "bucket": "major", + "newVersion": "jammy", + "newValue": "22.04", + "newMajor": 22, + "newMinor": 4, + "updateType": "major", + "branchName": "renovate/ubuntu-22.x" + } + ], + "warnings": [], + "currentVersion": "20.04", + "isSingleVersion": true, + "fixedVersion": "20.04" + } + ] + } + ], + "npm": [ + { + "packageFile": "package.json", + "deps": [ + { + "depType": "dependencies", + "depName": "cookie-parser", + "currentValue": "^1.4.5", + "datasource": "npm", + "prettyDepType": "dependency", + "depIndex": 0, + "updates": [], + "warnings": [], + "versioning": "npm", + "sourceUrl": "https://github.com/expressjs/cookie-parser", + "currentVersion": "1.4.6" + }, + { + "depType": "dependencies", + "depName": "express", + "currentValue": "~4.17.1", + "datasource": "npm", + "prettyDepType": "dependency", + "depIndex": 1, + "updates": [ + { + "bucket": "non-major", + "newVersion": "4.18.1", + "newValue": "~4.18.0", + "releaseTimestamp": "2022-04-29T19:33:40.441Z", + "newMajor": 4, + "newMinor": 18, + "updateType": "minor", + "isRange": true, + "branchName": "renovate/express-4.x" + } + ], + "warnings": [], + "versioning": "npm", + "sourceUrl": "https://github.com/expressjs/express", + "homepage": "http://expressjs.com/", + "currentVersion": "4.17.3", + "isSingleVersion": false + }, + { + "depType": "dependencies", + "depName": "express-handlebars", + "currentValue": ">=5.3.4", + "datasource": "npm", + "prettyDepType": "dependency", + "depIndex": 2, + "updates": [], + "warnings": [], + "versioning": "npm", + "sourceUrl": "https://github.com/express-handlebars/express-handlebars", + "currentVersion": "6.0.5" + }, + { + "depType": "dependencies", + "depName": "geoip-lite", + "currentValue": "1.4.*", + "datasource": "npm", + "prettyDepType": "dependency", + "depIndex": 3, + "updates": [], + "warnings": [], + "versioning": "npm", + "sourceUrl": "https://github.com/geoip-lite/node-geoip", + "currentVersion": "1.4.5" + }, + { + "depType": "dependencies", + "depName": "nodemailer", + "currentValue": "6.7.0", + "datasource": "npm", + "prettyDepType": "dependency", + "depIndex": 4, + "updates": [ + { + "bucket": "non-major", + "newVersion": "6.7.4", + "newValue": "6.7.4", + "releaseTimestamp": "2022-04-28T21:51:54.336Z", + "newMajor": 6, + "newMinor": 7, + "updateType": "patch", + "branchName": "renovate/nodemailer-6.x" + } + ], + "warnings": [], + "versioning": "npm", + "sourceUrl": "https://github.com/nodemailer/nodemailer", + "homepage": "https://nodemailer.com/", + "currentVersion": "6.7.0", + "isSingleVersion": true, + "fixedVersion": "6.7.0" + }, + { + "depType": "dependencies", + "depName": "redis", + "currentValue": "3.1.2-3.4.0", + "datasource": "npm", + "prettyDepType": "dependency", + "depIndex": 5, + "updates": [ + { + "bucket": "rollback", + "newMajor": 3, + "newValue": "3.1.1", + "newVersion": "3.1.1", + "updateType": "rollback", + "branchName": "renovate/redis-rollback" + }, + { + "bucket": "non-major", + "newVersion": "3.1.2", + "newValue": "3.1.2", + "releaseTimestamp": "2021-04-20T22:26:05.946Z", + "newMajor": 3, + "newMinor": 1, + "updateType": "patch", + "branchName": "renovate/redis-3.x" + }, + { + "bucket": "major", + "newVersion": "4.1.0", + "newValue": "4.1.0", + "releaseTimestamp": "2022-05-02T16:04:07.111Z", + "newMajor": 4, + "newMinor": 1, + "updateType": "major", + "branchName": "renovate/redis-4.x" + } + ], + "warnings": [], + "versioning": "npm", + "sourceUrl": "https://github.com/redis/node-redis", + "currentVersion": "3.1.2-3.4.0", + "isSingleVersion": true, + "fixedVersion": "3.1.2-3.4.0" + }, + { + "depType": "devDependencies", + "depName": "dotenv", + "currentValue": "10.0.0", + "datasource": "npm", + "prettyDepType": "devDependency", + "depIndex": 6, + "updates": [ + { + "bucket": "major", + "newVersion": "16.0.0", + "newValue": "16.0.0", + "releaseTimestamp": "2022-02-02T21:26:07.108Z", + "newMajor": 16, + "newMinor": 0, + "updateType": "major", + "branchName": "renovate/dotenv-16.x" + } + ], + "warnings": [], + "versioning": "npm", + "sourceUrl": "https://github.com/motdotla/dotenv", + "currentVersion": "10.0.0", + "isSingleVersion": true, + "fixedVersion": "10.0.0" + }, + { + "depType": "devDependencies", + "depName": "nodemon", + "currentValue": "2.0.14", + "datasource": "npm", + "prettyDepType": "devDependency", + "depIndex": 7, + "updates": [ + { + "bucket": "non-major", + "newVersion": "2.0.16", + "newValue": "2.0.16", + "releaseTimestamp": "2022-04-29T10:09:23.199Z", + "newMajor": 2, + "newMinor": 0, + "updateType": "patch", + "branchName": "renovate/nodemon-2.x" + } + ], + "warnings": [], + "versioning": "npm", + "sourceUrl": "https://github.com/remy/nodemon", + "homepage": "https://nodemon.io", + "currentVersion": "2.0.14", + "isSingleVersion": true, + "fixedVersion": "2.0.14" + } + ], + "packageJsonType": "app", + "managerData": { + "yarnZeroInstall": false + }, + "skipInstalls": true, + "constraints": {} + } + ], + "poetry": [ + { + "packageFile": "pyproject.toml", + "deps": [ + { + "depName": "six", + "depType": "dependencies", + "currentValue": "<=1.3.0", + "managerData": { + "nestedVersion": false + }, + "datasource": "pypi", + "versioning": "pep440", + "depIndex": 0, + "updates": [ + { + "bucket": "non-major", + "newVersion": "1.16.0", + "newValue": "<=1.16.0", + "releaseTimestamp": "2021-05-05T14:18:17.000Z", + "newMajor": 1, + "newMinor": 16, + "updateType": "minor", + "isRange": true, + "branchName": "renovate/six-1.x" + } + ], + "warnings": [], + "sourceUrl": "https://github.com/benjaminp/six", + "currentVersion": "1.3.0", + "isSingleVersion": false + } + ], + "constraints": { + "python": "^3.10" + } + } + ] +} diff --git a/lib/workers/repository/__snapshots__/dependency-dashboard.spec.ts.snap b/lib/workers/repository/__snapshots__/dependency-dashboard.spec.ts.snap index 94ce71462f..cfd52ab4d7 100644 --- a/lib/workers/repository/__snapshots__/dependency-dashboard.spec.ts.snap +++ b/lib/workers/repository/__snapshots__/dependency-dashboard.spec.ts.snap @@ -1,5 +1,263 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`workers/repository/dependency-dashboard ensureDependencyDashboard() checks detected dependencies section multi base branch repo add detected dependencies to the Dependency Dashboard body 1`] = ` +"This issue provides visibility into Renovate updates and their statuses. [Learn more](https://docs.renovatebot.com/key-concepts/dashboard/) + +This repository currently has no open or pending branches. + +## Detected dependencies + +<details><summary>Branch main +</summary> + + +<ul><details><summary>dockerfile</summary> + +<ul><details><summary>Dockerfile</summary> + + - \`ubuntu 20.04\` + +</details></ul> +</details></ul> +<ul><details><summary>npm</summary> + +<ul><details><summary>package.json</summary> + + - \`cookie-parser ^1.4.5\` + - \`express ~4.17.1\` + - \`express-handlebars >=5.3.4\` + - \`geoip-lite 1.4.*\` + - \`nodemailer 6.7.0\` + - \`redis 3.1.2-3.4.0\` + - \`dotenv 10.0.0\` + - \`nodemon 2.0.14\` + +</details></ul> +</details></ul> +<ul><details><summary>poetry</summary> + +<ul><details><summary>pyproject.toml</summary> + + - \`six <=1.3.0\` + +</details></ul> +</details></ul> +</details> + +<details><summary>Branch dev +</summary> + + +<ul><details><summary>dockerfile</summary> + +<ul><details><summary>Dockerfile</summary> + + - \`ubuntu 20.04\` + +</details></ul> +</details></ul> +<ul><details><summary>npm</summary> + +<ul><details><summary>package.json</summary> + + - \`cookie-parser ^1.4.5\` + - \`express ~4.17.1\` + - \`express-handlebars >=5.3.4\` + - \`geoip-lite 1.4.*\` + - \`nodemailer 6.7.0\` + - \`redis 3.1.2-3.4.0\` + - \`dotenv 10.0.0\` + - \`nodemon 2.0.14\` + +</details></ul> +</details></ul> +<ul><details><summary>poetry</summary> + +<ul><details><summary>pyproject.toml</summary> + + - \`six <=1.3.0\` + +</details></ul> +</details></ul> +</details> + +" +`; + +exports[`workers/repository/dependency-dashboard ensureDependencyDashboard() checks detected dependencies section multi base branch repo show default message in issues body when packageFiles is empty 1`] = ` +"This issue provides visibility into Renovate updates and their statuses. [Learn more](https://docs.renovatebot.com/key-concepts/dashboard/) + +This repository currently has no open or pending branches. + +## Detected dependencies + +<details><summary>Branch main +</summary> + +None detected + + +</details> + +<details><summary>Branch dev +</summary> + + +<ul><details><summary>dockerfile</summary> + +<ul><details><summary>Dockerfile</summary> + + - \`ubuntu 20.04\` + +</details></ul> +</details></ul> +<ul><details><summary>npm</summary> + +<ul><details><summary>package.json</summary> + + - \`cookie-parser ^1.4.5\` + - \`express ~4.17.1\` + - \`express-handlebars >=5.3.4\` + - \`geoip-lite 1.4.*\` + - \`nodemailer 6.7.0\` + - \`redis 3.1.2-3.4.0\` + - \`dotenv 10.0.0\` + - \`nodemon 2.0.14\` + +</details></ul> +</details></ul> +<ul><details><summary>poetry</summary> + +<ul><details><summary>pyproject.toml</summary> + + - \`six <=1.3.0\` + +</details></ul> +</details></ul> +</details> + +" +`; + +exports[`workers/repository/dependency-dashboard ensureDependencyDashboard() checks detected dependencies section multi base branch repo show default message in issues body when when packageFiles is null 1`] = ` +"This issue provides visibility into Renovate updates and their statuses. [Learn more](https://docs.renovatebot.com/key-concepts/dashboard/) + +This repository currently has no open or pending branches. + +## Detected dependencies + +<details><summary>Branch main +</summary> + +None detected + + +</details> + +<details><summary>Branch dev +</summary> + + +<ul><details><summary>dockerfile</summary> + +<ul><details><summary>Dockerfile</summary> + + - \`ubuntu 20.04\` + +</details></ul> +</details></ul> +<ul><details><summary>npm</summary> + +<ul><details><summary>package.json</summary> + + - \`cookie-parser ^1.4.5\` + - \`express ~4.17.1\` + - \`express-handlebars >=5.3.4\` + - \`geoip-lite 1.4.*\` + - \`nodemailer 6.7.0\` + - \`redis 3.1.2-3.4.0\` + - \`dotenv 10.0.0\` + - \`nodemon 2.0.14\` + +</details></ul> +</details></ul> +<ul><details><summary>poetry</summary> + +<ul><details><summary>pyproject.toml</summary> + + - \`six <=1.3.0\` + +</details></ul> +</details></ul> +</details> + +" +`; + +exports[`workers/repository/dependency-dashboard ensureDependencyDashboard() checks detected dependencies section single base branch repo add detected dependencies to the Dependency Dashboard body 1`] = ` +"This issue provides visibility into Renovate updates and their statuses. [Learn more](https://docs.renovatebot.com/key-concepts/dashboard/) + +This repository currently has no open or pending branches. + +## Detected dependencies + +<details><summary>dockerfile</summary> + +<ul><details><summary>Dockerfile</summary> + + - \`ubuntu 20.04\` + +</details></ul> +</details><details><summary>npm</summary> + +<ul><details><summary>package.json</summary> + + - \`cookie-parser ^1.4.5\` + - \`express ~4.17.1\` + - \`express-handlebars >=5.3.4\` + - \`geoip-lite 1.4.*\` + - \`nodemailer 6.7.0\` + - \`redis 3.1.2-3.4.0\` + - \`dotenv 10.0.0\` + - \`nodemon 2.0.14\` + +</details></ul> +</details><details><summary>poetry</summary> + +<ul><details><summary>pyproject.toml</summary> + + - \`six <=1.3.0\` + +</details></ul> +</details>" +`; + +exports[`workers/repository/dependency-dashboard ensureDependencyDashboard() checks detected dependencies section single base branch repo show default message in issues body when packageFiles is empty 1`] = ` +"This issue provides visibility into Renovate updates and their statuses. [Learn more](https://docs.renovatebot.com/key-concepts/dashboard/) + +This repository currently has no open or pending branches. + +## Detected dependencies + +None detected + + +" +`; + +exports[`workers/repository/dependency-dashboard ensureDependencyDashboard() checks detected dependencies section single base branch repo show default message in issues body when when packageFiles is null 1`] = ` +"This issue provides visibility into Renovate updates and their statuses. [Learn more](https://docs.renovatebot.com/key-concepts/dashboard/) + +This repository currently has no open or pending branches. + +## Detected dependencies + +None detected + + +" +`; + exports[`workers/repository/dependency-dashboard ensureDependencyDashboard() contains logged problems 1`] = ` "This issue provides visibility into Renovate updates and their statuses. [Learn more](https://docs.renovatebot.com/key-concepts/dashboard/) @@ -19,6 +277,11 @@ These updates await pending status checks. To force their creation now, click th - [ ] <!-- approvePr-branch=branchName1 -->pr1 +## Detected dependencies + +None detected + + " `; @@ -27,6 +290,11 @@ exports[`workers/repository/dependency-dashboard ensureDependencyDashboard() ope This repository currently has no open or pending branches. +## Detected dependencies + +None detected + + --- And this is a footer " @@ -37,6 +305,11 @@ exports[`workers/repository/dependency-dashboard ensureDependencyDashboard() ope This repository currently has no open or pending branches. +## Detected dependencies + +None detected + + --- And this is a footer for repository:test " @@ -58,5 +331,10 @@ These updates are awaiting their schedule. Click on a checkbox to get an update - [x] <!-- unschedule-branch=branchName3 -->pr3 +## Detected dependencies + +None detected + + " `; diff --git a/lib/workers/repository/dependency-dashboard.spec.ts b/lib/workers/repository/dependency-dashboard.spec.ts index 56338e0279..2781334215 100644 --- a/lib/workers/repository/dependency-dashboard.spec.ts +++ b/lib/workers/repository/dependency-dashboard.spec.ts @@ -1,9 +1,9 @@ import { ERROR, WARN } from 'bunyan'; import { mock } from 'jest-mock-extended'; +import { Fixtures } from '../../../test/fixtures'; import { RenovateConfig, getConfig, - loadFixture, logger, platform, } from '../../../test/util'; @@ -12,6 +12,7 @@ import { PlatformId } from '../../constants'; import type { Platform } from '../../modules/platform'; import { BranchConfig, BranchResult, BranchUpgradeConfig } from '../types'; import * as dependencyDashboard from './dependency-dashboard'; +import { PackageFiles } from './package-files'; type PrUpgrade = BranchUpgradeConfig; @@ -27,7 +28,6 @@ beforeEach(() => { async function dryRun( branches: BranchConfig[], - platform: jest.Mocked<Platform>, ensureIssueClosingCalls = 0, ensureIssueCalls = 0 @@ -50,7 +50,7 @@ describe('workers/repository/dependency-dashboard', () => { title: '', number: 1, body: - loadFixture('master-issue_with_8_PR.txt').replace('- [ ]', '- [x]') + + Fixtures.get('master-issue_with_8_PR.txt').replace('- [ ]', '- [x]') + '\n\n - [x] <!-- rebase-all-open-prs -->', }); await dependencyDashboard.readDashboardBody(conf); @@ -68,6 +68,7 @@ describe('workers/repository/dependency-dashboard', () => { describe('ensureDependencyDashboard()', () => { beforeEach(() => { + PackageFiles.add('main', null); GlobalConfig.reset(); }); @@ -266,7 +267,7 @@ describe('workers/repository/dependency-dashboard', () => { config.dependencyDashboardTitle ); expect(platform.ensureIssue.mock.calls[0][0].body).toBe( - loadFixture('master-issue_with_8_PR.txt') + Fixtures.get('master-issue_with_8_PR.txt') ); // same with dry run @@ -303,7 +304,7 @@ describe('workers/repository/dependency-dashboard', () => { config.dependencyDashboardTitle ); expect(platform.ensureIssue.mock.calls[0][0].body).toBe( - loadFixture('master-issue_with_2_PR_edited.txt') + Fixtures.get('master-issue_with_2_PR_edited.txt') ); // same with dry run @@ -348,7 +349,7 @@ describe('workers/repository/dependency-dashboard', () => { config.dependencyDashboardTitle ); expect(platform.ensureIssue.mock.calls[0][0].body).toBe( - loadFixture('master-issue_with_3_PR_in_progress.txt') + Fixtures.get('master-issue_with_3_PR_in_progress.txt') ); // same with dry run @@ -383,7 +384,7 @@ describe('workers/repository/dependency-dashboard', () => { config.dependencyDashboardTitle ); expect(platform.ensureIssue.mock.calls[0][0].body).toBe( - loadFixture('master-issue_with_2_PR_closed_ignored.txt') + Fixtures.get('master-issue_with_2_PR_closed_ignored.txt') ); // same with dry run @@ -433,7 +434,7 @@ describe('workers/repository/dependency-dashboard', () => { config.dependencyDashboardTitle ); expect(platform.ensureIssue.mock.calls[0][0].body).toBe( - loadFixture('master-issue_with_3_PR_in_approval.txt') + Fixtures.get('master-issue_with_3_PR_in_approval.txt') ); // same with dry run @@ -554,5 +555,103 @@ describe('workers/repository/dependency-dashboard', () => { // same with dry run await dryRun(branches, platform); }); + + describe('checks detected dependencies section', () => { + const packageFiles = Fixtures.getJson('./package-files.json'); + let config: RenovateConfig; + + beforeAll(() => { + GlobalConfig.reset(); + config = getConfig(); + config.dependencyDashboard = true; + }); + + describe('single base branch repo', () => { + beforeEach(() => { + PackageFiles.add('main', packageFiles); + }); + + afterEach(() => { + PackageFiles.clear(); + }); + + it('add detected dependencies to the Dependency Dashboard body', async () => { + const branches: BranchConfig[] = []; + await dependencyDashboard.ensureDependencyDashboard(config, branches); + expect(platform.ensureIssue).toHaveBeenCalledTimes(1); + expect(platform.ensureIssue.mock.calls[0][0].body).toMatchSnapshot(); + + // same with dry run + await dryRun(branches, platform); + }); + + it('show default message in issues body when packageFiles is empty', async () => { + const branches: BranchConfig[] = []; + PackageFiles.clear(); + PackageFiles.add('main', {}); + await dependencyDashboard.ensureDependencyDashboard(config, branches); + expect(platform.ensureIssue).toHaveBeenCalledTimes(1); + expect(platform.ensureIssue.mock.calls[0][0].body).toMatchSnapshot(); + + // same with dry run + await dryRun(branches, platform); + }); + + it('show default message in issues body when when packageFiles is null', async () => { + const branches: BranchConfig[] = []; + PackageFiles.clear(); + PackageFiles.add('main', null); + await dependencyDashboard.ensureDependencyDashboard(config, branches); + expect(platform.ensureIssue).toHaveBeenCalledTimes(1); + expect(platform.ensureIssue.mock.calls[0][0].body).toMatchSnapshot(); + + // same with dry run + await dryRun(branches, platform); + }); + }); + + describe('multi base branch repo', () => { + beforeEach(() => { + PackageFiles.add('main', packageFiles); + PackageFiles.add('dev', packageFiles); + }); + + afterEach(() => { + PackageFiles.clear(); + }); + + it('add detected dependencies to the Dependency Dashboard body', async () => { + const branches: BranchConfig[] = []; + await dependencyDashboard.ensureDependencyDashboard(config, branches); + expect(platform.ensureIssue).toHaveBeenCalledTimes(1); + expect(platform.ensureIssue.mock.calls[0][0].body).toMatchSnapshot(); + + // same with dry run + await dryRun(branches, platform); + }); + + it('show default message in issues body when packageFiles is empty', async () => { + const branches: BranchConfig[] = []; + PackageFiles.add('main', {}); + await dependencyDashboard.ensureDependencyDashboard(config, branches); + expect(platform.ensureIssue).toHaveBeenCalledTimes(1); + expect(platform.ensureIssue.mock.calls[0][0].body).toMatchSnapshot(); + + // same with dry run + await dryRun(branches, platform); + }); + + it('show default message in issues body when when packageFiles is null', async () => { + const branches: BranchConfig[] = []; + PackageFiles.add('main', null); + await dependencyDashboard.ensureDependencyDashboard(config, branches); + expect(platform.ensureIssue).toHaveBeenCalledTimes(1); + expect(platform.ensureIssue.mock.calls[0][0].body).toMatchSnapshot(); + + // same with dry run + await dryRun(branches, platform); + }); + }); + }); }); }); diff --git a/lib/workers/repository/dependency-dashboard.ts b/lib/workers/repository/dependency-dashboard.ts index b158de8771..634b91eb98 100644 --- a/lib/workers/repository/dependency-dashboard.ts +++ b/lib/workers/repository/dependency-dashboard.ts @@ -7,6 +7,7 @@ import { platform } from '../../modules/platform'; import { regEx } from '../../util/regex'; import * as template from '../../util/template'; import { BranchConfig, BranchResult } from '../types'; +import { PackageFiles } from './package-files'; interface DependencyDashboard { dependencyDashboardChecks: Record<string, string>; @@ -316,6 +317,8 @@ export async function ensureDependencyDashboard( 'This repository currently has no open or pending branches.\n\n'; } + issueBody += PackageFiles.getDashboardMarkdown(config); + if (config.dependencyDashboardFooter?.length) { issueBody += '---\n' + diff --git a/lib/workers/repository/finalise/index.ts b/lib/workers/repository/finalise/index.ts index 419a3a5cda..1f239204c1 100644 --- a/lib/workers/repository/finalise/index.ts +++ b/lib/workers/repository/finalise/index.ts @@ -3,6 +3,7 @@ import { logger } from '../../../logger'; import { platform } from '../../../modules/platform'; import * as repositoryCache from '../../../util/cache/repository'; import { clearRenovateRefs } from '../../../util/git'; +import { PackageFiles } from '../package-files'; import { pruneStaleBranches } from './prune'; import { runRenovateRepoStats } from './repository-statistics'; @@ -17,6 +18,7 @@ export async function finaliseRepo( `Action Required: Fix Renovate Configuration` ); await clearRenovateRefs(); + PackageFiles.clear(); const prList = await platform.getPrList(); if ( prList?.some( diff --git a/lib/workers/repository/package-files.ts b/lib/workers/repository/package-files.ts new file mode 100644 index 0000000000..e16abdbcc4 --- /dev/null +++ b/lib/workers/repository/package-files.ts @@ -0,0 +1,66 @@ +import type { RenovateConfig } from '../../config/types'; +import { logger } from '../../logger'; +import type { PackageFile } from '../../modules/manager/types'; + +export class PackageFiles { + private static data = new Map<string, Record<string, PackageFile[]> | null>(); + + public static add( + baseBranch: string, + packageFiles: Record<string, PackageFile[]> | null + ): void { + logger.debug( + { baseBranch }, + `PackageFiles.add() - Package file saved for branch` + ); + this.data.set(baseBranch, packageFiles); + } + + public static clear(): void { + logger.debug( + { baseBranches: [...this.data.keys()] }, + 'PackageFiles.clear() - Package files deleted' + ); + this.data.clear(); + } + + public static getDashboardMarkdown(config: RenovateConfig): string { + const title = `## Detected dependencies\n\n`; + const none = 'None detected\n\n'; + const pad = this.data.size > 1; // padding condition for a multi base branch repo + let deps = ''; + + for (const [branch, packageFiles] of this.data) { + deps += pad ? `<details><summary>Branch ${branch}\n</summary>\n\n` : ''; + if (packageFiles === null) { + deps += none; + deps += pad ? '\n</details>\n\n' : '\n'; + continue; + } + + const managers = Object.keys(packageFiles); + if (managers.length === 0) { + deps += none; + deps += pad ? '\n</details>\n\n' : '\n'; + continue; + } + + for (const manager of managers) { + deps += `${ + pad ? '\n<ul>' : '' + }<details><summary>${manager}</summary>\n\n`; + for (const packageFile of packageFiles[manager]) { + deps += `<ul><details><summary>${packageFile.packageFile}</summary>\n\n`; + for (const dep of packageFile.deps) { + deps += ` - \`${dep.depName} ${dep.currentValue}\`\n`; + } + deps += '\n</details></ul>'; + } + deps += `\n</details>${pad ? '</ul>' : ''}`; + } + deps += pad ? '\n</details>\n\n' : ''; + } + + return title + deps; + } +} diff --git a/lib/workers/repository/process/fetch.ts b/lib/workers/repository/process/fetch.ts index f3368f7237..4b6324a4d9 100644 --- a/lib/workers/repository/process/fetch.ts +++ b/lib/workers/repository/process/fetch.ts @@ -10,6 +10,7 @@ import type { } from '../../../modules/manager/types'; import { clone } from '../../../util/clone'; import { applyPackageRules } from '../../../util/package-rules'; +import { PackageFiles } from '../package-files'; import { lookupUpdates } from './lookup'; import type { LookupUpdateConfig } from './lookup/types'; @@ -100,6 +101,7 @@ export async function fetchUpdates( fetchManagerUpdates(config, packageFiles, manager) ); await Promise.all(allManagerJobs); + PackageFiles.add(config.baseBranch, { ...packageFiles }); logger.debug( { baseBranch: config.baseBranch }, 'Package releases lookups complete' -- GitLab