diff --git a/src/scripts/pr-check.js b/src/scripts/pr-check.js index 7a8b145..b835c0f 100644 --- a/src/scripts/pr-check.js +++ b/src/scripts/pr-check.js @@ -65,23 +65,22 @@ function getNewPackages(packageList) { const diffOutput = execSync(`git diff origin/${baseBranch} -- packages/package-list.json`).toString(); const newPackages = []; - const diffLines = diffOutput.split('\n'); - let currentPackage = null; - - for (const line of diffLines) { - if (line.startsWith('+') && !line.startsWith('+++')) { - const trimmedLine = line.substring(1).trim(); - if (trimmedLine.startsWith('{')) { - currentPackage = {}; - } else if (trimmedLine.startsWith('}')) { - if (currentPackage) { - newPackages.push(currentPackage); - currentPackage = null; - } - } else if (currentPackage) { - const [key, value] = trimmedLine.split(':').map(s => s.trim().replace(/,$/, '').replace(/"/g, '')); - currentPackage[key] = value; - } + // Extract complete JSON objects from diff + const addedBlocks = diffOutput.match(/^\+\s*{[\s\S]*?^\+\s*}/gm) || []; + + for (const block of addedBlocks) { + try { + // Remove diff markers and normalize whitespace + const cleanJson = block + .split('\n') + .map(line => line.replace(/^\+\s*/, '')) + .join('\n'); + + // Parse complete JSON object + const pkg = JSON.parse(cleanJson); + newPackages.push(pkg); + } catch (error) { + console.warn(`Warning: Failed to parse package block: ${error.message}`); } } diff --git a/src/scripts/pr-check.test.js b/src/scripts/pr-check.test.js index 1820136..9230d89 100644 --- a/src/scripts/pr-check.test.js +++ b/src/scripts/pr-check.test.js @@ -1,4 +1,5 @@ -import { validateRequiredFields } from './pr-check.js'; +import { execSync } from 'child_process'; +import { validateRequiredFields, getNewPackages } from './pr-check.js'; describe('validateRequiredFields', () => { test('accepts valid GitHub URLs', () => { @@ -40,3 +41,61 @@ describe('validateRequiredFields', () => { expect(() => validateRequiredFields(pkg)).not.toThrow(); }); }); + +describe('getNewPackages', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should correctly parse package with URL from git diff', () => { + const mockDiff = ` ++ { ++ "name": "test-package", ++ "description": "Test Package", ++ "vendor": "test", ++ "sourceUrl": "https://github.com/test/repo", ++ "homepage": "https://github.com/test/repo", ++ "license": "MIT", ++ "runtime": "python" ++ }`; + + execSync.mockReturnValue(Buffer.from(mockDiff)); + + const packages = getNewPackages({}); + expect(packages).toHaveLength(1); + expect(packages[0].sourceUrl).toBe('https://github.com/test/repo'); + }); + + it('should handle multiple packages in diff', () => { + const mockDiff = ` ++ { ++ "name": "package1", ++ "sourceUrl": "https://github.com/test/repo1" ++ }, ++ { ++ "name": "package2", ++ "sourceUrl": "https://github.com/test/repo2" ++ }`; + + execSync.mockReturnValue(Buffer.from(mockDiff)); + + const packages = getNewPackages({}); + expect(packages).toHaveLength(2); + expect(packages[0].sourceUrl).toBe('https://github.com/test/repo1'); + expect(packages[1].sourceUrl).toBe('https://github.com/test/repo2'); + }); + + it('should handle invalid JSON gracefully', () => { + const mockDiff = ` ++ { ++ "name": "broken-package", ++ "sourceUrl": "https://github.com/test/repo" ++ invalid-json-here ++ }`; + + execSync.mockReturnValue(Buffer.from(mockDiff)); + + const packages = getNewPackages({}); + expect(packages).toHaveLength(0); + }); +});