Skip to content

Commit

Permalink
feat: Refactor route detection and commenting logic in main function
Browse files Browse the repository at this point in the history
  • Loading branch information
hasithaishere committed Aug 5, 2024
1 parent 8d43db0 commit 2505a5f
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 9 deletions.
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ jobs:
uses: hasithaishere/route-commenter-action@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INPUT_COMMENT_CONTENT_FILE: '.github/config/route-comment-content.md'
INPUT_COMMENT_CONTENT_FILE: '.github/config/route-comment-content.md' # Optional: has hardcoded default content
INPUT_TAG_NAME: 'change-route' # Optional: default is 'change-route'
```
Create a route comment content file in your repository (e.g., `.github/config/route-comment-content.md`):
Expand All @@ -50,6 +51,23 @@ Create a route comment content file in your repository (e.g., `.github/config/ro
```
This content file will be optional and the default content will be used if not provided.

## For Maintainers

As general, this Github action also use ncc to package the code in to single js file. So in the development please globally install ncc first.

```sh
npm i -g @vercel/ncc --save
```

After your development, please execute following command for building the package file, then push the code to GitHub.

```sh
npm run build
```

## Developers

- [Hasitha Gamage](hasitha@rocketbots.io)

## License

Expand Down
85 changes: 81 additions & 4 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32083,17 +32083,29 @@ module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"]
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
/**
* @fileoverview This GitHub Action script detects changes in route files within a monorepo,
* adds comments to the PR where route changes are detected, and requests changes if necessary.
* It also adds a specific label to the PR if route changes are found.
*/

const fs = __nccwpck_require__(7147);
const path = __nccwpck_require__(1017);
const { execSync } = __nccwpck_require__(2081);
const { Octokit } = __nccwpck_require__(1540);
const { context } = __nccwpck_require__(8555);

// Constants
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
const COMMENT_FILE_PATH = process.env.INPUT_COMMENT_CONTENT_FILE;
const TAG_NAME = process.env.INPUT_TAG_NAME || 'change-route';

const octokit = new Octokit({ auth: GITHUB_TOKEN });

/**
* Gets the list of changed files in the pull request.
* @returns {Promise<string[]>} - An array of filenames that have been changed.
*/
async function getChangedFiles() {
const prNumber = context.payload.pull_request.number;
const owner = context.repo.owner;
Expand All @@ -32108,10 +32120,20 @@ async function getChangedFiles() {
return files.map(file => file.filename);
}

/**
* Checks if the specified folder is a service folder by looking for a 'routes' subfolder.
* @param {string} folderPath - The path of the folder to check.
* @returns {boolean} - True if the folder is a service folder, false otherwise.
*/
function isServiceFolder(folderPath) {
return fs.existsSync(path.join(folderPath, 'routes'));
}

/**
* Recursively gets all route files in the specified folder.
* @param {string} folderPath - The path of the folder to search for route files.
* @returns {string[]} - An array of paths to the route files.
*/
function getRouteFiles(folderPath) {
let routeFiles = [];
const items = fs.readdirSync(folderPath, { withFileTypes: true });
Expand All @@ -32133,6 +32155,12 @@ function getRouteFiles(folderPath) {
return routeFiles;
}

/**
* Detects the routes in the specified file that have changed based on the changed lines.
* @param {string} filePath - The path to the file to analyze.
* @param {number[]} changedLines - An array of line numbers that have changed in the file.
* @returns {Object[]} - An array of route objects that have changed.
*/
function detectRoutesInFile(filePath, changedLines) {
const data = fs.readFileSync(filePath, 'utf8');
const lines = data.split('\n');
Expand Down Expand Up @@ -32200,6 +32228,11 @@ function detectRoutesInFile(filePath, changedLines) {
return routes.filter(route => changedLines.some(line => line >= route.startLine && line <= route.endLine));
}

/**
* Gets the diff hunks for the specified file.
* @param {string} filePath - The path to the file to get the diff hunks for.
* @returns {Promise<Object[]>} - An array of diff hunk objects.
*/
async function getDiffHunks(filePath) {
const diffOutput = execSync(`git diff --unified=0 HEAD~1 HEAD ${filePath}`).toString();
const diffHunks = diffOutput.split('\n').filter(line => line.startsWith('@@')).map(hunk => {
Expand All @@ -32213,6 +32246,12 @@ async function getDiffHunks(filePath) {
return diffHunks;
}

/**
* Finds the corresponding line number in the original file for the specified target line in the diff hunks.
* @param {Object[]} diffHunks - An array of diff hunk objects.
* @param {number} targetLine - The target line number in the diff hunks.
* @returns {number|null} - The corresponding line number in the original file, or null if not found.
*/
function findDiffHunkLineNumber(diffHunks, targetLine) {
for (const hunk of diffHunks) {
if (targetLine >= hunk.newStart) {
Expand All @@ -32222,11 +32261,17 @@ function findDiffHunkLineNumber(diffHunks, targetLine) {
return null;
}

/**
* Gets the lines that need to be commented on based on the detected routes and changed lines.
* @param {Object[]} routes - An array of route objects.
* @param {number[]} changedLines - An array of changed line numbers.
* @returns {number[]} - An array of line numbers to be commented on.
*/
function getCommentingLines(routes, changedLines) {
const commentingLines = [];
changedLines.sort().forEach((line) => {
routes.forEach((route, index) => {
if (route.selectedLine == undefined && line >= route.startLine && line <= route.endLine) {
if (route.selectedLine === undefined && line >= route.startLine && line <= route.endLine) {
routes[index]['selectedLine'] = line;
commentingLines.push(line);
}
Expand All @@ -32235,6 +32280,14 @@ function getCommentingLines(routes, changedLines) {
return commentingLines;
}

/**
* Gets the existing comments made by the bot in the pull request.
* @param {string} owner - The owner of the repository.
* @param {string} repo - The name of the repository.
* @param {number} pullNumber - The pull request number.
* @param {string} botUsername - The username of the bot.
* @returns {Promise<Object[]>} - An array of existing comment objects.
*/
async function getExistingComments(owner, repo, pullNumber, botUsername) {
const { data: comments } = await octokit.rest.pulls.listReviewComments({
owner,
Expand All @@ -32245,6 +32298,14 @@ async function getExistingComments(owner, repo, pullNumber, botUsername) {
return comments.filter(comment => comment.user.login === botUsername);
}

/**
* Adds comments to the pull request for the specified lines and file.
* @param {number[]} commentingLines - An array of line numbers to comment on.
* @param {string} file - The path to the file to comment on.
* @param {Object[]} existingComments - An array of existing comment objects.
* @param {string} commentBody - The body of the comment to add.
* @returns {Promise<Object>} - An object indicating whether a comment was added.
*/
async function addPRComments(commentingLines, file, existingComments, commentBody) {
let commentAdded = false;
if (commentingLines.length > 0) {
Expand Down Expand Up @@ -32278,6 +32339,10 @@ async function addPRComments(commentingLines, file, existingComments, commentBod
return { commentAdded };
}

/**
* Gets the body of the comment from the specified file or returns a default comment body.
* @returns {Promise<string>} - The body of the comment.
*/
async function getCommentBody() {
// Default comment body
let commentBody = `
Expand All @@ -32294,7 +32359,15 @@ async function getCommentBody() {
return commentBody;
}

async function addLabelIfNotExists(owner, repo, prNumber, labelName, labelColor) {
/**
* Adds a label to the pull request if it does not already exist.
* @param {string} owner - The owner of the repository.
* @param {string} repo - The name of the repository.
* @param {number} prNumber - The pull request number.
* @param {string} labelName - The name of the label to add.
* @returns {Promise<void>}
*/
async function addLabelIfNotExists(owner, repo, prNumber, labelName) {
const { data: { labels } } = await octokit.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
Expand All @@ -32313,6 +32386,10 @@ async function addLabelIfNotExists(owner, repo, prNumber, labelName, labelColor)
}
}

/**
* Main function to execute the GitHub Action.
* @returns {Promise<void>}
*/
async function main() {
const rootPath = 'service';
const changedFiles = await getChangedFiles();
Expand Down Expand Up @@ -32368,8 +32445,8 @@ async function main() {
body: 'Please address the comments related to the route changes.',
});

// Add 'routes-changed' label with red color
await addLabelIfNotExists(context.repo.owner, context.repo.repo, context.payload.pull_request.number, 'routes-changed', 'ff0000');
// Add 'change-route' label with red color
await addLabelIfNotExists(context.repo.owner, context.repo.repo, context.payload.pull_request.number, TAG_NAME);
}
}

Expand Down
Loading

0 comments on commit 2505a5f

Please sign in to comment.