mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-11 22:46:27 +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.
|
||||
|
||||
### 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
|
||||
|
||||
Renovate's Dependency Dashboard shows an overview of all updates that are still "to do".
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
GitHubMaxPrBodyLen,
|
||||
massageMarkdown,
|
||||
} from '../../modules/platform/github';
|
||||
import { clone } from '../../util/clone';
|
||||
import { regEx } from '../../util/regex';
|
||||
import type { BranchConfig, BranchUpgradeConfig } from '../types';
|
||||
import * as dependencyDashboard from './dependency-dashboard';
|
||||
|
@ -981,6 +982,37 @@ None detected
|
|||
// same with dry run
|
||||
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', () => {
|
||||
|
|
|
@ -224,8 +224,32 @@ export async function ensureDependencyDashboard(
|
|||
return;
|
||||
}
|
||||
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);
|
||||
if (config.dependencyDashboardAutoclose && !hasBranches) {
|
||||
if (config.dependencyDashboardAutoclose && !hasBranches && !hasDeprecations) {
|
||||
if (GlobalConfig.get('dryRun')) {
|
||||
logger.info(
|
||||
{ title: config.dependencyDashboardTitle },
|
||||
|
@ -245,6 +269,25 @@ export async function ensureDependencyDashboard(
|
|||
|
||||
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(
|
||||
(branch) => branch.result === 'needs-approval',
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue