also looking at this
fix(dashboard): read the include toggles and the enabled switch
#1430
5 files
+100
-2
| @@ -793,6 +793,16 @@ cli | ||
| 793 | 793 | const logger = options.verbose ? Logger.verbose() : Logger.quiet() |
| 794 | 794 | const config = await resolveConfig(options.config) |
| 795 | 795 | |
| 796 | // Explicit `false` only. Unset stays on: the setting was documented as | |
| 797 | // defaulting to false and was read by nothing, and enforcing that | |
| 798 | // literally would switch off the dashboard for every repository that | |
| 799 | // never wrote a `dashboard` block — the same trap `ai.review.enabled` | |
| 800 | // set, and the same reading that avoids it. | |
| 801 | if (config.dashboard?.enabled === false) { | |
| 802 | logger.info('ℹ️ Dashboard is disabled by config (dashboard.enabled: false)') | |
| 803 | return | |
| 804 | } | |
| 805 | ||
| 796 | 806 | try { |
| 797 | 807 | logger.info('Creating or updating dependency dashboard...') |
| 798 | 808 | |
| @@ -3151,6 +3161,8 @@ cli | ||
| 3151 | 3161 | // Supplied here because refreshing means a full scan, which is |
| 3152 | 3162 | // `Buddy`'s job rather than the gate module's. |
| 3153 | 3163 | refreshDashboard: async () => { |
| 3164 | if (config.dashboard?.enabled === false) | |
| 3165 | throw new Error('dashboard.enabled is false') | |
| 3154 | 3166 | await new Buddy(config).createOrUpdateDashboard() |
| 3155 | 3167 | }, |
| 3156 | 3168 | }) |
| @@ -62,7 +62,7 @@ export default { | ||
| 62 | 62 | |
| 63 | 63 | | Option | Type | Default | Description | |
| 64 | 64 | |--------|------|---------|-------------| |
| 65 | | `enabled` | `boolean` | `false` | Enable dependency dashboard | | |
| 65 | | `enabled` | `boolean` | `true` | Set to `false` to stop the dashboard being created or refreshed | | |
| 66 | 66 | | `title` | `string` | `'Dependency Dashboard'` | Custom dashboard title | |
| 67 | 67 | | `labels` | `string[]` | `['dependencies', 'dashboard']` | Labels to add to the issue | |
| 68 | 68 | | `assignees` | `string[]` | `[]` | Users to assign to the issue | |
| @@ -3289,6 +3289,9 @@ export class Buddy { | ||
| 3289 | 3289 | showOpenPRs: dashboardConfig.showOpenPRs ?? true, |
| 3290 | 3290 | showDetectedDependencies: dashboardConfig.showDetectedDependencies ?? true, |
| 3291 | 3291 | showDeprecatedDependencies: dashboardConfig.showDeprecatedDependencies ?? true, |
| 3292 | includePackageJson: dashboardConfig.includePackageJson ?? true, | |
| 3293 | includeDependencyFiles: dashboardConfig.includeDependencyFiles ?? true, | |
| 3294 | includeGitHubActions: dashboardConfig.includeGitHubActions ?? true, | |
| 3292 | 3295 | bodyTemplate: dashboardConfig.bodyTemplate, |
| 3293 | 3296 | }) |
| 3294 | 3297 | |
| @@ -18,6 +18,10 @@ export class DashboardGenerator { | ||
| 18 | 18 | showDetectedDependencies?: boolean |
| 19 | 19 | showDeprecatedDependencies?: boolean |
| 20 | 20 | showVulnerableDependencies?: boolean |
| 21 | /** Per-ecosystem toggles within the detected-dependencies section */ | |
| 22 | includePackageJson?: boolean | |
| 23 | includeDependencyFiles?: boolean | |
| 24 | includeGitHubActions?: boolean | |
| 21 | 25 | bodyTemplate?: string |
| 22 | 26 | } = {}): { title: string, body: string } { |
| 23 | 27 | const { |
| @@ -25,6 +29,9 @@ export class DashboardGenerator { | ||
| 25 | 29 | showDetectedDependencies = true, |
| 26 | 30 | showDeprecatedDependencies = true, |
| 27 | 31 | showVulnerableDependencies = true, |
| 32 | includePackageJson = true, | |
| 33 | includeDependencyFiles = true, | |
| 34 | includeGitHubActions = true, | |
| 28 | 35 | bodyTemplate, |
| 29 | 36 | } = options |
| 30 | 37 | |
| @@ -61,7 +68,13 @@ export class DashboardGenerator { | ||
| 61 | 68 | } |
| 62 | 69 | |
| 63 | 70 | if (showDetectedDependencies) { |
| 64 | body += this.generateDetectedDependenciesSection(data.detectedDependencies) | |
| 71 | // The three `include*` toggles were declared, documented in the defaults | |
| 72 | // table, and read by nothing — every ecosystem was always listed. | |
| 73 | body += this.generateDetectedDependenciesSection({ | |
| 74 | packageJson: includePackageJson ? data.detectedDependencies.packageJson : [], | |
| 75 | dependencyFiles: includeDependencyFiles ? data.detectedDependencies.dependencyFiles : [], | |
| 76 | githubActions: includeGitHubActions ? data.detectedDependencies.githubActions : [], | |
| 77 | }) | |
| 65 | 78 | } |
| 66 | 79 | |
| 67 | 80 | body += this.generateFooter() |
| @@ -855,3 +855,73 @@ Dependency files: | ||
| 855 | 855 | expect(result.body).toContain('<!-- rebase-branch=renovate/symfony-console-7.x -->') |
| 856 | 856 | }) |
| 857 | 857 | }) |
| 858 | ||
| 859 | /** | |
| 860 | * `includePackageJson`, `includeDependencyFiles` and `includeGitHubActions` | |
| 861 | * were declared, documented in the defaults table as `true`, and read by | |
| 862 | * nothing — every ecosystem was always listed whatever the config said. | |
| 863 | */ | |
| 864 | describe('per-ecosystem include toggles', () => { | |
| 865 | const generator = new DashboardGenerator() | |
| 866 | ||
| 867 | function file(path: string, type: PackageFile['type'], depType: PackageFile['dependencies'][number]['type']): PackageFile { | |
| 868 | return { | |
| 869 | path, | |
| 870 | type, | |
| 871 | content: '', | |
| 872 | dependencies: [{ name: `dep-in-${path}`, currentVersion: '1.0.0', type: depType, file: path }], | |
| 873 | } | |
| 874 | } | |
| 875 | ||
| 876 | const data: DashboardData = { | |
| 877 | repository: { owner: 'o', name: 'r', provider: 'github' }, | |
| 878 | openPRs: [], | |
| 879 | detectedDependencies: { | |
| 880 | packageJson: [file('package.json', 'package.json', 'dependencies')], | |
| 881 | dependencyFiles: [file('deps.yaml', 'deps.yaml', 'dependencies')], | |
| 882 | githubActions: [file('.github/workflows/ci.yml', 'github-actions', 'github-actions')], | |
| 883 | }, | |
| 884 | lastUpdated: new Date('2024-01-01T00:00:00Z'), | |
| 885 | } | |
| 886 | ||
| 887 | it('success case - everything is listed by default', () => { | |
| 888 | const { body } = generator.generateDashboard(data) | |
| 889 | ||
| 890 | expect(body).toContain('<summary>npm</summary>') | |
| 891 | expect(body).toContain('<summary>github-actions</summary>') | |
| 892 | expect(body).toContain('<summary>dependency-files</summary>') | |
| 893 | }) | |
| 894 | ||
| 895 | it('success case - includePackageJson: false drops the npm section only', () => { | |
| 896 | const { body } = generator.generateDashboard(data, { includePackageJson: false }) | |
| 897 | ||
| 898 | expect(body).not.toContain('<summary>npm</summary>') | |
| 899 | expect(body).toContain('<summary>github-actions</summary>') | |
| 900 | expect(body).toContain('<summary>dependency-files</summary>') | |
| 901 | }) | |
| 902 | ||
| 903 | it('success case - includeGitHubActions: false drops the actions section only', () => { | |
| 904 | const { body } = generator.generateDashboard(data, { includeGitHubActions: false }) | |
| 905 | ||
| 906 | expect(body).not.toContain('<summary>github-actions</summary>') | |
| 907 | expect(body).toContain('<summary>npm</summary>') | |
| 908 | }) | |
| 909 | ||
| 910 | it('success case - includeDependencyFiles: false drops the dependency-files section only', () => { | |
| 911 | const { body } = generator.generateDashboard(data, { includeDependencyFiles: false }) | |
| 912 | ||
| 913 | expect(body).not.toContain('<summary>dependency-files</summary>') | |
| 914 | expect(body).toContain('<summary>npm</summary>') | |
| 915 | }) | |
| 916 | ||
| 917 | it('edge case - all three off leaves the heading and nothing under it', () => { | |
| 918 | const { body } = generator.generateDashboard(data, { | |
| 919 | includePackageJson: false, | |
| 920 | includeDependencyFiles: false, | |
| 921 | includeGitHubActions: false, | |
| 922 | }) | |
| 923 | ||
| 924 | expect(body).toContain('## Detected dependencies') | |
| 925 | expect(body).not.toContain('<summary>') | |
| 926 | }) | |
| 927 | }) | |