mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-12 06:56:24 +00:00
feat(dashboard): show deprecated dependency warnings (#29694)
Co-authored-by: HonkingGoose <34918129+HonkingGoose@users.noreply.github.com>
This commit is contained in:
parent
4b8beded1d
commit
03c034fbb5
3 changed files with 93 additions and 1 deletions
|
@ -49,6 +49,23 @@ To disable the Dependency Dashboard, add the preset `:disableDependencyDashboard
|
||||||
|
|
||||||
This section explains some common use cases where having the Dependency Dashboard can help.
|
This section explains some common use cases where having the Dependency Dashboard can help.
|
||||||
|
|
||||||
|
### Warnings for deprecated dependencies
|
||||||
|
|
||||||
|
If Renovate finds:
|
||||||
|
|
||||||
|
- packages flagged as deprecated on their registry, or
|
||||||
|
- packages that have a community-sourced replacement PR available
|
||||||
|
|
||||||
|
Then Renovate adds a prominent warning about these packages near the top of the Dependency Dashboard.
|
||||||
|
Here is an example of how this can look:
|
||||||
|
|
||||||
|
> The following dependencies are deprecated:
|
||||||
|
|
||||||
|
| Datasource | Name | Replacement? |
|
||||||
|
| ---------- | ------------------- | --------------------------------------------------------------------------------- |
|
||||||
|
| npm | `airbnb-prop-types` | ![Available](https://img.shields.io/badge/available-green?style=flat-square) |
|
||||||
|
| npm | `left-pad` | ![Unavailable](https://img.shields.io/badge/unavailable-orange?style=flat-square) |
|
||||||
|
|
||||||
### Visibility into rejected/deferred updates
|
### Visibility into rejected/deferred updates
|
||||||
|
|
||||||
Renovate's Dependency Dashboard shows an overview of all updates that are still "to do".
|
Renovate's Dependency Dashboard shows an overview of all updates that are still "to do".
|
||||||
|
|
|
@ -19,6 +19,7 @@ import {
|
||||||
GitHubMaxPrBodyLen,
|
GitHubMaxPrBodyLen,
|
||||||
massageMarkdown,
|
massageMarkdown,
|
||||||
} from '../../modules/platform/github';
|
} from '../../modules/platform/github';
|
||||||
|
import { clone } from '../../util/clone';
|
||||||
import { regEx } from '../../util/regex';
|
import { regEx } from '../../util/regex';
|
||||||
import type { BranchConfig, BranchUpgradeConfig } from '../types';
|
import type { BranchConfig, BranchUpgradeConfig } from '../types';
|
||||||
import * as dependencyDashboard from './dependency-dashboard';
|
import * as dependencyDashboard from './dependency-dashboard';
|
||||||
|
@ -981,6 +982,37 @@ None detected
|
||||||
// same with dry run
|
// same with dry run
|
||||||
await dryRun(branches, platform, 0, 1);
|
await dryRun(branches, platform, 0, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('shows deprecations', async () => {
|
||||||
|
const branches: BranchConfig[] = [];
|
||||||
|
const packageFilesWithDeprecations = clone(packageFiles);
|
||||||
|
packageFilesWithDeprecations.npm[0].deps[0].deprecationMessage =
|
||||||
|
'some deprecation message';
|
||||||
|
packageFilesWithDeprecations.npm[0].deps[2].updates.push({
|
||||||
|
updateType: 'replacement',
|
||||||
|
newName: 'prop-types-tools',
|
||||||
|
newValue: '2.17.0',
|
||||||
|
branchName: 'renovate/airbnb-prop-types-replacement',
|
||||||
|
});
|
||||||
|
PackageFiles.add('main', packageFilesWithDeprecations);
|
||||||
|
await dependencyDashboard.ensureDependencyDashboard(
|
||||||
|
config,
|
||||||
|
branches,
|
||||||
|
packageFilesWithDeprecations,
|
||||||
|
);
|
||||||
|
expect(platform.ensureIssue).toHaveBeenCalledTimes(1);
|
||||||
|
expect(platform.ensureIssue.mock.calls[0][0].body).toInclude(
|
||||||
|
'These dependencies are deprecated',
|
||||||
|
);
|
||||||
|
expect(platform.ensureIssue.mock.calls[0][0].body).toInclude(
|
||||||
|
'| npm | `cookie-parser` | ![Unavailable]',
|
||||||
|
);
|
||||||
|
expect(platform.ensureIssue.mock.calls[0][0].body).toInclude(
|
||||||
|
'npm | `express-handlebars` | ![Available]',
|
||||||
|
);
|
||||||
|
// same with dry run
|
||||||
|
await dryRun(branches, platform, 0, 1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('multi base branch repo', () => {
|
describe('multi base branch repo', () => {
|
||||||
|
|
|
@ -224,8 +224,32 @@ export async function ensureDependencyDashboard(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
logger.debug('Ensuring Dependency Dashboard');
|
logger.debug('Ensuring Dependency Dashboard');
|
||||||
|
|
||||||
|
// Check packageFiles for any deprecations
|
||||||
|
let hasDeprecations = false;
|
||||||
|
const deprecatedPackages: Record<string, Record<string, boolean>> = {};
|
||||||
|
logger.debug(
|
||||||
|
{ packageFiles },
|
||||||
|
'Checking packageFiles for deprecated packages',
|
||||||
|
);
|
||||||
|
for (const [manager, fileNames] of Object.entries(packageFiles)) {
|
||||||
|
for (const fileName of fileNames) {
|
||||||
|
for (const dep of fileName.deps) {
|
||||||
|
const name = dep.packageName ?? dep.depName;
|
||||||
|
const hasReplacement = !!dep.updates?.find(
|
||||||
|
(updates) => updates.updateType === 'replacement',
|
||||||
|
);
|
||||||
|
if (name && (dep.deprecationMessage ?? hasReplacement)) {
|
||||||
|
hasDeprecations = true;
|
||||||
|
deprecatedPackages[manager] ??= {};
|
||||||
|
deprecatedPackages[manager][name] ??= hasReplacement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const hasBranches = is.nonEmptyArray(branches);
|
const hasBranches = is.nonEmptyArray(branches);
|
||||||
if (config.dependencyDashboardAutoclose && !hasBranches) {
|
if (config.dependencyDashboardAutoclose && !hasBranches && !hasDeprecations) {
|
||||||
if (GlobalConfig.get('dryRun')) {
|
if (GlobalConfig.get('dryRun')) {
|
||||||
logger.info(
|
logger.info(
|
||||||
{ title: config.dependencyDashboardTitle },
|
{ title: config.dependencyDashboardTitle },
|
||||||
|
@ -245,6 +269,25 @@ export async function ensureDependencyDashboard(
|
||||||
|
|
||||||
issueBody = appendRepoProblems(config, issueBody);
|
issueBody = appendRepoProblems(config, issueBody);
|
||||||
|
|
||||||
|
if (hasDeprecations) {
|
||||||
|
issueBody += '> ⚠ **Warning**\n> \n';
|
||||||
|
issueBody += 'These dependencies are deprecated:\n\n';
|
||||||
|
issueBody += '| Datasource | Name | Replacement PR? |\n';
|
||||||
|
issueBody += '|------------|------|--------------|\n';
|
||||||
|
for (const manager of Object.keys(deprecatedPackages).sort()) {
|
||||||
|
const deps = deprecatedPackages[manager];
|
||||||
|
for (const depName of Object.keys(deps).sort()) {
|
||||||
|
const hasReplacement = deps[depName];
|
||||||
|
issueBody += `| ${manager} | \`${depName}\` | ${
|
||||||
|
hasReplacement
|
||||||
|
? '![Available](https://img.shields.io/badge/available-green?style=flat-square)'
|
||||||
|
: '![Unavailable](https://img.shields.io/badge/unavailable-orange?style=flat-square)'
|
||||||
|
} |\n`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
issueBody += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
const pendingApprovals = branches.filter(
|
const pendingApprovals = branches.filter(
|
||||||
(branch) => branch.result === 'needs-approval',
|
(branch) => branch.result === 'needs-approval',
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue