feat: add DevLake DORA Metrics plugin#8364
Open
mikilior wants to merge 11 commits intobackstage:mainfrom
Open
Conversation
Add new workspace with three packages: - @backstage-community/plugin-devlake: Frontend dashboard with DORA metric cards and trend charts - @backstage-community/plugin-devlake-backend: Backend plugin proxying Apache DevLake API - @backstage-community/plugin-devlake-common: Shared types and DORA level classifiers Closes backstage#8189 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: mikilior <mikilior@gmail.com>
- Replace REST API client with direct MySQL queries via mysql2 - Query DevLake domain layer tables (cicd_deployment_commits, project_pr_metrics, incidents) - Add "All" team option to aggregate across all projects - Add 1Y time range preset - Remove PRODUCTION environment filter (environments are not standardized) - Use pr.merged_date for lead time (not deployment date) - Add helpful no-data messages per metric type - Export MetricCard, MetricChart, TeamSelector, TimeRangeSelector components - Update API reports and tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: mikilior <mikilior@gmail.com>
Add alpha.ts and src/alpha/ to support the Backstage New Frontend System: - PageBlueprint wraps DoraMetricsPage via compatWrapper (no App.tsx route needed) - ApiBlueprint registers devlakeApiRef via the NFS DI system - Plugin is auto-discoverable and path is configurable via app-config Adopters on the legacy system are unaffected (src/index.ts unchanged). Signed-off-by: mikilior <mikilior@gmail.com>
Adds a compact DORA metrics card that renders on entity pages annotated with `devlake.io/project-name`. Supports both the legacy and New Frontend System extension points. - EntityDoraCard component: 2x2 grid of DORA metrics with level chips - MissingAnnotationEmptyState when annotation is absent - Optional Grafana deep-link per project via app-config (devlake.grafana.baseUrl / devlake.grafana.doraDashboardPath) - EntityCardBlueprint NFS wiring (entityDoraCard) - Legacy createComponentExtension wiring in plugin.ts - Exports: EntityDoraCard, EntityDoraCardProps, isDevlakeAvailable, DEVLAKE_PROJECT_NAME_ANNOTATION - New deps: @backstage/catalog-model, @backstage/plugin-catalog-react - config.d.ts updated with grafana config schema Signed-off-by: mikilior <mikilior@gmail.com>
Adds 9 new test files covering the frontend plugin, backend plugin, and common utilities. Total: 81 tests across 12 suites. Frontend: - constants.test.ts: isDevlakeAvailable predicate + annotation constant - api/DevlakeClient.test.ts: all 3 API methods (success + error paths) - components/TeamSelector: render with teams and selected value - components/TimeRangeSelector: preset buttons, date inputs, callbacks - components/MetricChart: render with mocked recharts - components/EntityDoraCard: missing annotation, loading, metrics, N/A state, Grafana link, error panel, API call params - pages/DoraMetricsPage: title, metric cards, error handling Backend: - service/DevlakeDbClient.test.ts: pool creation, getDoraMetrics (4 parallel queries, null rows, level classification), getDoraTrend, close() - types/config.test.ts: readDevlakeConfig (db fields, defaults, teams, missing config errors) Signed-off-by: mikilior <mikilior@gmail.com>
Signed-off-by: mikilior <mikilior@gmail.com>
Contributor
Changed Packages
|
Signed-off-by: mikilior <mikilior@gmail.com>
Signed-off-by: mikilior <mikilior@gmail.com>
- Remove unused renderCard variable (TS6133 noUnusedLocals)
- Add @types/lodash devDependency to fix recharts type resolution (TS7016)
- Add NoInfer<T> polyfill in types/global.d.ts for TS 5.3 compat (TS2304)
- Override knex resolution via tsconfig paths to CJS types so
@backstage/backend-plugin-api's { Knex } import resolves correctly
with moduleResolution: bundler (TS2724)
- Exclude types/ dir from ESLint (declaration files need no linting)
Signed-off-by: mikilior <mikilior@gmail.com>
- Remove @material-ui/lab (unused — only @material-ui/core and icons used) - Remove msw (unused — API is mocked via jest.fn() in all tests) - Replace @types/lodash devDep with a minimal ambient module stub in types/global.d.ts, satisfying recharts' DebouncedFunc import under tsc --skipLibCheck false without an unnecessary direct dependency - Commit generated knip-report.md (now clean — no unused deps) Signed-off-by: mikilior <mikilior@gmail.com>
- Replace deprecated MissingAnnotationEmptyState from @backstage/core-components with the current version from @backstage/plugin-catalog-react - Explicitly type EntityDoraCard as ComponentType<EntityDoraCardProps> to eliminate ae-forgotten-export warning from API Extractor (was inferring internal EntityDoraCard_2 type that API Extractor couldn't name) - Add report-alpha.api.md for /alpha entry point (auto-generated) - Update report.api.md with corrected EntityDoraCard signature Signed-off-by: mikilior <mikilior@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DevLake DORA Metrics Plugin
Closes #8189
Why this plugin matters
Engineering teams today face a fundamental challenge: measuring what actually matters. Lines of code, story points, and velocity tell you how busy a team is — not how effective it is. The DORA research program, backed by over a decade of data from thousands of engineering organizations, identified four metrics that reliably predict both software delivery performance and organizational outcomes:
Elite-performing teams don't just ship faster — they ship with higher quality, lower burnout, and better business outcomes. DORA metrics give engineering leadership an objective, evidence-based language for that conversation.
The gap, however, is access. Most teams collect the raw data — in CI/CD systems, Git providers, and incident trackers — but it lives in silos. Making sense of it requires either expensive tooling or significant engineering investment.
Apache DevLake solves the collection and normalization problem: it ingests data from GitHub, GitLab, Jenkins, PagerDuty, Jira, and more into a unified domain model, and computes DORA metrics out of the box. It is 100% open-source, CNCF-incubating, and production-ready.
This plugin brings those metrics directly into Backstage — the developer portal where engineers already spend their time. Instead of opening a separate Grafana dashboard, teams can see DORA performance at a glance: on a dedicated metrics page, and inline on every service's entity page. It closes the feedback loop between the software catalog and engineering effectiveness data, making DORA metrics a first-class citizen in the inner loop of development.
Packages
@backstage-community/plugin-devlake@backstage-community/plugin-devlake-backend@backstage-community/plugin-devlake-commonFeatures
DoraMetricsPage— a full standalone dashboard page:app-config.yaml)EntityDoraCard— a compact card for entity pages:devlake.io/project-nameto show its DORA metrics inlinedevlake.grafana.baseUrl)MissingAnnotationEmptyStatewhen the annotation is absentBoth components support the New Frontend System extension points via the
/alphaentry point (EntityCardBlueprint,PageBlueprint,ApiBlueprint) — no manual route registration inApp.tsxis required.Technical Design
Why direct MySQL instead of the DevLake REST API?
DevLake v1.x exposes a Grafana-style dashboard API but no DORA REST endpoint suitable for programmatic consumption. The backend plugin queries DevLake's MySQL domain-layer tables directly with read-only credentials. This is the same data source Grafana uses.
Backend data flow
The backend exposes three endpoints under
/api/devlake:GET /healthGET /teamsGET /dora/metrics?team=&preset=GET /dora/metrics/trend?team=&preset=Time range can be specified as a preset (
7d,30d,90d,quarter,1y) or explicitfrom/todate strings.team=Allqueries across all projects.Key domain tables queried
cicd_deployment_commitsproject_mappingpull_requests+project_pr_metricsincidents+project_incident_deployment_relationshipsDORA level thresholds
Frontend architecture
Installation
1. Add the packages
2. Register the backend plugin
3. Configure
app-config.yaml4a. Legacy system — add the page route
4b. New Frontend System — no route registration needed
5. Add
EntityDoraCardto entity pagesLegacy system:
New Frontend System: the
entityDoraCardextension from/alphais auto-registered — no entity page changes required.6. Annotate entities
Test plan
yarn tscpasses with no errorsDevlakeDbClient, config parsing)EntityDoraCard,DoraMetricsPage)DoraMetricsPagerenders at/devlakewith a running DevLake instanceEntityDoraCardrenders on an annotated entityEntityDoraCardshowsMissingAnnotationEmptyStatewhen annotation is absent