diff --git a/.github/workflows/lint-detection.yml b/.github/workflows/lint-detection.yml new file mode 100644 index 0000000..29294d7 --- /dev/null +++ b/.github/workflows/lint-detection.yml @@ -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 + +    # 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 }} diff --git a/scripts/manageLintIssues.js b/scripts/manageLintIssues.js new file mode 100644 index 0000000..9fae7c4 --- /dev/null +++ b/scripts/manageLintIssues.js @@ -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, +        }); +      } +    } + +    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); +  } +})();