* Parses and validates all change files for a package. * Returns changes if valid, or errors if invalid.
(packageDirName: string)
| 58 | * Returns changes if valid, or errors if invalid. |
| 59 | */ |
| 60 | function parsePackageChanges(packageDirName: string): ParsedPackageChanges { |
| 61 | let packagePath = getPackagePath(packageDirName); |
| 62 | let changesDir = path.join(packagePath, ".changes"); |
| 63 | let changes: ChangeFile[] = []; |
| 64 | let errors: ValidationError[] = []; |
| 65 | |
| 66 | // Changes directory should exist (with at least .gitkeep) |
| 67 | if (!fs.existsSync(changesDir)) { |
| 68 | return { |
| 69 | valid: false, |
| 70 | errors: [ |
| 71 | { |
| 72 | packageDirName, |
| 73 | file: ".changes/", |
| 74 | error: "Changes directory does not exist", |
| 75 | }, |
| 76 | ], |
| 77 | }; |
| 78 | } |
| 79 | |
| 80 | // .gitkeep should exist in .changes directory so it persists between releases |
| 81 | let gitkeepPath = path.join(changesDir, ".gitkeep"); |
| 82 | if (!fs.existsSync(gitkeepPath)) { |
| 83 | errors.push({ |
| 84 | packageDirName, |
| 85 | file: ".changes/.gitkeep", |
| 86 | error: ".gitkeep is missing from .changes directory", |
| 87 | }); |
| 88 | } |
| 89 | |
| 90 | // Get package version to determine validation rules |
| 91 | let packageJsonPath = getPackageFile(packageDirName, "package.json"); |
| 92 | let packageJson = readJson(packageJsonPath); |
| 93 | let currentVersion = packageJson.version as string; |
| 94 | |
| 95 | // Read all files in .changes directory |
| 96 | let changeFileNames = fs |
| 97 | .readdirSync(changesDir) |
| 98 | .filter((file) => file.endsWith(".md")); |
| 99 | |
| 100 | for (let file of changeFileNames) { |
| 101 | // Parse and validate filename format (e.g. "minor.add-feature.md") |
| 102 | let bump: BumpType | null = null; |
| 103 | |
| 104 | let withoutExt = path.basename(file, ".md"); |
| 105 | let dotIndex = withoutExt.indexOf("."); |
| 106 | if (dotIndex !== -1) { |
| 107 | let bumpStr = withoutExt.slice(0, dotIndex); |
| 108 | let name = withoutExt.slice(dotIndex + 1); |
| 109 | if (bumpTypes.includes(bumpStr as BumpType) && name.length > 0) { |
| 110 | bump = bumpStr as BumpType; |
| 111 | } |
| 112 | } |
| 113 | |
| 114 | if (bump == null) { |
| 115 | errors.push({ |
| 116 | packageDirName, |
| 117 | file, |
no test coverage detected
searching dependent graphs…