chenwei791129 opened a new pull request, #9229: URL: https://github.com/apache/devlake/pull/9229
### Summary Add a DORA project setting, **Source branch pattern** (`prHeadRefPattern`). When it is set, only merged pull requests whose source branch (`pull_requests.head_ref`) matches the regex count toward Lead Time for Changes. This lets teams leave out "carrier" PRs such as release or UAT merges, which would otherwise count the same changes twice. | Item | Behavior | | --- | --- | | Where to set it | Project → Settings → DORA. Stored in `ProjectMetricSetting.PluginOption`, like linker's `prToIssueRegexp` | | Matching | Go `regexp.MatchString`. No implicit anchors (write `^(feat\|fix)/`); use `(?i)` to ignore case; a leading `refs/heads/` is stripped before matching | | Empty or whitespace-only | No filtering, same as today | | Invalid regex | Plan generation returns `BadInput` (HTTP 400) `invalid prHeadRefPattern` | | Scope | Only `project_pr_metrics` is affected. `pull_requests` is unchanged, so code review dashboards keep all PRs | | Data sources | Filtering happens on the domain layer, so it works for GitLab, GitHub, Bitbucket and Azure DevOps alike | | Commit | Change | | --- | --- | | `feat(dora)` | `task_data.go`: new option plus compile/match helpers. `impl.go`: compile in `PrepareTaskData`; `MakeMetricPluginPipelinePlanV200` validates early and adds the pattern to the `calculateChangeLeadTime` stage only when it is not empty. `change_lead_time_calculator.go`: skip PRs that do not match and log how many were excluded | | `feat(config-ui)` ×2 | `settings-panel.tsx`: input, description and help tooltip in the DORA block | ### Does this close any open issues? Closes #9222 ### Screenshots Project → Settings, with DORA enabled and the new Source branch pattern field: <img width="900" alt="DORA source branch pattern in project settings" src="https://raw.githubusercontent.com/chenwei791129/devlake/6ac7107b78a38a03a133ab640193dc11ab5d0f8a/pr-9222/dora-source-branch-pattern.png" /> ### Other Information **Compatibility** - With no pattern set, the plan and the results are exactly the same as before (the existing expected plan in `impl_test` is unchanged). - No schema change, no scope config change, no migration. - An invalid regex is reported when the plan is generated, so the whole blueprint fails to trigger (not only DORA). This matches the monorepo `deployJobPattern` option. Validating options on save is handled separately by #9228 (closes #9227); the two PRs do not depend on each other. - After changing the pattern, a Re-transform is enough. `calculateChangeLeadTime` deletes the project's old rows first, so no stale rows are left behind. **Related issues and PRs** | Link | Relation | | --- | --- | | #9225 / #9226 | The Engineering Throughput PR time panels average PRs without a `project_pr_metrics` row as 0 hours, so those panels read low once a pattern is set. DORA dashboards are not affected | | #9227 / #9228 | Validate metric plugin options (including this regex) when a project is saved | | #9223 / #9224 | The dora e2e tests need an `accounts` table on a fresh database (pre-existing) | **Docs**: the user docs live in `apache/devlake-website`. I will open a follow-up PR there for `docs/DORA.md` and `docs/Metrics/LeadTimeForChanges.md`. ### Tests **Automated** | Check | Result | | --- | --- | | `go build`, `go vet`, `gofmt -l`, `golangci-lint run ./plugins/dora/...` | Pass | | `go test ./plugins/dora/...` incl. e2e (MySQL 8.4) | Pass. New e2e case logs `excluded 4 of 7 merged pull requests` | | Unit: `task_data_test.go` | Empty/whitespace, invalid regex, case sensitivity and `(?i)`, `refs/heads/` prefix, empty `head_ref` | | Unit: `impl_test.go` | Option added to the plan only when not empty, whitespace treated as unset, invalid regex returns `BadInput`, `PrepareTaskData` decoding | | config-ui | `tsc` clean; eslint shows only 2 existing prettier warnings on untouched lines | **Manual, against a self-hosted GitLab** The same commits, backported to v1.0.3-beta15 (only import paths differ), were deployed and tested with real data. Two test repos each got 10 MRs: 9 merged, 1 left open. Every merge to `main` ran a dummy production deploy job. - **A**: DevLake project with the pattern set - **B**: control project, no pattern After each pattern change I ran a Re-transform (no recollection) and checked `project_pr_metrics`, the pipeline log and Grafana. | Source branch | `^(feat\|fix)/` | `^(feat\|fix\|hotfix)/` | `(?i)^(feat\|fix)/` | | --- | --- | --- | --- | | `feat/alpha`, `fix/beta` | ✔ | ✔ | ✔ | | `hotfix/epsilon` | | ✔ | | | `FEAT/delta` | | | ✔ | | `chore/gamma`, `release-uat`, `my-feat/zeta` | | | | | `feat/open` (not merged) | | | | | Scenario | Rows written for A | Log `excluded M of N` | B (control) | Result | | --- | --- | --- | --- | --- | | No pattern | All 7 | Not logged | 7 | ✔ | | `^(feat\|fix)/` | `feat/alpha`, `fix/beta` | 5 of 7 | 7 | ✔ | | Change to `^(feat\|fix\|hotfix)/` | Adds `hotfix/epsilon` | 4 of 7 | 7 | ✔ | | `(?i)^(feat\|fix)/` | Adds `FEAT/delta`, drops `hotfix` | 4 of 7 | 7 | ✔ | | Invalid `^(feat\|fix` | Unchanged | — | — | ✔ Save succeeds; triggering returns HTTP 400 `invalid prHeadRefPattern` and no pipeline is created | | Cleared / whitespace only | All rows again | Not logged | — | ✔ | | Matches nothing (`^nothing-matches/`) | 0 rows | 7 of 7 | — | ✔ | | Incremental collection after merging `feat/eta` and `chore/theta` | Only `feat/eta` added | 6 of 9 | 9 | ✔ Scheduled runs apply it too | Also confirmed: - Rows that no longer match are removed when the pattern changes. - The pipeline plan carries `prHeadRefPattern` only in the `calculateChangeLeadTime` stage, and leaves the key out when it is not set. - Deployments are unaffected: every MR in both projects links to its production deployment and has a `pr_deploy_time`. Grafana, with A set to `^(feat|fix)/`: | Dashboard / panel | A | B | Note | | --- | --- | --- | --- | | DORA → Deployment Frequency | Same | Same | Not affected ✔ | | DORA → Median Lead Time for Changes | 2.1 h | 2.1 h | Test MRs have similar durations, so equal medians are expected | | DORA Details – Lead Time for Changes → PR list | **3 PRs** | **9 PRs** | Only matching MRs are listed ✔ | | Engineering Throughput → PRs Opened / Merged | 10 / 9 | 10 / 9 | Not affected ✔ | | Engineering Throughput → PR Cycle Time | 0.69 h | 2.12 h | Excluded PRs are averaged in as 0 h; fixed by #9226 | Pre-existing issues seen during testing (not caused by this PR): | Item | What happens | Status | | --- | --- | --- | | Engineering Throughput PR time panels | PRs without a metrics row are averaged in as 0 h (0.69 h vs 2.12 h above) | #9225, fixed by #9226 | | GitLab `Convert MR Commits` runs before `Extract MR Commits` | On the first collection of a new MR, `pr_coding_time` is NULL; the next pipeline fills it in. Happens with or without a pattern, including in the control project | Not addressed here | -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
