From d0000fa60345aca90c713ef61341bb79489d9f27 Mon Sep 17 00:00:00 2001 From: kpj2006 <24ucs074@lnmiit.ac.in> Date: Sun, 5 Jul 2026 04:18:01 +0530 Subject: [PATCH 1/8] feat: add Lighthouse CI workflow and configuration for automated performance auditing --- .github/workflows/lighthouse.yml | 37 ++++++++++++++++++++++++++++++++ .gitignore | 1 + lighthouserc.json | 19 ++++++++++++++++ 3 files changed, 57 insertions(+) create mode 100644 .github/workflows/lighthouse.yml create mode 100644 lighthouserc.json diff --git a/.github/workflows/lighthouse.yml b/.github/workflows/lighthouse.yml new file mode 100644 index 0000000..731f6c9 --- /dev/null +++ b/.github/workflows/lighthouse.yml @@ -0,0 +1,37 @@ +name: Lighthouse CI Audit + +on: + pull_request: + branches: + - main + workflow_dispatch: + +concurrency: + group: lighthouse-${{ github.ref }} + cancel-in-progress: true + +jobs: + lighthouse: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Build application + run: npm run build + + - name: Run Lighthouse CI + uses: treosh/lighthouse-ci-action@v12 + with: + configPath: './lighthouserc.json' + uploadTargets: 'temporary-public-storage' diff --git a/.gitignore b/.gitignore index 216a31b..1ecbf67 100644 --- a/.gitignore +++ b/.gitignore @@ -380,6 +380,7 @@ logs/ coverage/ playwright-report/ test-results/ +.lighthouseci/ # =============================== # IDE / Editor diff --git a/lighthouserc.json b/lighthouserc.json new file mode 100644 index 0000000..0d5a179 --- /dev/null +++ b/lighthouserc.json @@ -0,0 +1,19 @@ +{ + "ci": { + "collect": { + "staticDistDir": "./dist", + "numberOfRuns": 3 + }, + "upload": { + "target": "temporary-public-storage" + }, + "assert": { + "assertions": { + "categories:performance": ["warn", { "minScore": 0.75 }], + "categories:accessibility": ["error", { "minScore": 0.8 }], + "categories:best-practices": ["error", { "minScore": 0.85 }], + "categories:seo": ["error", { "minScore": 0.85 }] + } + } + } +} From 243d12c83773bd8a5dd810bb4a3b2c2320f8d2c8 Mon Sep 17 00:00:00 2001 From: kpj2006 <24ucs074@lnmiit.ac.in> Date: Sun, 5 Jul 2026 04:27:12 +0530 Subject: [PATCH 2/8] Update .github/workflows/lighthouse.yml Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .github/workflows/lighthouse.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/lighthouse.yml b/.github/workflows/lighthouse.yml index 731f6c9..cc46110 100644 --- a/.github/workflows/lighthouse.yml +++ b/.github/workflows/lighthouse.yml @@ -13,10 +13,14 @@ concurrency: jobs: lighthouse: runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout repository uses: actions/checkout@v4 + with: + persist-credentials: false - name: Setup Node.js uses: actions/setup-node@v4 From f6c1a0d725acbc41d673c4c3d41056b917c0a36d Mon Sep 17 00:00:00 2001 From: kpj2006 <24ucs074@lnmiit.ac.in> Date: Sun, 5 Jul 2026 05:01:44 +0530 Subject: [PATCH 3/8] Update .github/workflows/lighthouse.yml Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .github/workflows/lighthouse.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lighthouse.yml b/.github/workflows/lighthouse.yml index cc46110..a558877 100644 --- a/.github/workflows/lighthouse.yml +++ b/.github/workflows/lighthouse.yml @@ -38,4 +38,4 @@ jobs: uses: treosh/lighthouse-ci-action@v12 with: configPath: './lighthouserc.json' - uploadTargets: 'temporary-public-storage' + temporaryPublicStorage: true From fbd9b75b21fa6f2648d1042b8b7819bad03b2c28 Mon Sep 17 00:00:00 2001 From: kpj2006 <24ucs074@lnmiit.ac.in> Date: Sun, 5 Jul 2026 05:17:34 +0530 Subject: [PATCH 4/8] pin correct sha --- .github/workflows/lighthouse.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lighthouse.yml b/.github/workflows/lighthouse.yml index a558877..2182f15 100644 --- a/.github/workflows/lighthouse.yml +++ b/.github/workflows/lighthouse.yml @@ -18,12 +18,12 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 with: persist-credentials: false - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 with: node-version: 22 cache: npm @@ -35,7 +35,7 @@ jobs: run: npm run build - name: Run Lighthouse CI - uses: treosh/lighthouse-ci-action@v12 + uses: treosh/lighthouse-ci-action@3e7e23fb74242897f95c0ba9cabad3d0227b9b18 with: configPath: './lighthouserc.json' temporaryPublicStorage: true From 82014e7367cf5d9901c63684c6281400f84541c2 Mon Sep 17 00:00:00 2001 From: kpj2006 <24ucs074@lnmiit.ac.in> Date: Sun, 5 Jul 2026 06:06:13 +0530 Subject: [PATCH 5/8] automated Lighthouse performance reporting badges --- .../scripts/generate-lighthouse-badges.cjs | 119 ++++++++++++++++++ .github/workflows/lighthouse.yml | 20 ++- README.md | 28 ++++- badges/lighthouse-accessibility.svg | 1 + badges/lighthouse-best-practices.svg | 1 + badges/lighthouse-performance.svg | 1 + badges/lighthouse-pwa.svg | 1 + badges/lighthouse-seo.svg | 1 + badges/lighthouse.svg | 1 + 9 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 .github/scripts/generate-lighthouse-badges.cjs create mode 100644 badges/lighthouse-accessibility.svg create mode 100644 badges/lighthouse-best-practices.svg create mode 100644 badges/lighthouse-performance.svg create mode 100644 badges/lighthouse-pwa.svg create mode 100644 badges/lighthouse-seo.svg create mode 100644 badges/lighthouse.svg diff --git a/.github/scripts/generate-lighthouse-badges.cjs b/.github/scripts/generate-lighthouse-badges.cjs new file mode 100644 index 0000000..a21266f --- /dev/null +++ b/.github/scripts/generate-lighthouse-badges.cjs @@ -0,0 +1,119 @@ +const fs = require('fs'); +const path = require('path'); +const https = require('https'); + +// Path to LHCI manifest and output directory +const manifestPath = path.join(__dirname, '../../.lighthouseci/manifest.json'); +const outputDir = path.join(__dirname, '../../badges'); + +// Ensure output directory exists +if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); +} + +/** + * Downloads a badge from Shields.io + * @param {string} label + * @param {string} value + * @param {string} color + * @returns {Promise} + */ +function downloadBadge(label, value, color) { + const url = `https://img.shields.io/badge/${encodeURIComponent(label)}-${encodeURIComponent(value)}-${color}`; + const filename = `${label.toLowerCase().replace(/%20/g, '-').replace(/ /g, '-')}.svg`; + const filePath = path.join(outputDir, filename); + + return new Promise((resolve, reject) => { + https.get(url, { headers: { 'User-Agent': 'NodeJS/LighthouseBadgeGenerator' } }, (res) => { + if (res.statusCode !== 200) { + reject(new Error(`Failed to download ${label} badge: Status code ${res.statusCode}`)); + return; + } + const fileStream = fs.createWriteStream(filePath); + res.pipe(fileStream); + fileStream.on('finish', () => { + fileStream.close(); + console.log(`Successfully downloaded: ${filename} (${value})`); + resolve(); + }); + }).on('error', (err) => { + reject(err); + }); + }); +} + +async function main() { + try { + if (!fs.existsSync(manifestPath)) { + console.error(`Error: Manifest file not found at ${manifestPath}`); + process.exit(1); + } + + const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')); + if (!Array.isArray(manifest) || manifest.length === 0) { + console.error('Error: Manifest is empty or invalid.'); + process.exit(1); + } + + // Find the representative run (median run) or fallback to first run + const run = manifest.find(r => r.isRepresentativeRun) || manifest[0]; + const summary = run.summary; + + if (!summary) { + console.error('Error: No summary found in the representative run.'); + process.exit(1); + } + + // Categories to generate badges for + const categories = { + 'Performance': summary.performance, + 'Accessibility': summary.accessibility, + 'Best Practices': summary['best-practices'], + 'SEO': summary.seo, + 'PWA': summary.pwa + }; + + let totalScore = 0; + let count = 0; + + for (const [name, score] of Object.entries(categories)) { + if (score === undefined || score === null) { + console.log(`Skipping category ${name} (no score available)`); + continue; + } + + const percentage = Math.round(score * 100); + totalScore += percentage; + count++; + + // Determine color according to Lighthouse standards + let color = 'ff3333'; // Red (0-49) + if (percentage >= 90) { + color = '00cc66'; // Green (90-100) + } else if (percentage >= 50) { + color = 'ffaa33'; // Orange (50-89) + } + + await downloadBadge(`Lighthouse ${name}`, `${percentage}%`, color); + } + + // Generate single aggregate score badge + if (count > 0) { + const average = Math.round(totalScore / count); + let color = 'ff3333'; + if (average >= 90) { + color = '00cc66'; + } else if (average >= 50) { + color = 'ffaa33'; + } + await downloadBadge('Lighthouse', `${average}%`, color); + } + + console.log('Lighthouse badges generated successfully!'); + } catch (error) { + console.error('Error generating badges:', error); + process.exit(1); + } +} + +main(); diff --git a/.github/workflows/lighthouse.yml b/.github/workflows/lighthouse.yml index 2182f15..9100cfb 100644 --- a/.github/workflows/lighthouse.yml +++ b/.github/workflows/lighthouse.yml @@ -1,6 +1,9 @@ name: Lighthouse CI Audit on: + push: + branches: + - main pull_request: branches: - main @@ -14,13 +17,11 @@ jobs: lighthouse: runs-on: ubuntu-latest permissions: - contents: read + contents: write steps: - name: Checkout repository uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 - with: - persist-credentials: false - name: Setup Node.js uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 @@ -39,3 +40,16 @@ jobs: with: configPath: './lighthouserc.json' temporaryPublicStorage: true + + - name: Generate Lighthouse Badges + run: node .github/scripts/generate-lighthouse-badges.cjs + + - name: Commit and Push Badges + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + run: | + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + git add badges/ + git commit -m "chore: update lighthouse badges [skip ci]" || echo "No changes to commit" + git push origin HEAD:${{ github.ref_name }} + diff --git a/README.md b/README.md index 7cb9cea..ca05680 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,15 @@ +
+ Lighthouse Score   + Lighthouse Performance   + Lighthouse Accessibility   + Lighthouse Best Practices   + Lighthouse SEO   + Lighthouse PWA +
+ --- **OrgExplorer** transforms GitHub organizations into interactive, visual intelligence dashboards. Explore repository relationships, compare two or more organizations, contributor networks, activity trends, risk metrics, and organizational health—all without leaving your browser. @@ -294,7 +303,24 @@ Dashboard renders visual intelligence Open http://localhost:5173 in your browser. -3. **Risk Assessment** +3. **Docker Deployment (Optional)** + + If you want to host OrgExplorer locally or in your own containerized infrastructure: + + * **Using Docker Compose (Recommended)**: + ```bash + docker compose up --build -d + ``` + Open http://localhost:8080 in your browser. + + * **Using Docker CLI**: + ```bash + docker build -t orgexplorer . + docker run -d -p 8080:80 orgexplorer + ``` + Open http://localhost:8080 in your browser. + +4. **Risk Assessment** - Open bus factor panel - Detect low contributor redundancy - Review critical repositories diff --git a/badges/lighthouse-accessibility.svg b/badges/lighthouse-accessibility.svg new file mode 100644 index 0000000..1d5d14e --- /dev/null +++ b/badges/lighthouse-accessibility.svg @@ -0,0 +1 @@ +Lighthouse Accessibility: 90%Lighthouse Accessibility90% \ No newline at end of file diff --git a/badges/lighthouse-best-practices.svg b/badges/lighthouse-best-practices.svg new file mode 100644 index 0000000..7082396 --- /dev/null +++ b/badges/lighthouse-best-practices.svg @@ -0,0 +1 @@ +Lighthouse Best Practices: 88%Lighthouse Best Practices88% \ No newline at end of file diff --git a/badges/lighthouse-performance.svg b/badges/lighthouse-performance.svg new file mode 100644 index 0000000..987200a --- /dev/null +++ b/badges/lighthouse-performance.svg @@ -0,0 +1 @@ +Lighthouse Performance: 95%Lighthouse Performance95% \ No newline at end of file diff --git a/badges/lighthouse-pwa.svg b/badges/lighthouse-pwa.svg new file mode 100644 index 0000000..4cdb537 --- /dev/null +++ b/badges/lighthouse-pwa.svg @@ -0,0 +1 @@ +Lighthouse PWA: 50%Lighthouse PWA50% \ No newline at end of file diff --git a/badges/lighthouse-seo.svg b/badges/lighthouse-seo.svg new file mode 100644 index 0000000..843c72b --- /dev/null +++ b/badges/lighthouse-seo.svg @@ -0,0 +1 @@ +Lighthouse SEO: 100%Lighthouse SEO100% \ No newline at end of file diff --git a/badges/lighthouse.svg b/badges/lighthouse.svg new file mode 100644 index 0000000..1f4a227 --- /dev/null +++ b/badges/lighthouse.svg @@ -0,0 +1 @@ +Lighthouse: 85%Lighthouse85% \ No newline at end of file From 92c25c297e97e4d1a43e68df38c2cf6b412dcc41 Mon Sep 17 00:00:00 2001 From: kpj2006 <24ucs074@lnmiit.ac.in> Date: Sun, 5 Jul 2026 09:29:11 +0530 Subject: [PATCH 6/8] Update .github/scripts/generate-lighthouse-badges.cjs Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .github/scripts/generate-lighthouse-badges.cjs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/scripts/generate-lighthouse-badges.cjs b/.github/scripts/generate-lighthouse-badges.cjs index a21266f..bb5b79b 100644 --- a/.github/scripts/generate-lighthouse-badges.cjs +++ b/.github/scripts/generate-lighthouse-badges.cjs @@ -24,21 +24,24 @@ function downloadBadge(label, value, color) { const filePath = path.join(outputDir, filename); return new Promise((resolve, reject) => { - https.get(url, { headers: { 'User-Agent': 'NodeJS/LighthouseBadgeGenerator' } }, (res) => { + const req = https.get(url, { headers: { 'User-Agent': 'NodeJS/LighthouseBadgeGenerator' }, timeout: 10000 }, (res) => { if (res.statusCode !== 200) { + res.resume(); reject(new Error(`Failed to download ${label} badge: Status code ${res.statusCode}`)); return; } const fileStream = fs.createWriteStream(filePath); + res.on('error', reject); + fileStream.on('error', reject); res.pipe(fileStream); fileStream.on('finish', () => { fileStream.close(); console.log(`Successfully downloaded: ${filename} (${value})`); resolve(); }); - }).on('error', (err) => { - reject(err); }); + req.on('error', reject); + req.on('timeout', () => req.destroy(new Error(`Timed out downloading ${label} badge`))); }); } From 535de6d4d50c32cc2b77760e7e9d2ad9eb29b811 Mon Sep 17 00:00:00 2001 From: kpj2006 <24ucs074@lnmiit.ac.in> Date: Sun, 5 Jul 2026 09:47:30 +0530 Subject: [PATCH 7/8] Update .github/workflows/lighthouse.yml Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .github/workflows/lighthouse.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lighthouse.yml b/.github/workflows/lighthouse.yml index 9100cfb..f0015e9 100644 --- a/.github/workflows/lighthouse.yml +++ b/.github/workflows/lighthouse.yml @@ -46,10 +46,12 @@ jobs: - name: Commit and Push Badges if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + env: + REF_NAME: ${{ github.ref_name }} run: | - git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.email "github-actions[bot]`@users.noreply.github.com`" git config --local user.name "github-actions[bot]" git add badges/ git commit -m "chore: update lighthouse badges [skip ci]" || echo "No changes to commit" - git push origin HEAD:${{ github.ref_name }} + git push origin HEAD:"$REF_NAME" From 80dbf1c189b0185eaa03dabbea2f0a8c60f11743 Mon Sep 17 00:00:00 2001 From: kpj2006 <24ucs074@lnmiit.ac.in> Date: Sun, 5 Jul 2026 09:50:31 +0530 Subject: [PATCH 8/8] remove the redundant .replace(/%20/g, '-') --- .github/scripts/generate-lighthouse-badges.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/generate-lighthouse-badges.cjs b/.github/scripts/generate-lighthouse-badges.cjs index a21266f..4aaa56b 100644 --- a/.github/scripts/generate-lighthouse-badges.cjs +++ b/.github/scripts/generate-lighthouse-badges.cjs @@ -20,7 +20,7 @@ if (!fs.existsSync(outputDir)) { */ function downloadBadge(label, value, color) { const url = `https://img.shields.io/badge/${encodeURIComponent(label)}-${encodeURIComponent(value)}-${color}`; - const filename = `${label.toLowerCase().replace(/%20/g, '-').replace(/ /g, '-')}.svg`; + const filename = `${label.toLowerCase().replace(/ /g, '-')}.svg`; const filePath = path.join(outputDir, filename); return new Promise((resolve, reject) => {