Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/lint-detection.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Lint Detection and Issue Management

on:
  # Trigger workflow for pull requests targeting the master branch
  pull_request:
    branches:
      - master

  # Trigger workflow for direct pushes or merges to the master branch
  push:
    branches:
      - master

jobs:
  lint:
    runs-on: ubuntu-latest

    steps:
    # Step 1: Checkout the repository to make the code available to the workflow
    - name: Checkout repository
      uses: actions/checkout@v3

    # Step 2: Set up Node.js environment and install npm dependencies
    - name: Set up Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '20' # Adjust this based on your project's requirements
        cache: 'npm'       # Use npm caching for faster workflow execution

    - name: Install Node.js Dependencies
      working-directory: ./Application
      run: npm install

    # Step 3: Run the linter and export its output as JSON
    - name: Run Linter and Export Results
      id: lint
      working-directory: ./Application
      run: |
        npm run lint --json > lint-output.json
Comment on lines +35 to +39
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The npm run lint command has an incorrect output redirection syntax. The --json flag should come before the redirection operator, and the command may fail depending on the linter's exit code. The syntax should be 'npm run lint -- --format=json > lint-output.json' or similar depending on the linter being used. Additionally, if lint errors are found, npm run lint typically exits with a non-zero code which will fail the workflow step unless you add '|| true' to allow continuation.

Suggested change
    - name: Run Linter and Export Results
      id: lint
      working-directory: ./Application
      run: |
        npm run lint --json > lint-output.json
- name: Run Linter and Export Results
id: lint
working-directory: ./Application
run: |
npm run lint -- --format=json > lint-output.json || true

Copilot uses AI. Check for mistakes.

    # Step 4: Install and run the tree command for directory mapping
    - name: Generate Repository File Tree (Exclude node_modules)
      id: tree
      run: |
        apt-get update && apt-get install -y tree
        tree -L 5 -I "node_modules" > tree-output.txt
Comment on lines +41 to +46
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The apt-get commands are being run without sudo privileges. In GitHub Actions ubuntu-latest runners, these commands require elevated permissions. This will cause the workflow to fail with a permission denied error.

Suggested change
    # Step 4: Install and run the tree command for directory mapping
    - name: Generate Repository File Tree (Exclude node_modules)
      id: tree
      run: |
        apt-get update && apt-get install -y tree
        tree -L 5 -I "node_modules" > tree-output.txt
# Step 4: Install and run the tree command for directory mapping
- name: Generate Repository File Tree (Exclude node_modules)
id: tree
run: |
sudo apt-get update && sudo apt-get install -y tree
tree -L 5 -I "node_modules" > tree-output.txt

Copilot uses AI. Check for mistakes.

    # Step 5: Run the issue management script using the lint output and tree file
    - name: Process and Manage GitHub Issues for Lint
      run: |
        node scripts/manageLintIssues.js ./Application/lint-output.json tree-output.txt
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Comment on lines +41 to +53
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow is missing installation of the @octokit/rest package which is required by the manageLintIssues.js script. The script requires this dependency but it's only installed in the Application directory. Either add a package.json in the root directory with this dependency, or install it explicitly before running the script.

Suggested change
    # Step 4: Install and run the tree command for directory mapping
    - name: Generate Repository File Tree (Exclude node_modules)
      id: tree
      run: |
        apt-get update && apt-get install -y tree
        tree -L 5 -I "node_modules" > tree-output.txt
    # Step 5: Run the issue management script using the lint output and tree file
    - name: Process and Manage GitHub Issues for Lint
      run: |
        node scripts/manageLintIssues.js ./Application/lint-output.json tree-output.txt
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Step 4: Install and run the tree command for directory mapping
- name: Generate Repository File Tree (Exclude node_modules)
id: tree
run: |
apt-get update && apt-get install -y tree
tree -L 5 -I "node_modules" > tree-output.txt
# Step 5: Install Octokit dependency required by manageLintIssues.js
- name: Install Octokit dependency
run: npm install @octokit/rest
# Step 6: Run the issue management script using the lint output and tree file
- name: Process and Manage GitHub Issues for Lint
run: |
node scripts/manageLintIssues.js ./Application/lint-output.json tree-output.txt
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Copilot uses AI. Check for mistakes.
99 changes: 99 additions & 0 deletions scripts/manageLintIssues.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
const fs = require('fs');
const { Octokit } = require('@octokit/rest');

const octokit = new Octokit({
  auth: process.env.GITHUB_TOKEN, // GitHub token provided via workflow secrets
});

// Repository owner and name
const REPO_OWNER = 'codingUnited';
const REPO_NAME = 'MokseWebsite';

// Generate short path for file, starting from the 3rd level of depth
function generateShortPath(filePath) {
  const levels = filePath.split('/');
  const startPath = levels.slice(2, 5).join('/');
  const fileParent = levels.slice(levels.length - 2, levels.length - 1)[0];
  return `${startPath}/~${fileParent}`;
}

// Generate issue title based on short file path
function generateIssueTitle(filePath) {
  const shortPath = generateShortPath(filePath);
  const fileParentAndName = filePath.split('/').slice(-2).join('/');
  return `-${shortPath} on /${fileParentAndName}`;
}

// Main script for managing issues
(async () => {
  try {
    // Read lint results and directory tree output
    const lintResults = JSON.parse(fs.readFileSync(process.argv[2], 'utf-8'));
    const treeOutput = fs.readFileSync(process.argv[3], 'utf-8').split('\n');

    // Fetch existing issues
    const existingIssues = await octokit.issues.listForRepo({
      owner: REPO_OWNER,
      repo: REPO_NAME,
    });

    const existingIssuesMap = new Map();
    for (let issue of existingIssues.data) {
      existingIssuesMap.set(issue.title, issue);
    }

    for (let result of lintResults) {
      const filePath = result.filePath.replace('Application/', '');
      const lintMessage = result.message;
      const ruleId = result.ruleId;

      if (!treeOutput.includes(filePath)) {
        continue; // Skip if file not in the directory tree
      }

      const issueTitle = generateIssueTitle(filePath);
      const issueBody = `**File:** ${filePath}\n**Error:** ${lintMessage}\n**Rule ID:** ${ruleId}`;
      const labels = ['Lint Detection'];

      if (existingIssuesMap.has(issueTitle)) {
        const existingIssue = existingIssuesMap.get(issueTitle);
        const updatedBody = existingIssue.body.includes(lintMessage)
          ? existingIssue.body
          : `${existingIssue.body}\n\n**Additional Issue:** ${lintMessage}`;

        if (updatedBody !== existingIssue.body) {
          await octokit.issues.update({
            owner: REPO_OWNER,
            repo: REPO_NAME,
            issue_number: existingIssue.number,
            body: updatedBody,
          });
        }
      } else {
        await octokit.issues.create({
          owner: REPO_OWNER,
          repo: REPO_NAME,
          title: issueTitle,
          body: issueBody,
          labels,
        });
      }
Comment on lines +45 to +80
Copy link

Copilot AI Jan 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GitHub API calls inside the loop are not rate-limited or batched, which could hit GitHub API rate limits when processing many lint errors. Consider batching updates or adding delay between API calls to avoid rate limiting issues, especially in repositories with many lint errors.

Copilot uses AI. Check for mistakes.
    }

    for (let [title, issue] of existingIssuesMap) {
      const shortFilePath = title.match(/-([^ ]*) on/)[1];
      if (!treeOutput.some(line => line.includes(shortFilePath))) {
        await octokit.issues.update({
          owner: REPO_OWNER,
          repo: REPO_NAME,
          issue_number: issue.number,
          state: 'closed',
        });
      }
    }

    console.log('Issues updated successfully.');
  } catch (e) {
    console.error('Error managing lint issues:', e.message);
  }
})();
Loading