From f7635580b04266d56adb5e2a6f78488c7bf4c517 Mon Sep 17 00:00:00 2001 From: Michael Latman Date: Wed, 4 Dec 2024 20:05:42 -0500 Subject: [PATCH] Add PR check for new node packages --- package.json | 3 +- src/.github/workflows/pr-check.yml | 32 +++++++++++ src/scripts/pr-check.js | 89 ++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 src/.github/workflows/pr-check.yml create mode 100644 src/scripts/pr-check.js diff --git a/package.json b/package.json index 4386d6f..d3b29dc 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "version:patch": "npm version patch", "version:minor": "npm version minor", "version:major": "npm version major", - "publish:npm": "npm run build && npm publish --access public" + "publish:npm": "npm run build && npm publish --access public", + "pr-check": "node src/scripts/pr-check.js" }, "bin": { "mcp-get": "dist/index.js" diff --git a/src/.github/workflows/pr-check.yml b/src/.github/workflows/pr-check.yml new file mode 100644 index 0000000..13daed3 --- /dev/null +++ b/src/.github/workflows/pr-check.yml @@ -0,0 +1,32 @@ +name: PR Check + +on: + pull_request: + branches: + - main + +jobs: + pr-check: + runs-on: ubuntu-latest + + steps: + - name: Check out repository + uses: actions/checkout@v2 + + - name: Set up Node.js + uses: actions/setup-node@v2 + with: + node-version: '18' + + - name: Install dependencies + run: npm ci + + - name: Run PR check script + run: npm run pr-check + + - name: Provide feedback + run: | + COMMENT="PR check completed. Please review the results." + gh pr comment ${{ github.event.pull_request.number }} --body "$COMMENT" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/src/scripts/pr-check.js b/src/scripts/pr-check.js new file mode 100644 index 0000000..cec4bb6 --- /dev/null +++ b/src/scripts/pr-check.js @@ -0,0 +1,89 @@ +const { execSync } = require('child_process'); +const fs = require('fs'); +const path = require('path'); +const { Octokit } = require('@octokit/rest'); + +const REQUIRED_FIELDS = ['name', 'description', 'vendor', 'sourceUrl', 'homepage', 'license', 'runtime']; + +async function validatePackages() { + const packageListPath = path.join(__dirname, '../../packages/package-list.json'); + const packageList = JSON.parse(fs.readFileSync(packageListPath, 'utf-8')); + + const newPackages = getNewPackages(packageList); + + for (const pkg of newPackages) { + validateRequiredFields(pkg); + await checkNpmPublication(pkg.name); + } + + await provideFeedback(newPackages); +} + +function getNewPackages(packageList) { + const baseBranch = 'main'; + 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; + } + } + } + + return newPackages; +} + +function validateRequiredFields(pkg) { + for (const field of REQUIRED_FIELDS) { + if (!pkg[field]) { + throw new Error(`Package ${pkg.name} is missing required field: ${field}`); + } + } +} + +async function checkNpmPublication(packageName) { + try { + execSync(`npm view ${packageName}`); + } catch (error) { + throw new Error(`Package ${packageName} is not published on npm`); + } +} + +async function provideFeedback(newPackages) { + const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN }); + const { data: pullRequest } = await octokit.pulls.get({ + owner: process.env.GITHUB_REPOSITORY_OWNER, + repo: process.env.GITHUB_REPOSITORY, + pull_number: process.env.GITHUB_PULL_REQUEST_NUMBER + }); + + const feedback = newPackages.length > 0 + ? `The following new packages were validated successfully:\n${newPackages.map(pkg => `- ${pkg.name}`).join('\n')}` + : 'No new packages were added in this PR.'; + + await octokit.issues.createComment({ + owner: process.env.GITHUB_REPOSITORY_OWNER, + repo: process.env.GITHUB_REPOSITORY, + issue_number: pullRequest.number, + body: feedback + }); +} + +validatePackages().catch(error => { + console.error(error); + process.exit(1); +});