
Scaling gitPlumbers: The Angular 20+ Code Analysis Platform for GitHub Apps, Zip Uploads, and Auto‑Fix Recommendations
How I scaled gitPlumbers into a resilient Nx + Firebase + Docker pipeline that ingests GitHub repos and zip uploads, analyzes code at scale, and generates actionable remediation recommendations.
Rules first, AI optional. If your platform can explain every recommendation, teams will ship the fix today—not next quarter.Back to all posts
I’ve lived the Monday-morning scramble: a director asks if we can scan 900+ repos and tell them which Angular apps can be upgraded to 20 without breaking prod—by Friday. gitPlumbers was built for that moment. It now ingests GitHub repos, accepts zip uploads for air‑gapped audits, runs Dockerized analyzers, and returns clear remediation steps—fast, explainable, and safe.
This is a platform & delivery breakdown of how I scaled it: Angular 20 + Signals/SignalStore on the front end (PrimeNG for data grids), Firebase for the control plane, and a container farm for analyzers. If you need an Angular consultant or want to hire an Angular developer to build similar enterprise tooling, here’s the playbook I actually ship.
The Monday Scene: GitHub Repos, Zip Dumps, and a Deadline
What landed on my desk
gitPlumbers had to scale from boutique audits to an always‑on pipeline. That meant secure GitHub integration, resumable uploads for zips, and analyzers that could fan out to thousands of jobs without melting the UX or the budget.
Hundreds of Angular repos across orgs
A zip dump from a vendor who couldn’t grant GitHub access
A request for actionable, prioritized fixes—not a PDF report
Constraints I treat as non‑negotiable
As companies plan 2025 Angular roadmaps, leadership wants deterministic timelines. That only happens if the platform is observable and the UX is calm under load. Signals and SignalStore do a lot of heavy lifting here.
No tokens in the browser beyond Auth—use a GitHub App + server webhooks
Multi‑tenant isolation with org/project scoping
Deterministic recommendations (rules first, AI optional)
Clear UX: job progress without jitter, cancel/retry, downloadable SARIF/JSON
Why Scaling a Code Analysis Platform Is Hard in 2025
Two ingestion modes, one truth
Both paths must end in the same job orchestration model. A Firestore job document is the single source of truth; analyzers read an artifact URL, write results, and emit progress events.
GitHub App: event‑driven, cheap, secure
Zip uploads: offline/air‑gapped audits, resumable, virus‑scanned
Speed and explainability
We prioritize rule‑based remediation with typed dependency graphs (pnpm-lock.yaml, package.json, tsconfig) and add LLM suggestions behind a feature flag for long‑tail issues. Teams can accept, modify, or ignore with clear diffs.
P95 scan time beats averages for planning
Explainable fixes land faster than black‑box AI
gitPlumbers Architecture: Nx Angular 20, Firebase Control Plane, Docker Analyzers
// libs/state/src/lib/ingestion.store.ts
import { signalStore, withState, withMethods, patchState } from '@ngrx/signals';
import { inject } from '@angular/core';
import { JobsApi } from '../data/jobs.api';
export interface IngestionState {
connectingGitHub: boolean;
uploadProgress: number; // 0-100
queueDepth: number;
recentJobs: { id: string; status: 'queued'|'running'|'done'|'error'; repo?: string }[];
}
const initial: IngestionState = {
connectingGitHub: false,
uploadProgress: 0,
queueDepth: 0,
recentJobs: []
};
export const IngestionStore = signalStore(
withState(initial),
withMethods((store) => {
const api = inject(JobsApi);
return {
async enqueueRepo(owner: string, repo: string) {
patchState(store, { connectingGitHub: true });
try {
const job = await api.createJob({ owner, repo });
patchState(store, { recentJobs: [job, ...store.recentJobs()] });
} finally {
patchState(store, { connectingGitHub: false });
}
},
setUploadProgress(p: number) {
patchState(store, { uploadProgress: p });
},
updateQueueDepth(depth: number) {
patchState(store, { queueDepth: depth });
}
};
})
);Front end: Angular 20 + Signals/SignalStore
The UI is an Angular 20 app with Signals to avoid over‑rendering when thousands of job toasts start flying. PrimeNG gives me production‑grade grids and filters out of the box.
Nx workspace with libs for models, API, and state
PrimeNG DataTable for results, TabView for per‑repo insights
SignalStore for ingestion and job orchestration state
Control plane: Firebase
Functions receive GitHub webhooks, enqueue tasks, and write jobs. Storage handles large zips with resumable uploads; an antivirus step (ClamAV in Cloud Run) protects the cluster.
Auth (GitHub/Email)
Firestore (jobs, results, tenants)
Storage (zip artifacts)
Functions + Cloud Tasks (webhooks, fan‑out)
Optional: Cloud Run for heavy services
Analyzers: Dockerized workers
Workers are ephemeral; they pull artifacts, run rules, and push results back. Horizontal scale is a knob, not a rewrite.
Node.js and .NET analyzers for framework‑specific checks
Contracts via a typed JSON schema for inputs/outputs
Results emitted as SARIF + JSON for UI and IDE consumption
Secure GitHub Ingestion: App Install, OAuth, Webhooks
// functions/src/webhooks.ts
import * as functions from 'firebase-functions/v2/https';
import { Octokit } from 'octokit';
import { getAppJwt, mintInstallationToken, enqueueJob } from './lib/github';
export const githubWebhook = functions.onRequest(async (req, res) => {
const event = req.headers['x-github-event'];
const installationId = req.body.installation?.id;
if (!installationId) return res.status(400).send('no installation');
const token = await mintInstallationToken(installationId);
const octokit = new Octokit({ auth: token });
const repo = req.body.repository?.full_name;
const sha = req.body.after || req.body.pull_request?.head?.sha;
await enqueueJob({ repo, sha, installationId });
return res.status(202).send('enqueued');
});Install and permissions
Enterprise clients love the audit trail a GitHub App provides. We store only the installation ID; tokens are minted just‑in‑time in Functions.
Use a GitHub App with repo:read, checks:write, metadata:read
Avoid PATs in the browser; redirect to server‑side OAuth
Webhook handler and fan‑out
One event → many checks. We batch by repo and branch to avoid duplicate work during busy merges.
Receive push and pull_request events
Debounce noisy repos; coalesce commits
Enqueue Firestore jobs via Cloud Tasks
Zip Uploads That Don’t Crash Browsers or Budgets
// apps/web/src/app/upload/upload.component.ts
@Component({ selector: 'gp-upload', templateUrl: './upload.html' })
export class UploadComponent {
store = inject(IngestionStore);
async onFile(file: File) {
const { ref, uploadBytesResumable, getDownloadURL } = await import('firebase/storage');
const r = ref(storage, `artifacts/${crypto.randomUUID()}/${file.name}`);
const task = uploadBytesResumable(r, file);
task.on('state_changed', s => this.store.setUploadProgress(Math.round(100*s.bytesTransferred/s.totalBytes)));
await task;
const url = await getDownloadURL(r);
await this.store.enqueueRepo('zip','artifact:'+url); // unified path through job queue
}
}Client: resumable + Signals for calm UX
Zip uploads are for vendors, air‑gapped teams, or historical bundles. Progress and cancel/retry are first‑class.
Firebase Storage resumable uploads
SignalStore to show progress without jank
PrimeNG ProgressBar for clarity
Server: antivirus and artifact URLs
Artifacts never hit analyzer containers until they’re scanned. Results are attached back to the job doc for the UI to stream.
ClamAV in Cloud Run for scanning
Time‑scoped signed URLs passed to analyzers
Automated Remediation: Rules First, LLMs Optional
# rules/angular-upgrade.yaml
- id: rxjs-8-imports
match: "import { of, from, map } from 'rxjs'"
suggest: "Use path imports: 'rxjs/of', 'rxjs/map'"
autofix:
type: codemod
command: npx rxjs-ts-morph-codemod --target=8
docs: https://rxjs.dev/guides/v8-migration
- id: zone-cleanup
match: tsconfig.json
suggest: "Consider zoneless + Signals; migrate change detection incrementally"
docs: https://angular.dev/guide/going-zonelessExplainable rules
We ship a rule pack for Angular 9→20 upgrades, RxJS 7→8 changes, zone.js cleanup, and PrimeNG theming migrations.
Typed rules over AST and dependency graphs
Deterministic diffs as patches/PRs
When AI helps
LLM suggestions are annotated with confidence and links to docs. Teams can disable per‑tenant.
Long‑tail suggestions behind a feature flag
Safety: rate limits, content filters, retries with taxonomy
CI/CD and Scale: From One Repo to Thousands
# .github/workflows/gitplumbers-scan.yml
name: gitPlumbers Scan
on: [pull_request]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with: { version: 9 }
- run: pnpm i --frozen-lockfile
- name: Upload lockfiles for dependency analysis
run: |
curl -X POST "$GP_API/jobs" \
-H "Authorization: Bearer ${{ secrets.GP_TOKEN }}" \
-F repo=${{ github.repository }} \
-F sha=${{ github.sha }} \
-F lock=@pnpm-lock.yaml \
-F pkg=@package.jsonKick scans from CI
We keep compute near code. A lightweight CI step triggers scans and uploads lockfiles.
Checks API comments on PRs
Artifacts uploaded once; reused by analyzers
Autoscale analyzers
Bursty traffic is normal after branch cutoffs. Autoscaling saves cost while keeping P95 under target.
Cloud Run minInstances=0, maxInstances tuned
Warm caches for pnpm/npm
Observability and Metrics That Keep You Honest
Measure what matters
Angular DevTools and Lighthouse don’t matter here—latency and clarity do. In the UI, Signals stream job state while we chart throughput with PrimeNG + Highcharts.
P95 scan time per repo size bucket
Queue depth and time‑to‑first‑result
Recommendation acceptance rate
Cost per 100 scans
Telemetry and alerting
When a rule regresses, we can roll it back in seconds with Firebase Remote Config.
OpenTelemetry traces from Functions and analyzers
Firebase Logs‑based alerts to Slack
Feature flags for risky rules
When to Hire an Angular Developer for Legacy Rescue
You likely need help if
This is where an Angular expert earns their keep. If you need to stabilize and modernize fast, I can step in as a remote Angular developer or Angular consultant and get you to green builds without outages. See how we can "stabilize your Angular codebase" at gitPlumbers.
Your repos span Angular 9–15 and you can’t inventory debt
CI is flaky after AI‑generated refactors
You need deterministic migration plans with rollbacks
Engagement patterns that work
Discovery call within 48 hours. Assessment in 1 week. Pilot org in 2–4 weeks. Then scale.
2–4 week assessment with dashboards and rule packs
4–8 week upgrade/migration sprints
Ongoing CI policy + analyzer tuning
Example Walkthrough: Scanning a Telecom Analytics Repo
From webhook to pull request comment
In one recent run (ads analytics platform for a telecom provider), P95 was 6m12s across 130 repos. 72% of autofixes merged cleanly; the rest generated PRs with code diffs and screening notes for reviewers.
Webhook enqueues job → analyzer pulls lockfiles → rules run → SARIF posted
UX under load
The UI stayed at 60fps on mid‑range laptops during multi‑org scans. That’s the difference Signals + careful change detection make.
Signals kept render counts low; no spinner storms
PrimeNG DataTable virtualized 25k+ findings
Practical Takeaways and Next Instrumentation
If you copy one thing, copy this
You can add fancy later. Deterministic foundations pay off forever.
Single job model for both GitHub and zips
Rules first, AI optional
SignalStore for calm, reliable state
What to instrument next
Tie every metric back to business outcomes—faster upgrades, fewer outages, lower CI cost.
Auto‑PR merge rate vs. revert rate
Time to first green build after recommendations
Tenant‑level cost and cache hit ratios
Key takeaways
- Use a GitHub App for secure, event-driven ingestion; zip uploads cover private/offline repos.
- Model all ingestion and scan state with SignalStore to avoid jittery UX under load.
- Separate the analyzer farm (Docker) from the control plane (Firebase/Firestore) to scale safely.
- Blend static rules with typed dependency graphs for fast, explainable remediation; keep LLMs optional.
- Instrument P95 scan time, queue depth, and recommendation acceptance rate to target real outcomes.
Implementation checklist
- Register a GitHub App with repo:read, checks:write, and webhooks for push/pull_request.
- Provision Firebase: Auth (GitHub + Email), Firestore (multi-tenant), Storage (resumable uploads), Functions (webhooks), Cloud Tasks/Run (worker fan-out).
- Create an Nx monorepo: Angular 20+ app, shared libs, analyzer contracts, and Firebase Functions.
- Implement SignalStore for ingestion + job orchestration state; use PrimeNG to visualize jobs/queues.
- Build Dockerized analyzers (Node.js/.NET) that pull artifacts, run rules, post results.
- Set CI with GitHub Actions to trigger scans, build/push analyzer images, and e2e with Cypress.
- Add observability: OpenTelemetry traces, Firebase Logs, custom metrics for P95 and queue depth.
- Gate releases with feature flags; ship incrementally (org-level pilots before global enablement).
Questions we hear from teams
- How much does it cost to hire an Angular developer to build a code analysis platform?
- Most teams start with a 2–4 week assessment ($12k–$30k) to validate architecture and ROI, then 4–8 week delivery sprints. Fixed‑fee pilots are available for one org or 50–100 repos. I’m a remote Angular consultant and can scope quickly after a 30‑minute call.
- How long does GitHub App integration and zip upload support take?
- A secure GitHub App with webhooks typically ships in 3–5 days. Zip uploads with resumable storage and antivirus add 2–3 days. End‑to‑end with dashboards and SignalStore usually fits in a 2‑week sprint if environments are ready.
- What does automated remediation include?
- Deterministic rules for Angular upgrades, RxJS 8 changes, zone.js cleanup, and PrimeNG theming. Optional AI suggestions are gated by feature flags. Output is SARIF/JSON and PRs with diffs so reviewers can accept or tweak confidently.
- Will this work with our CI/CD (GitHub Actions, Jenkins, Azure DevOps)?
- Yes. We use a simple API trigger and artifact upload pattern that ports to GitHub Actions, Jenkins, and Azure DevOps. Analyzers run in Docker, so you can host on AWS/GCP/Azure or on‑prem. Observability is via OpenTelemetry and Firebase Logs.
- What’s involved in a typical engagement?
- Discovery call within 48 hours. Assessment deck and metrics in 1 week. Pilot org scans in weeks 2–4. Rollout with CI policy and rule tuning in weeks 4–8. I can continue as an Angular contractor to maintain analyzers and dashboards.
Ready to level up your Angular experience?
Let AngularUX review your Signals roadmap, design system, or SSR deployment plan.
NG Wave
Angular Component Library
A comprehensive collection of 110+ animated, interactive, and customizable Angular components. Converted from React Bits with full feature parity, built with Angular Signals, GSAP animations, and Three.js for stunning visual effects.
Explore Components