From 604b3d6702aa60c94f7475c1fe933878f1a4decd Mon Sep 17 00:00:00 2001 From: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com> Date: Mon, 22 Sep 2025 14:47:34 +0200 Subject: [PATCH] refactor: replace bash parsing with JavaScript script - Create .github/scripts/parse-metrics.mjs for robust markdown parsing - Replace complex bash/awk parsing with proper JavaScript logic - Better error handling and debug output - Should correctly parse time values and handle edge cases --- .github/scripts/parse-metrics.mjs | 88 ++++++++++++++++++++ .github/workflows/weekly-metrics-discord.yml | 41 +-------- 2 files changed, 89 insertions(+), 40 deletions(-) create mode 100644 .github/scripts/parse-metrics.mjs diff --git a/.github/scripts/parse-metrics.mjs b/.github/scripts/parse-metrics.mjs new file mode 100644 index 00000000..b711f5b9 --- /dev/null +++ b/.github/scripts/parse-metrics.mjs @@ -0,0 +1,88 @@ +#!/usr/bin/env node + +import { readFileSync, existsSync } from 'fs'; +import { writeFileSync } from 'fs'; + +function parseMetricsTable(content, metricName) { + const lines = content.split('\n'); + + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + if (line.includes(metricName)) { + // Split by | and get the value column (usually index 2) + const columns = line.split('|').map(col => col.trim()); + if (columns.length >= 3) { + return columns[2] || 'N/A'; + } + } + } + return 'N/A'; +} + +function parseCountMetric(content, metricName) { + const result = parseMetricsTable(content, metricName); + // Try to extract just the number if it's a valid number + const number = parseInt(result); + return isNaN(number) ? 0 : number; +} + +function main() { + const metrics = { + issues_created: 0, + issues_closed: 0, + prs_created: 0, + prs_merged: 0, + avg_first_response: 'N/A', + avg_time_to_close: 'N/A', + pr_avg_merge_time: 'N/A' + }; + + // Parse issue metrics + if (existsSync('issue_metrics.md')) { + const issueContent = readFileSync('issue_metrics.md', 'utf8'); + console.log('DEBUG: Parsing issue metrics...'); + + metrics.issues_created = parseCountMetric(issueContent, 'Total number of items created'); + metrics.issues_closed = parseCountMetric(issueContent, 'Number of items closed'); + metrics.avg_first_response = parseMetricsTable(issueContent, 'Time to first response'); + metrics.avg_time_to_close = parseMetricsTable(issueContent, 'Time to close'); + + console.log('Issues created:', metrics.issues_created); + console.log('Issues closed:', metrics.issues_closed); + console.log('Avg first response:', metrics.avg_first_response); + console.log('Avg time to close:', metrics.avg_time_to_close); + } else { + console.log('No issue_metrics.md found'); + } + + // Parse PR metrics + if (existsSync('pr_metrics.md')) { + const prContent = readFileSync('pr_metrics.md', 'utf8'); + console.log('DEBUG: Parsing PR metrics...'); + + metrics.prs_created = parseCountMetric(prContent, 'Total number of items created'); + metrics.prs_merged = parseCountMetric(prContent, 'Number of items closed'); + metrics.pr_avg_merge_time = parseMetricsTable(prContent, 'Time to close'); + + console.log('PRs created:', metrics.prs_created); + console.log('PRs merged:', metrics.prs_merged); + console.log('PR avg merge time:', metrics.pr_avg_merge_time); + } else { + console.log('No pr_metrics.md found'); + } + + // Output for GitHub Actions + const output = Object.entries(metrics) + .map(([key, value]) => `${key}=${value}`) + .join('\n'); + + console.log('\nFinal metrics:'); + console.log(output); + + // Write to GITHUB_OUTPUT if in GitHub Actions + if (process.env.GITHUB_OUTPUT) { + writeFileSync(process.env.GITHUB_OUTPUT, output + '\n', { flag: 'a' }); + } +} + +main(); \ No newline at end of file diff --git a/.github/workflows/weekly-metrics-discord.yml b/.github/workflows/weekly-metrics-discord.yml index 4f0a3c32..9e688802 100644 --- a/.github/workflows/weekly-metrics-discord.yml +++ b/.github/workflows/weekly-metrics-discord.yml @@ -45,46 +45,7 @@ jobs: - name: Parse metrics id: metrics - run: | - # Parse the metrics from the generated markdown files - if [ -f "issue_metrics.md" ]; then - echo "DEBUG: issue_metrics.md content:" - head -20 issue_metrics.md - echo "DEBUG: Lines with 'Time to first response':" - grep "Time to first response" issue_metrics.md || echo "No matches found" - echo "DEBUG: Lines with 'Time to close':" - grep "Time to close" issue_metrics.md || echo "No matches found" - - # Extract key metrics using grep/awk - AVG_TIME_TO_FIRST_RESPONSE=$(grep "Time to first response" issue_metrics.md | awk -F'|' '{print $3}' | xargs || echo "N/A") - AVG_TIME_TO_CLOSE=$(grep "Time to close" issue_metrics.md | awk -F'|' '{print $3}' | xargs || echo "N/A") - NUM_ISSUES_CREATED=$(grep "Total number of items created" issue_metrics.md | awk -F'|' '{print $3}' | xargs || echo "0") - NUM_ISSUES_CLOSED=$(grep "Number of items closed" issue_metrics.md | awk -F'|' '{print $3}' | xargs || echo "0") - else - NUM_ISSUES_CREATED=0 - NUM_ISSUES_CLOSED=0 - AVG_TIME_TO_FIRST_RESPONSE="N/A" - AVG_TIME_TO_CLOSE="N/A" - fi - - if [ -f "pr_metrics.md" ]; then - PR_AVG_TIME_TO_MERGE=$(grep "Time to close" pr_metrics.md | awk -F'|' '{print $3}' | xargs || echo "N/A") - NUM_PRS_CREATED=$(grep "Total number of items created" pr_metrics.md | awk -F'|' '{print $3}' | xargs || echo "0") - NUM_PRS_MERGED=$(grep "Number of items closed" pr_metrics.md | awk -F'|' '{print $3}' | xargs || echo "0") - else - NUM_PRS_CREATED=0 - NUM_PRS_MERGED=0 - PR_AVG_TIME_TO_MERGE="N/A" - fi - - # Set outputs for Discord action - echo "issues_created=${NUM_ISSUES_CREATED:-0}" >> $GITHUB_OUTPUT - echo "issues_closed=${NUM_ISSUES_CLOSED:-0}" >> $GITHUB_OUTPUT - echo "prs_created=${NUM_PRS_CREATED:-0}" >> $GITHUB_OUTPUT - echo "prs_merged=${NUM_PRS_MERGED:-0}" >> $GITHUB_OUTPUT - echo "avg_first_response=${AVG_TIME_TO_FIRST_RESPONSE:-N/A}" >> $GITHUB_OUTPUT - echo "avg_time_to_close=${AVG_TIME_TO_CLOSE:-N/A}" >> $GITHUB_OUTPUT - echo "pr_avg_merge_time=${PR_AVG_TIME_TO_MERGE:-N/A}" >> $GITHUB_OUTPUT + run: node .github/scripts/parse-metrics.mjs - name: Send to Discord uses: sarisia/actions-status-discord@v1