|
| 1 | +#!/usr/bin/env php |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Script to automatically generate dependabot.yml configuration based on directory structure. |
| 6 | + * |
| 7 | + * This script scans the project for composer.json files and generates a dependabot.yml |
| 8 | + * configuration file with appropriate settings for each package. |
| 9 | + * |
| 10 | + * Usage: php scripts/generate-dependabot-config.php |
| 11 | + */ |
| 12 | + |
| 13 | +// Configuration |
| 14 | +$rootDir = dirname(__DIR__); |
| 15 | +$outputFile = $rootDir . '/.github/dependabot.yml'; |
| 16 | +$scanDirs = [ |
| 17 | + $rootDir, |
| 18 | + $rootDir . '/src', |
| 19 | + $rootDir . '/examples', |
| 20 | +]; |
| 21 | + |
| 22 | +// Initialize YAML content |
| 23 | +$yaml = [ |
| 24 | + '# Dependabot configuration file', |
| 25 | + '# See: https://docs.github.com/github/administering-a-repository/', |
| 26 | + '# configuration-options-for-dependency-updates', |
| 27 | + '', |
| 28 | + 'version: 2', |
| 29 | + 'updates:', |
| 30 | +]; |
| 31 | + |
| 32 | +// Add root project configuration |
| 33 | +$yaml[] = ' # Maintain dependencies for the root project'; |
| 34 | +$yaml[] = ' - package-ecosystem: "composer"'; |
| 35 | +$yaml[] = ' directory: "/"'; |
| 36 | +$yaml[] = ' schedule:'; |
| 37 | +$yaml[] = ' interval: "weekly"'; |
| 38 | +$yaml[] = ' open-pull-requests-limit: 10'; |
| 39 | +$yaml[] = ' labels:'; |
| 40 | +$yaml[] = ' - "dependencies"'; |
| 41 | +$yaml[] = ' versioning-strategy: "auto"'; |
| 42 | +$yaml[] = ' allow:'; |
| 43 | +$yaml[] = ' - dependency-type: "direct"'; |
| 44 | +$yaml[] = ' - dependency-type: "indirect"'; |
| 45 | +$yaml[] = ' groups:'; |
| 46 | +$yaml[] = ' dev-dependencies:'; |
| 47 | +$yaml[] = ' patterns:'; |
| 48 | +$yaml[] = ' - "friendsofphp/php-cs-fixer"'; |
| 49 | +$yaml[] = ' - "phan/phan"'; |
| 50 | +$yaml[] = ' - "phpstan/phpstan*"'; |
| 51 | +$yaml[] = ' - "phpunit/phpunit"'; |
| 52 | +$yaml[] = ' - "vimeo/psalm"'; |
| 53 | +$yaml[] = ' - "psalm/plugin-phpunit"'; |
| 54 | +$yaml[] = ' exclude-patterns:'; |
| 55 | +$yaml[] = ' - "open-telemetry/*"'; |
| 56 | +$yaml[] = ' open-telemetry:'; |
| 57 | +$yaml[] = ' patterns:'; |
| 58 | +$yaml[] = ' - "open-telemetry/*"'; |
| 59 | +$yaml[] = ' symfony:'; |
| 60 | +$yaml[] = ' patterns:'; |
| 61 | +$yaml[] = ' - "symfony/*"'; |
| 62 | +$yaml[] = ' ignore:'; |
| 63 | +$yaml[] = ' - dependency-name: "*"'; |
| 64 | +$yaml[] = ' update-types: ["version-update:semver-major"]'; |
| 65 | +$yaml[] = ' commit-message:'; |
| 66 | +$yaml[] = ' prefix: "chore"'; |
| 67 | +$yaml[] = ' prefix-development: "chore"'; |
| 68 | +$yaml[] = ' include: "scope"'; |
| 69 | +$yaml[] = ''; |
| 70 | + |
| 71 | +// Add GitHub Actions configuration |
| 72 | +$yaml[] = ' # Maintain dependencies for GitHub Actions'; |
| 73 | +$yaml[] = ' - package-ecosystem: "github-actions"'; |
| 74 | +$yaml[] = ' directory: "/"'; |
| 75 | +$yaml[] = ' schedule:'; |
| 76 | +$yaml[] = ' interval: "weekly"'; |
| 77 | +$yaml[] = ' open-pull-requests-limit: 10'; |
| 78 | +$yaml[] = ' labels:'; |
| 79 | +$yaml[] = ' - "dependencies"'; |
| 80 | +$yaml[] = ' commit-message:'; |
| 81 | +$yaml[] = ' prefix: "chore"'; |
| 82 | +$yaml[] = ' prefix-development: "chore"'; |
| 83 | +$yaml[] = ' include: "scope"'; |
| 84 | +$yaml[] = ''; |
| 85 | + |
| 86 | +// Find all composer.json files |
| 87 | +$composerFiles = []; |
| 88 | +foreach ($scanDirs as $scanDir) { |
| 89 | + findComposerFiles($scanDir, $composerFiles, $rootDir); |
| 90 | +} |
| 91 | + |
| 92 | +// Filter out the root composer.json as it's already configured |
| 93 | +$packageDirectories = []; |
| 94 | +foreach ($composerFiles as $composerFile) { |
| 95 | + if ($composerFile !== '/') { |
| 96 | + $packageDirectories[] = $composerFile; |
| 97 | + } |
| 98 | +} |
| 99 | + |
| 100 | +// Add a single configuration for all package directories |
| 101 | +if (!empty($packageDirectories)) { |
| 102 | + $yaml[] = ' # Maintain dependencies for all packages'; |
| 103 | + $yaml[] = ' - package-ecosystem: "composer"'; |
| 104 | + $yaml[] = ' directories:'; |
| 105 | + |
| 106 | + // Sort directories for consistent output |
| 107 | + sort($packageDirectories); |
| 108 | + foreach ($packageDirectories as $directory) { |
| 109 | + $yaml[] = ' - "' . $directory . '"'; |
| 110 | + } |
| 111 | + |
| 112 | + $yaml[] = ' schedule:'; |
| 113 | + $yaml[] = ' interval: "weekly"'; |
| 114 | + $yaml[] = ' labels:'; |
| 115 | + $yaml[] = ' - "dependencies"'; |
| 116 | + $yaml[] = ' groups:'; |
| 117 | + $yaml[] = ' dev-dependencies:'; |
| 118 | + $yaml[] = ' patterns:'; |
| 119 | + $yaml[] = ' - "friendsofphp/php-cs-fixer"'; |
| 120 | + $yaml[] = ' - "phan/phan"'; |
| 121 | + $yaml[] = ' - "phpstan/phpstan*"'; |
| 122 | + $yaml[] = ' - "phpunit/phpunit"'; |
| 123 | + $yaml[] = ' - "vimeo/psalm"'; |
| 124 | + $yaml[] = ' - "psalm/plugin-phpunit"'; |
| 125 | + $yaml[] = ' laravel:'; |
| 126 | + $yaml[] = ' patterns:'; |
| 127 | + $yaml[] = ' - "laravel/*"'; |
| 128 | + $yaml[] = ' - "illuminate/*"'; |
| 129 | + $yaml[] = ' open-telemetry:'; |
| 130 | + $yaml[] = ' patterns:'; |
| 131 | + $yaml[] = ' - "open-telemetry/*"'; |
| 132 | + $yaml[] = ' symfony:'; |
| 133 | + $yaml[] = ' patterns:'; |
| 134 | + $yaml[] = ' - "symfony/*"'; |
| 135 | + $yaml[] = ' ignore:'; |
| 136 | + $yaml[] = ' - dependency-name: "*"'; |
| 137 | + $yaml[] = ' update-types: ["version-update:semver-major"]'; |
| 138 | + $yaml[] = ' commit-message:'; |
| 139 | + $yaml[] = ' prefix: "chore"'; |
| 140 | + $yaml[] = ' prefix-development: "chore"'; |
| 141 | + $yaml[] = ' include: "scope"'; |
| 142 | + $yaml[] = ''; |
| 143 | +} |
| 144 | + |
| 145 | +// Write the YAML file |
| 146 | +file_put_contents($outputFile, implode("\n", $yaml)); |
| 147 | + |
| 148 | +echo "Dependabot configuration generated at: $outputFile\n"; |
| 149 | +echo "Found " . count($composerFiles) . " composer.json files.\n"; |
| 150 | + |
| 151 | +/** |
| 152 | + * Recursively find composer.json files in the given directory. |
| 153 | + * |
| 154 | + * @param string $dir The directory to scan |
| 155 | + * @param array $results Array to store results |
| 156 | + * @param string $rootDir The root directory of the project |
| 157 | + */ |
| 158 | +function findComposerFiles($dir, &$results, $rootDir) { |
| 159 | + $files = scandir($dir); |
| 160 | + |
| 161 | + foreach ($files as $file) { |
| 162 | + if ($file === '.' || $file === '..' || $file === 'vendor') { |
| 163 | + continue; |
| 164 | + } |
| 165 | + |
| 166 | + $path = $dir . '/' . $file; |
| 167 | + |
| 168 | + if (is_dir($path)) { |
| 169 | + // Skip vendor directories |
| 170 | + if (strpos($path, '/vendor/') !== false) { |
| 171 | + continue; |
| 172 | + } |
| 173 | + |
| 174 | + findComposerFiles($path, $results, $rootDir); |
| 175 | + } elseif ($file === 'composer.json') { |
| 176 | + // Get relative path from root |
| 177 | + $relativePath = str_replace($rootDir, '', dirname($path)); |
| 178 | + $relativePath = $relativePath ?: '/'; |
| 179 | + |
| 180 | + // Add to results if not already present |
| 181 | + if (!in_array($relativePath, $results)) { |
| 182 | + $results[] = $relativePath; |
| 183 | + } |
| 184 | + } |
| 185 | + } |
| 186 | +} |
0 commit comments