Repository navigation
chore(config-ui): sync with upstream apache/devlake - #83
Merged
muzamilkm merged 49 commits intoOct 6, 2026
Merged
Conversation
Add a system-aware dark theme with a header toggle (light, dark, system) that persists in localStorage. All colors now flow through `src/theme/tokens.ts` into both the antd component library and styled-components, replacing hardcoded hex across `styled.ts` files and inline styles. Light mode is preserved the same as before. apache#8863 (cherry picked from commit ac73e27)
* feat(rootly): scaffold plugin skeleton
Add the plugin entry point, impl shell with all required plugin
interfaces except DataSourcePluginBlueprintV200 (wired in U2),
connection model with Bearer auth, service + scope-config + placeholder
incident/user/assignment models, and the initial migration script. API
resources and subtasks are intentionally empty and will be populated by
U2-U5.
* feat(rootly): add API handlers and blueprint v200
Wire up connection test, remote scope list/search, scope CRUD, scope
sync state, and blueprint v200 endpoints. Remote scope listing speaks
JSON:API and page-based pagination to match the Rootly API shape.
TestConnection validates the bearer token via GET /users/current.
impl.go now wires api.Init and restores DataSourcePluginBlueprintV200
so the plugin can produce pipeline plans for selected Rootly services.
* feat(rootly): collect and convert services to domain boards
Add services_collector, services_extractor, and service_converter
subtasks. Collector fetches GET /services/{id} for the scoped service,
unwraps the JSON:API envelope, and populates _tool_rootly_services.
Converter emits one ticket.Board per service using the standard
domain-id generator, feeding into the existing TICKET pipeline.
Also harden remote-scope pagination termination to key off the page
we requested rather than meta.current_page so a response missing that
field does not silently truncate the service list.
* feat(rootly): collect and extract incidents with inline users
Finalize the Incident and User models and add role-specific user-id
fields (creator, started_by, mitigated_by, resolved_by, closed_by)
directly on the Incident row. Add the incidents_collector and
incidents_extractor subtasks. The collector is single-phase,
filter[services]-scoped and filter[updated_at][gt]-incremental; the
extractor unwraps the JSON:API envelope and pulls inline nested user
objects from the incident attributes, emitting deduplicated User rows
per incident.
Drop the Assignment table entirely. Rootly's incident data model is
role-per-lifecycle-event, not a list of assignees, so PagerDuty's
n-assignees shape does not fit. The schema and GetTablesInfo are
adjusted accordingly.
* feat(rootly): convert incidents to domain issues
Add incidents_converter. For each tool-layer incident, emit a
ticket.Issue (Type=INCIDENT) with status, priority, lead time, and
resolution date derived from the corresponding Rootly fields; emit one
ticket.IssueAssignee per distinct role user (creator, started_by,
mitigated_by, resolved_by, closed_by); and emit a ticket.BoardIssue
linking the incident to its service board. This feeds DevLake's
existing DORA pipeline so change-failure rate and MTTR compute
correctly for teams running on Rootly.
Unknown incident statuses fall back to IN_PROGRESS with a warning log
rather than panicking (a deliberate divergence from the PagerDuty
plugin, motivated by Rootly's more volatile status enum). Severity
mapping accepts case-insensitive sev0-sev4; unknown severities are
preserved as-is.
Guard computeLeadTime against resolved-before-started timestamps (clock
skew or backfill anomalies) by returning nil rather than the wraparound
garbage a naive uint() cast would produce. Tighten test coverage on the
dedup, key-fallback, and known-status-warning boundaries flagged during
code review.
* test(rootly): add e2e test for extract and convert pipeline
Add an end-to-end test that drives the extract and convert subtasks
over a crafted raw-incident fixture and verifies the tool-layer and
domain-layer output against snapshot CSVs. Fixtures cover every branch
of the status and severity mapping tables, the same-user-across-roles
dedup path, the zero-user case, and the safety-net filter that drops
incidents whose relationships point at a different service than the
one the task was scoped to.
* feat(rootly): register plugin in backend and config-ui
Add rootly to the backend plugin startup test and the table-info test
so CI exercises it alongside the other plugins. Register RootlyConfig
in the config-ui plugin list so operators can create connections,
browse scopes, and run blueprints through the UI.
The cloud endpoint default includes the /v1/ API version prefix,
which is what Rootly's REST API actually expects; without it requests
land on the marketing site and return 404. The DOC_URL entries point
at a Configuration/Rootly docs page that still needs to be written.
Use the Rootly wordmark glyph as the plugin icon, rewritten as a
fill-aware (currentColor) SVG so the config-ui can recolor it for
selected/unselected states the same way it does every other plugin
icon.
* fix(rootly): align archived models with live model schemas
The U1 init migration's archived Connection, Service, and ScopeConfig
models were missing columns contributed by the live models' embedded
helpers, so AutoMigrate produced tables the live models could not
read or write. Each gap surfaced as an "Unknown column" error from
MySQL the first time the table was touched:
- Connection was missing endpoint, proxy, rate_limit_per_hour
(contributed by helper.RestConnection on the live struct).
- Service was missing scope_config_id (contributed by common.Scope).
- ScopeConfig was missing connection_id and name (contributed by
common.ScopeConfig, which the archived base type does not include).
Fold the missing fields into the archived models so a single init
migration produces the correct schema. Since rootly has not been
deployed anywhere, keeping one init migration is cleaner than
chaining follow-up ALTERs; a fresh migrate creates the correct
tables in one pass.
* fix(rootly): align API contract with real Rootly /v1 responses
The original plugin shape was built from docs summaries rather than an
actual response capture and diverged from the Rootly API in ways that
silently produced zero incidents. Reconcile every code path with
ground truth from the OpenAPI spec and a captured GET /v1/incidents
response:
- Connection test hits /users/me (Rootly's real "who am I" path); the
original /users/current returns 404.
- Incident list filter is filter[service_ids]=<uuid>, not
filter[services]=<uuid>. The latter exists but accepts names and
silently matches nothing for a UUID.
- Role-bearing user fields (user, started_by, mitigated_by,
resolved_by, closed_by) and severity are JSON:API response
envelopes nested on attributes: {"data":{"id":...,"attributes":...}}.
The previous flat NestedUser / SeverityAttrs shapes were reading the
wrong paths, so those fields were always empty.
- Service membership lives on the sibling relationships block as
JSON:API id+type pointers, not on attributes. The safety-net
scope-filter check now reads from the right place.
- The incident resource does not have an urgency field. Drop the
corresponding column from the model and archived schema.
Also harden the collector: split the ResponseParser / next-page logic
so pagination state is captured during parse (rather than re-reading
the already-drained response body in GetNextPageCustomData), and add
lightweight request/response diagnostics gated behind Debug logging.
Verified end-to-end against a live Rootly tenant: 3 of 6 scoped
services returned incidents, all 3 extracted and converted into
ticket.Issue rows with creator assignees and board linkage.
* style(rootly): trim narrative comments to match plugin conventions
Match PagerDuty's comment density. Keep the few comments that flag
non-obvious invariants (archived-base field overrides, 1-based
pagination, deliberate divergence from PagerDuty's panic-on-unknown
behavior, clock-skew guard).
* refactor(rootly): address code review feedback
Apply fixes from a multi-lens code review pass:
- API: rename swagger {serviceId} to {scopeId} to match registered
route; remove dead Proxy handler.
- Models: add Sanitize() on RootlyConn; add RoleUserIds() helper on
Incident; index ServiceId; drop unused Url field on User; remove
dead RootlyResponse/ApiUserResponse types.
- Migrations: mirror live schema in archived models (index on
service_id; drop user.url).
- Collector: switch pagination to reqData.Pager.Page (avoids
divide-by-zero), cap at 10000 pages, extract buildIncidentsQuery
as a pure helper, drop unreachable lastPageEmpty branch and unused
TotalCount, remove diagnostic logs; add unit test pinning the
filter[service_ids] param literal as a regression guard.
- Services: preserve ScopeConfigId across re-collections; declare
ProductTables on collector and extractor metas.
- Extractor: skip emitting User rows with neither name nor email so
sibling scope tasks can fill in fuller data; use generic resolve()
for SequentialId; type ServiceRef as a named struct.
- Converter: consolidate mapStatus to return (mapped, known); use
Incident.RoleUserIds() instead of an inline slice.
- impl.go: comment justifying services-before-incidents subtask
ordering.
- e2e: rewrite raw incident fixtures to JSON:API envelope shape;
regenerate snapshots (drop urgency column).
* feat(rootly): add rootly dashboard
* chore: run gofmt
* chore: add isBeta flag to rootly plugin
(cherry picked from commit aff3487)
* feat(tempo): add Jira Tempo Timesheets plugin Adds plugin for ingesting worklogs from Jira Tempo (Tempo Timesheets) API v4. Backend: - Plugin entry point (impl/impl.go) - Tempo API client with Bearer token auth (tasks/api_client.go) - Data collectors, extractors, and converters for worklogs and teams - Connection management API endpoints (api/) - Database migrations for _tool_tempo_worklogs, _tool_tempo_teams - E2E tests with CSV fixtures Config-UI: - Connection configuration UI (config.tsx) - Plugin registration in index.ts Dependency: requires Jira plugin for issue ID mapping. Closes apache#8883 * fix(tempo): resolve CI failures on tempo plugin PR - fix Apache license headers in 5 files (missing/typo content) - move migration script to archived models pattern (forbidden import on plugins/tempo/models) - register tempo in plugins/table_info_test.go - drop unused validator var/import in api/init.go - fix malformed issue_worklogs.csv snapshot (header/body column mismatch) * fix(tempo): align e2e team fixtures with extractor expectations The team extractor queries _raw_tempo_api_teams with the params serialized from TempoApiParams{ConnectionId, TeamId}, expecting the raw fixture rows to store each team as its own record with a single-object data payload. The previous fixture wrapped both teams into a JSON array in the data column and used only ConnectionId in params, causing TestTeamDataFlow to find zero matching rows. Also extend the _tool_tempo_teams snapshot with the _raw_data_* columns that the test verifies via ColumnWithRawData. --------- Co-authored-by: Fix Bot <fix@example.com> (cherry picked from commit 9e659ab)
* feat(linear): add tool-layer models and init migration
Add the Linear plugin's tool-layer data models (connection, team scope,
scope config, account, issue, comment, issue label, workflow state, cycle,
issue history) and the initial schema migration with archived snapshots.
The connection authenticates with a personal API key passed verbatim in the
Authorization header (Linear uses no Bearer prefix).
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): add plugin skeleton, connection API and GraphQL client
Wire the Linear plugin entry point and implement all required plugin
interfaces (meta, init, task, api, model, source, migration, blueprint v200,
closeable). Add connection/scope/scope-config CRUD via the data-source helper,
a test-connection endpoint that runs a GraphQL viewer query, and a rate-limited
async GraphQL client that injects the API key via a bare Authorization header.
SubTaskMetas is intentionally empty; collectors are added per entity in
following commits.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): collect, extract and convert users to accounts
Add the users GraphQL collector (paginated), extractor to
_tool_linear_accounts, and convertor to the domain crossdomain.Account
table, wired as the first three subtasks. Includes an e2e dataflow test
with raw fixtures and verified snapshots.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): collect and extract workflow states
Add the team-scoped workflow states GraphQL collector and extractor into
_tool_linear_workflow_states. These states (backlog/unstarted/started/
completed/canceled) drive deterministic issue status mapping. Includes an
e2e test covering all five state types.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): collect, extract and convert issues
Add the team-scoped issues GraphQL collector (incremental via updatedAt
ordering, inline labels), extractor to _tool_linear_issues and
_tool_linear_issue_labels, and convertor to domain ticket.Issue and
ticket.BoardIssue.
Status maps deterministically from Linear's WorkflowState.type
(backlog/unstarted->TODO, started->IN_PROGRESS, completed/canceled->DONE);
priority maps to its label; lead time falls back to resolution minus
creation. Includes an e2e test spanning all state types, unassigned issues,
issues without a cycle, and multi-label issues.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): collect, extract and convert issue comments
Add a per-issue comments GraphQL collector (driven by an input iterator over
collected issues, with pagination), an extractor that recovers the owning
issue id from the raw input column, and a convertor to domain
ticket.IssueComment. Includes an e2e dataflow test.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): convert issue labels to domain layer
Add the convertor from _tool_linear_issue_labels (populated inline by the
issue extractor) into the domain ticket.IssueLabel table. Includes an e2e
test covering issues with multiple labels and with none.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): collect cycles and convert to sprints
Add the team-scoped cycles GraphQL collector and extractor, plus convertors
producing domain ticket.Sprint and ticket.BoardSprint (status derived from
completedAt), and ticket.SprintIssue linking issues to their cycle. Includes
an e2e dataflow test covering closed/active cycles and issues with/without a
cycle.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): collect issue history and convert to changelogs
Add a per-issue history GraphQL collector (input iterator over issues, with
pagination), an extractor capturing state transitions including state types,
and a convertor to domain ticket.IssueChangelogs with mapped from/to status
values. Lead time is already derived from the issue's native
startedAt/completedAt. Includes an e2e test of a full
backlog->started->completed lifecycle.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* test(linear): add blueprint v200 scope generation tests
Cover makeScopesV200: a team scope with the ticket entity produces the
expected domain board scope id, and a scope without the ticket entity
produces none.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* docs(linear): add plugin README
Document the Linear plugin: supported entities, tool/domain mapping tables,
deterministic status mapping, priority/type/lead-time handling, API-key auth,
connection/scope/pipeline setup examples, rate limiting, and the roadmap
(OAuth, label-based type mapping, config-ui integration).
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* fix(linear): guard lead-time fallback against resolution before creation
A resolution timestamp (completedAt/canceledAt) earlier than createdAt —
from clock skew or migrated/imported issues — produced a negative duration
that, cast to uint, yields platform-dependent garbage (0 on arm64, ~1.8e19
on amd64). Skip the fallback unless the resolution is after creation so lead
time stays unset instead.
Adds an isolated e2e dataflow test with a fixture whose canceledAt precedes
createdAt, asserting lead_time_minutes is empty.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* fix(linear): map Linear triage state type to TODO
The WorkflowState.type 'triage' (the inbox state issues land in before being
accepted) previously fell through to OTHER, contradicting the documented total
mapping and silently mislabeling triage issues. Map it to TODO; keep OTHER as
the fallback for genuinely unrecognized types so unexpected API values surface.
Adds a unit test covering every documented state type plus triage and an
unknown value.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* refactor(linear): remove unused GraphqlInlineAccount struct
The struct was documented as the shared inline-user shape but was never
referenced; each collector declares its own inline user struct. Removing it
avoids misleading a maintainer into editing a type nothing reads.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* perf(linear): raise issue collector page size to 100
Every other Linear collector uses a page size of 100; issues used 50, which
doubled the number of issue-page round-trips and the iterator size that drives
the per-issue comment/history collectors. Linear permits first: 250.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): populate issue assignee/creator names and issue_assignees
The issue convertor set only assignee_id/creator_id, leaving the denormalized
assignee_name/creator_name columns blank and writing no issue_assignees rows,
so dashboards reading those columns or joining through issue_assignees showed
blank names. Preload account display names (matching the account convertor's
displayName-then-name rule) and emit an IssueAssignee per assigned issue.
The issue dataflow test now loads accounts before conversion and asserts the
names plus issue_assignees; the lead-time test flushes accounts to stay
order-independent on the shared test DB.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* fix(linear): clear stale sprint_issues when issues leave their cycle
Sprint membership is derived from each issue's cycle_id, and the batch divider
only deletes outdated rows when it produces at least one row of the type. When
every issue is moved out of its cycle the convertor emits nothing, so the
divider never fires and prior sprint_issues rows linger, leaving issues shown
in sprints they no longer belong to. Delete the team's sprint_issues up front
so the result is correct regardless of how many issues remain in a cycle.
Adds a two-run e2e test that empties every issue's cycle and asserts
sprint_issues is empty afterward.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): derive issue lead time from state-transition history
The LinearIssue.LeadTimeMinutes field was never populated, so lead time always
fell back to the coarse createdAt -> resolutionDate span. Derive it instead from
the recorded history: the span from an issue's first transition into an
in-progress state to its first transition into a done state thereafter (active
cycle time), which is the value that genuinely requires history. ConvertIssues
still seeds the fallback; ConvertIssueHistory now overrides it when the
transitions exist, and issues lacking them keep the fallback.
Adds an e2e test asserting issue-1 (started 05-02, completed 05-03) resolves to
1440 minutes from history rather than its 2880-minute created->resolved span.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): add remote-scopes endpoints to enumerate teams
Other first-party ticket plugins (jira, asana, github) expose
connections/:connectionId/remote-scopes so the config UI can browse and select
scopes from the API. Linear had none, forcing users to hand-craft a PUT /scopes
with raw team UUIDs they had no in-product way to discover. Wire the standard
DsRemoteApiProxyHelper + DsRemoteApiScopeListHelper and a lister that queries
the GraphQL teams connection (flat list, cursor-paginated) through the
connection's authenticated client.
Adds unit tests for the response->scope-entry mapping, the pagination cursor,
and the route registration.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* perf(linear): make comment and history collection incremental
Both child collectors used a plain GraphqlCollector and swept every issue in
the team on every run, issuing one request per issue with no since filter -
tens of thousands of requests per run on a large team against Linear's ~1500
req/hour budget. Switch them to a stateful collector and restrict the driving
cursor to issues updated since the last successful collection, so steady-state
runs scale with the change delta rather than the whole backlog. A full sync
(since == nil) still sweeps every issue.
Adds a unit test for the incremental cursor-clause builder.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* fix(linear): filter issues server-side by updatedAt for incremental sync
Incremental collection relied on the issues query returning newest-first and a
client-side early-stop, but the query pinned no sort direction (Linear's orderBy
is a scalar enum with no direction operand). If the server default were
ascending, the early-stop would fire on the first (oldest) row and collect
almost nothing. Pass a server-side IssueFilter { updatedAt: { gt: since } }
instead and drop the early-stop, so correctness no longer depends on an
undocumented default ordering. A full sync passes an empty filter (match all).
Adds a unit test pinning the filter's JSON shape to Linear's IssueFilter input.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* refactor(linear): drop dead LeadTimeMinutes tool-layer field
The _tool_linear_issues.lead_time_minutes column was never populated (the
collector never requested it and no extractor set it). Now that lead time is
derived into the domain ticket.Issue directly -- from state-transition history
when available, otherwise the createdAt->resolutionDate fallback in the issue
convertor -- the tool-layer field is pure dead weight. Remove it from the model,
the init migration's archived model, the convertor, and the extractor snapshot.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(config-ui): register Linear plugin
Adds the Linear data source to config-ui so it appears in the connection
picker: connection form (endpoint + personal API key + proxy + rate limit),
a flat Teams data-scope backed by the plugin's remote-scopes endpoint, and the
Linear logo. No scope-config transformation — Linear's status mapping is
deterministic. Wired into the plugin registry.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* fix(config-ui): map Linear scope id to teamId
getPluginScopeId fell through to the default (scope.id) for Linear, but a
LinearTeam scope is keyed by teamId and has no id field — so the blueprint
referenced an undefined scopeId and patching failed with 'LinearTeam not found'.
Add a linear case returning scope.teamId.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): add Grafana dashboard
Adds grafana/dashboards/Linear.json (cloned from the Asana ticket-dashboard
template) so Linear ships a per-tool dashboard like every other ticket plugin.
Its board picker is scoped to Linear (boards id like 'linear%'); the 13 panels
(throughput, lead/cycle time, status distribution, delivery rate, sprints) read
the shared domain tables. Auto-loaded via Grafana file provisioning.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* fix(linear): convert team scope to a domain board
board_issues and sprint_issues referenced a board_id (boardIdGen over
LinearTeam), but nothing ever created the ticket.Board row itself, so the
domain boards table stayed empty. Board-scoped dashboards (whose board picker
is 'boards where id like linear%') and any board join therefore returned no
data. Add a ConvertTeams subtask that converts the team scope in
_tool_linear_teams into a ticket.Board keyed identically to those references.
Adds an e2e test asserting the board is produced with the matching id.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* fix(linear): widen issue title/url columns to avoid truncation
_tool_linear_issues.title and .url were varchar(255), but Linear titles can
exceed 255 chars (and the issue URL embeds a title slug), so extraction failed
with 'Error 1406: Data too long for column title'. Drop the varchar limit so
both are longtext, matching the domain issues.title and jira's tool summary.
Adds an e2e test extracting a 300-char title without truncation.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* fix(linear): recover owning issue id for comments and history
The GraphQL collector stores the query variables (which carry issueId) in the
raw row's input column, but the comment and history extractors parsed it as
{"Id":...} (SimpleLinearIssue.Id), so the owning issue id came out empty and
the convertor joins produced zero domain comments/changelogs on real data. The
e2e fixtures hand-wrote {"Id":...}, masking it. Parse issueId (with an Id
fallback) and update the fixtures to the real collector shape.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* test: flush LinearIssueLabel before issue extraction in e2e tests
The issue extractor writes both _tool_linear_issues and
_tool_linear_issue_labels, but comment_test, cycle_test and
issue_history_test only flushed LinearIssue before running
ExtractIssuesMeta. On a clean database (as in CI) the table
_tool_linear_issue_labels was never auto-migrated, so the extractor's
DELETE on that table panicked and aborted the whole package. Flush
LinearIssueLabel too, matching the other linear e2e tests and the jira
plugin convention.
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* test: register linear plugin in Test_GetPluginTablesInfo
The plugin count check failed in CI (actual 41 vs tested 40) because the
linear plugin was not listed in table_info_test.go. Add its import and
FeedIn call so every Go plugin is covered.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
* feat(linear): map issues to ticket types via label-based scope config
Linear has no native issue type, so the issue convertor previously
hardcoded every issue to REQUIREMENT. Add optional regex fields to the
Linear scope config (issueTypeIncident/Bug/Requirement) matched against
an issue's label names, with precedence INCIDENT > BUG > REQUIREMENT and
a REQUIREMENT default when nothing matches. This lets DORA classify
Linear bugs as incidents for change-failure-rate / time-to-restore.
Also fix two gaps that made scope configs unusable for Linear:
- thread the scope's ScopeConfigId into the pipeline task options so the
convertor can load the config at runtime
- register the standard scope-config/:scopeConfigId/projects route that
every other plugin serves (config-ui 404'd on the scope config page)
Tested: new e2e TestLinearIssueIncidentMapping (Bug label -> INCIDENT,
other issues REQUIREMENT) plus a blueprint plan test asserting
ScopeConfigId is passed through; full plugins/linear suite green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
---------
Signed-off-by: Eduardo Rodrigues <2961314+eduardoarantes@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
(cherry picked from commit cec4286)
…pache#8918) (cherry picked from commit 33f7d34)
…pache#8903) * fix(jira): rename Jira Server to Jira Data Center in UI labels * fix(jira): show both Jira Server and Jira Data Center labels (cherry picked from commit 50010e0)
(cherry picked from commit 57b2641)
(cherry picked from commit 0e96ba1)
…xclusion (apache#8931) * feat(jira): collect issues via search API to avoid kanban sub-filter exclusion * Switch from board Agile API to search API with saved filter JQL so resolved issues (e.g. released fixVersions) are no longer silently excluded by kanban sub-filters * Add sub_query field to boards model and migration to track kanban sub-filter changes across syncs * Support JIRA Cloud v3 search/jql endpoint alongside v2 for Server * fix(jira,config-ui): correct SubQuery parsing and connection form crashes * Fix Jira board SubQuery struct to match nested API response shape * Prevent click event from being stored as plugin state in connection list * Default initialValues to empty object when plugin config omits it * feat(jira): Add BoardConfiguration unmarshal tests * Verify SubQuery parsing for kanban boards with, without, and empty sub-filter objects * Include a test using a full Jira Cloud response payload to validate all fields (cherry picked from commit 15e34bb)
* feat(jira): Allow extra JQL when querying JIRA board * fix: revert code so we just do extrajql, no dynamic dev lake project name * fix: remove reference to devlakeprojectname as a template option (cherry picked from commit cd7bebf)
Co-authored-by: Bujjibabukatta <bujjubabukatta6@gmail.com> Co-authored-by: Eldrick Wega <eldrick.wega@outlook.com> Co-authored-by: Eldrick Wega <ewega@github.com> (cherry picked from commit f93895f)
…pache#8995) Co-authored-by: Klesh Wong <klesh@qq.com> (cherry picked from commit 060af3a)
…pache#9006) * chore(config-ui): modernize frontend toolchain and framework stack Upgrade the config-ui frontend to current supported versions as one coupled change so the build stays green: - Node 18 -> 24, Yarn 3.4.1 -> 4.17.0 (Corepack, vendored release, .yarnrc.yml), nginx base image bump in config-ui/Dockerfile - Vite 8, TypeScript config update, ESLint flat config (eslint.config.mjs) replacing .eslintrc.js/.eslintignore, Vitest setup replacing .file-headerrc - React 18 -> 19 and antd 5 -> 6 with the resulting ref/hook/type fixes and a miller-columns-select compatibility patch - Add main-entry and miller-columns-select tests The q-dev connection-field files are touched only for the mandatory React 19 useRef(undefined) fix and Prettier formatting; no q-dev logic changes. Verified on Node 24.18.0 / Yarn 4.17.0: install --immutable clean, tsc --noEmit, eslint . (0 errors), yarn build (Vite 8), yarn test (4/4) all pass. Signed-off-by: DoDiODev <DoDiDev@proton.me> * ci(config-ui): bump lint workflow Node to 24 The modernized config-ui toolchain (ESLint 10.5.0) uses util.styleText in its stylish formatter, which is only available on Node >= 20.12. The lint workflow still pinned Node 18, causing 'TypeError: util.styleText is not a function'. Align CI with the volta-pinned Node 24.17.0. --------- Signed-off-by: DoDiODev <DoDiDev@proton.me> (cherry picked from commit 2127e84)
…prints, DORA) (apache#9009) * feat(clickup): scaffold ClickUp data-source plugin (task→issue MVP) Add a new DevLake data-source plugin for ClickUp, mirroring the linear (structure) and trello (REST client) tracker plugins. - models: ClickUpConnection (token auth, no Bearer prefix), ClickUpList scope (keyed by list id), ClickUpTask, ClickUpUser, ClickUpTaskComment (stub), ClickUpScopeConfig (status + type mapping) - migrationscripts: register + addInitTables creating all _tool_clickup_* tables via migrationhelper.AutoMigrateTables - tasks: task/user collectors (page-based + member REST), extractors, convertors to ticket.Issue/BoardIssue/IssueAssignee, crossdomain.Account and ticket.Board; shared status/type/time helpers - api: connection CRUD + test-connection (GET /team), scope, scope-config, hierarchical remote-scopes (Team→Space→Folder→List), proxy, blueprint v200 - impl: all required plugin interfaces incl. GetTablesInfo listing every model, dependency-ordered SubTaskMetas and PrepareTaskData - register clickup in plugins/table_info_test.go go build ./plugins/clickup/... and go vet pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(clickup): add ClickUp connector with folder-scope boards, sprints, and DORA Add a new ClickUp data-source plugin so ClickUp workspaces feed DevLake's issue-tracking and DORA/velocity metrics, modeled on the Jira/Linear connectors. Backend: - Folder is the data-source scope (ClickUpFolder ~= a Jira board); lists are child entities collected every sync, so rolling/archived sprint lists never need re-scoping. - Sprint lists (name-matched) -> ticket.Sprint + board_sprints; start/end parsed from the list name (M/D vs D/M disambiguated by the >12 rule). - Tasks -> issues + board_issues; sprint-list tasks also -> sprint_issues. - Story points from ClickUp native sprint points (or a configured custom field). - Scope config: sprint-name pattern, story-point field, force-issue-type (flag a folder INCIDENT for DORA CFR/MTTR), status/type overrides. - remote-scopes walks Workspace -> Space -> Folder (folders selectable). - migration 20260722 adds _tool_clickup_folders + sprint/story-point columns. - Unit tests for sprint name/date parsing and status/type/story-point mapping. Config UI: - ClickUp connection registration (personal-token auth) with a Beta pill. - Boards data-scope picker + scope-config transformation panel. - getPluginScopeId(clickup) -> folderId so scope delete and per-scope project selection target one scope; fix a pre-existing Connections-page chunk() split that silently dropped plugins. Docs & dashboards: - Plugin README (connection, folder scope, sprints, story points, incidents). - Branded ClickUp Grafana dashboard (grafana/dashboards/ClickUp.json). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Evan Lynch <e.lynch303@gmail.com> * feat(clickup): classify issues by list name (bug/incident list patterns) ClickUp frequently carries no per-task type, so teams group bugs and incidents in dedicated lists (e.g. "QA Bugs", "Incident Backlog") rather than tagging each task. Add scope-config BugListPattern and IncidentListPattern regexes matched against a list's name; tasks in a matching list are classified BUG / INCIDENT (INCIDENT wins when both match). Precedence in the task convertor: forced DefaultIssueType > list-name pattern > per-task type detection > REQUIREMENT default. - models: BugListPattern / IncidentListPattern on ClickUpScopeConfig - migration 20260723 adds the two columns (additive AutoMigrate) - task convertor: loadListTypeOverrides + pure listTypeFor helper - unit test for listTypeFor (precedence, case-insensitivity, nil regexes) - config-ui transformation panel: two list-pattern inputs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Evan Lynch <e.lynch303@gmail.com> --------- Signed-off-by: Evan Lynch <e.lynch303@gmail.com> Co-authored-by: Evan Lynch <elynch@freedomeledger.net> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> (cherry picked from commit 73fa07d)
(cherry picked from commit 2cfe630)
Adds a datasource plugin for incident.io (https://incident.io), an incident management platform, following the structure of the rootly plugin: - Connection with Bearer-token auth against https://api.incident.io/ - Scopes are incident types (v1/incident_types); remote-scope listing included - Collects incidents (v2/incidents, cursor pagination), extracts to _tool_incidentio_* tables (test/tutorial-mode incidents excluded), converts to ticket domain issues with type INCIDENT for DORA CFR/MTTR correlation - Timestamps mapped from incident_timestamp_values: 'Declared at' drives the created date, 'Resolved at' (falling back to 'Closed at') the resolution date; retrospective incidents keep their resolution date even when it precedes the declaration - Unit tests, e2e snapshot tests, config-ui registration, Grafana dashboard Validated end-to-end against a production incident.io workspace via the in-memory test server (50 incidents, field-level match with reference data). Closes apache#9018 Co-authored-by: Claude Fable 5 <noreply@anthropic.com> (cherry picked from commit 0194a41)
- Add JIRA_GATEWAY_REGEX and a third connection mode 'Jira Cloud (Atlassian API Gateway)' in the connection UI - Auto-build endpoint from Cloud ID input: the user types only the Cloud ID and the full gateway URL is constructed automatically - Force authMethod=AccessToken for gateway connections; existing BasicAuth path for standard cloud and server connections is unchanged - Detect gateway endpoints on edit/load and pre-fill the Cloud ID field - Suppress misleading /rest/ hint in testConnection() for api.atlassian.com endpoints (a 404 there means a bad Cloud ID, not a missing /rest/ path) - Add unit tests for gateway and standard-cloud connection flows - Add frontend test suite for regex patterns and Cloud ID builder No migration script required. No new DB columns. All collectors, extractors, converters and domain models unchanged. (cherry picked from commit 14a4e5b)
…ction (apache#9034) Add a scoped GET /plugins/github/scope-duplicates API and a dismissible Config-UI Alert so users are informed before creating cross-connection duplicate domain records (apache#8947). Co-authored-by: Cursor <noreply@cursor.com> Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit d323c16)
…he#9044) * build(deps): refresh container images Bump the pinned container images used by the dev/test stacks and the shipped Dockerfiles to their current patch releases: - Grafana 13.0.2 -> 13.1.3 (grafana/Dockerfile) - PostgreSQL 18.1 -> 18.4 (docker-compose-dev-postgresql.yml, backend/test/e2e/remote/docker-compose.test.yml) - MySQL 8.4.10 -> 8.4.11, LTS line (docker-compose-dev-mysql.yml, docker-compose.datasources.yml, .devcontainer/docker-compose.yml, devops/deployment/temporal/docker-compose-temporal.yml, backend/test/e2e/remote/docker-compose.test.yml) - nginx-unprivileged 1.31.2 -> 1.31.3 (config-ui/Dockerfile) Every occurrence of a given pin is raised together so the stacks stay consistent. The Grafana bump stays within the 13.x line and requires no dashboard JSON changes. Release artefacts under devops/releases/ are historical and intentionally left untouched. Signed-off-by: DoDiODev <DoDiDev@proton.me> * build(deps): bump pinned Node.js to 24.19.0 Update the volta Node pin in config-ui/package.json from 24.17.0 to 24.19.0, the current 24.x LTS ("Krypton") release. The Docker build stays on the floating node:24-bookworm-slim tag, so this only aligns local development environments with the release actually used in CI/images. Signed-off-by: DoDiODev <DoDiDev@proton.me> * build(deps): refresh frontend dependencies Update the pinned config-ui dependencies to their current releases and regenerate yarn.lock: - antd 6.4.5 -> 6.6.0 - @ant-design/icons 6.2.5 -> 6.3.2 - cron-parser 5.6.0 -> 5.8.1 - react-router-dom 7.18.0 -> 7.18.2 - styled-components 6.4.2 -> 6.5.1 - eslint 10.5.0 -> 10.8.1 - prettier 3.8.4 -> 3.9.6 - vite 8.1.0 -> 8.2.1 - vitest 4.1.9 -> 4.1.10 All target versions stay within their current major line and keep their declared engines/peerDependencies compatible with the pinned Node 24 and React 19 versions. TypeScript is deliberately left at 6.0.3, since 7.x is a major upgrade that deserves its own change. Validated locally with yarn install, yarn build, yarn test and yarn lint. Signed-off-by: DoDiODev <DoDiDev@proton.me> --------- Signed-off-by: DoDiODev <DoDiDev@proton.me> (cherry picked from commit 62612a8)
…ther connection (apache#9047) * feat(gitlab,bitbucket): extend scope-duplicate warning to GitLab and Bitbucket Add scope-duplicates API endpoints for GitLab and Bitbucket, mirroring the existing GitHub implementation, and generalize the config-ui data-scope-remote component and scope API client so the duplicate-connection warning works for all three plugins. Co-Authored-By: Cursor Agent <noreply@cursor.com> Co-authored-by: Cursor <cursoragent@cursor.com> * assert specific error message --------- Co-authored-by: Cursor Agent <noreply@cursor.com> Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit 83b457e)
…che#9014) (apache#9014) (cherry picked from commit 5b3a51f)
(cherry picked from commit b34e53a)
* feat(kiro): add S3 collection and plugin APIs Signed-off-by: warren <warren.chen830@gmail.com> * feat(config-ui): add Kiro connection support Signed-off-by: warren <warren.chen830@gmail.com> * fix(kiro): use portable timestamp precision Signed-off-by: warren <warren.chen830@gmail.com> * fix(kiro): keep q_dev in table info checks Signed-off-by: warren <warren.chen830@gmail.com> --------- Signed-off-by: warren <warren.chen830@gmail.com> (cherry picked from commit 0642b59)
* chore: remove incubator prefix * fix: linting * fix: mockery (cherry picked from commit e355317)
…9097) Phase 1 of the deprecation plan in apache#9092. Adds deprecation warnings across the codebase to inform users that the Python plugin framework will be removed in 3 months in favor of Go-based plugins. Changes: - backend/python/README.md: add DEPRECATED banner + migration guidance - backend/python/plugins/azuredevops/README.md: mark plugin deprecated, point users to azuredevops_go - backend/core/runner/loader.go: emit a WARN log line at server startup when remote (Python) plugins are being loaded - backend/core/plugin/plugin_meta.go: add PluginDeprecation interface - backend/server/services/remote/plugin/plugin_impl.go: implement PluginDeprecation on RemotePlugin so all Python plugins are flagged - backend/server/api/plugininfo/plugininifo.go: expose field on GET /plugins so config-ui can detect deprecated plugins - config-ui: add isDeprecated/deprecationMessage to IPluginConfig, mark the azuredevops (Python) plugin deprecated, and render a 'Deprecated' badge + message in the Connections page (cherry picked from commit 8692568)
Bumps [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) from 6.9.1 to 7.0.1. - [Release notes](https://github.com/testing-library/jest-dom/releases) - [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md) - [Commits](testing-library/jest-dom@v6.9.1...v7.0.1) --- updated-dependencies: - dependency-name: "@testing-library/jest-dom" dependency-version: 7.0.1 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit 69535ed)
) Bumps [jsdom](https://github.com/jsdom/jsdom) from 29.1.1 to 30.0.1. - [Release notes](https://github.com/jsdom/jsdom/releases) - [Commits](jsdom/jsdom@v29.1.1...v30.0.1) --- updated-dependencies: - dependency-name: jsdom dependency-version: 30.0.1 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit 04ae22b)
…pache#9112) Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.13.2 to 26.4.1. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) --- updated-dependencies: - dependency-name: "@types/node" dependency-version: 26.4.1 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit 36e3c07)
Bumps the docker-patch group with 1 update in the /config-ui directory: nginxinc/nginx-unprivileged. Updates `nginxinc/nginx-unprivileged` from 1.31.3 to 1.31.5 --- updated-dependencies: - dependency-name: nginxinc/nginx-unprivileged dependency-version: 1.31.5 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: docker-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit cc577f3)
…he#9130) The A-N and O-Z headings were produced by cutting the plugin list at the first plugin id starting with a letter from o to z. That agrees with the headings only while each config's `sort` value runs alphabetically, and it stopped doing so as plugins were appended in the order they were added: Asana, Kiro, Linear and incident.io are all listed after Opsgenie, so all four appeared under O-Z. Group by the first letter of the displayed name instead, which is what a reader is matching against, and extract the decision into a pure function with tests. Generated-by: Claude Code (Claude Opus 5) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> (cherry picked from commit 10c20d9)
(cherry picked from commit a0cc751)
…st and delete paths (apache#9135) Co-authored-by: Veet M <veet@inst-builder-debian-12-build-build-v4yxp.europe-west4-a.c.gce-image-builder.internal> (cherry picked from commit 40f2b0d)
… updates (apache#9158) Bumps the js-minor-patch group with 26 updates in the /config-ui directory: | Package | From | To | | --- | --- | --- | | [@ant-design/icons](https://github.com/ant-design/ant-design-icons) | `6.3.2` | `6.3.4` | | [ahooks](https://github.com/alibaba/hooks) | `3.9.7` | `3.10.0` | | [antd](https://github.com/ant-design/ant-design) | `6.6.0` | `6.6.4` | | [axios](https://github.com/axios/axios) | `1.18.1` | `1.20.0` | | [cron-parser](https://github.com/harrisiirak/cron-parser) | `5.8.1` | `5.10.1` | | [dayjs](https://github.com/iamkun/dayjs) | `1.11.21` | `1.11.23` | | [react](https://github.com/react/react/tree/HEAD/packages/react) | `19.2.7` | `19.3.0` | | [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `19.2.17` | `19.3.0` | | [react-dom](https://github.com/react/react/tree/HEAD/packages/react-dom) | `19.2.7` | `19.3.0` | | [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `19.2.3` | `19.3.0` | | [react-is](https://github.com/react/react/tree/HEAD/packages/react-is) | `19.2.7` | `19.3.0` | | [react-medium-image-zoom](https://github.com/rpearce/react-medium-image-zoom) | `5.4.8` | `5.4.9` | | [react-router-dom](https://github.com/remix-run/react-router/tree/HEAD/packages/react-router-dom) | `7.18.2` | `7.18.4` | | [styled-components](https://github.com/styled-components/styled-components) | `6.5.1` | `6.5.3` | | [@testing-library/dom](https://github.com/testing-library/dom-testing-library) | `10.4.1` | `10.4.2` | | [@testing-library/react](https://github.com/testing-library/react-testing-library) | `16.3.2` | `16.3.3` | | [@types/lodash](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/lodash) | `4.17.24` | `4.17.25` | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.4.1` | `26.6.1` | | [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `19.2.17` | `19.3.0` | | [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `19.2.3` | `19.3.0` | | [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `6.0.3` | `6.1.1` | | [eslint](https://github.com/eslint/eslint) | `10.8.1` | `10.10.0` | | [globals](https://github.com/sindresorhus/globals) | `17.7.0` | `17.12.0` | | [jsdom](https://github.com/jsdom/jsdom) | `30.0.1` | `30.1.0` | | [lint-staged](https://github.com/lint-staged/lint-staged) | `17.0.8` | `17.5.1` | | [prettier](https://github.com/prettier/prettier) | `3.9.6` | `3.9.8` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.62.0` | `8.70.0` | | [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `8.2.1` | `8.3.0` | Updates `@ant-design/icons` from 6.3.2 to 6.3.4 - [Commits](https://github.com/ant-design/ant-design-icons/commits) Updates `ahooks` from 3.9.7 to 3.10.0 - [Release notes](https://github.com/alibaba/hooks/releases) - [Commits](alibaba/hooks@v3.9.7...v3.10.0) Updates `antd` from 6.6.0 to 6.6.4 - [Release notes](https://github.com/ant-design/ant-design/releases) - [Changelog](https://github.com/ant-design/ant-design/blob/master/CHANGELOG.en-US.md) - [Commits](ant-design/ant-design@6.6.0...6.6.4) Updates `axios` from 1.18.1 to 1.20.0 - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](axios/axios@v1.18.1...v1.20.0) Updates `cron-parser` from 5.8.1 to 5.10.1 - [Release notes](https://github.com/harrisiirak/cron-parser/releases) - [Changelog](https://github.com/harrisiirak/cron-parser/blob/master/CHANGELOG.md) - [Commits](harrisiirak/cron-parser@v5.8.1...v5.10.1) Updates `dayjs` from 1.11.21 to 1.11.23 - [Release notes](https://github.com/iamkun/dayjs/releases) - [Changelog](https://github.com/iamkun/dayjs/blob/v1.11.23/CHANGELOG.md) - [Commits](iamkun/dayjs@v1.11.21...v1.11.23) Updates `react` from 19.2.7 to 19.3.0 - [Release notes](https://github.com/react/react/releases) - [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/react/react/commits/v19.3.0/packages/react) Updates `@types/react` from 19.2.17 to 19.3.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) Updates `react-dom` from 19.2.7 to 19.3.0 - [Release notes](https://github.com/react/react/releases) - [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/react/react/commits/v19.3.0/packages/react-dom) Updates `@types/react-dom` from 19.2.3 to 19.3.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom) Updates `react-is` from 19.2.7 to 19.3.0 - [Release notes](https://github.com/react/react/releases) - [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md) - [Commits](https://github.com/react/react/commits/v19.3.0/packages/react-is) Updates `react-medium-image-zoom` from 5.4.8 to 5.4.9 - [Release notes](https://github.com/rpearce/react-medium-image-zoom/releases) - [Changelog](https://github.com/rpearce/react-medium-image-zoom/blob/main/CHANGELOG.md) - [Commits](rpearce/react-medium-image-zoom@v5.4.8...v5.4.9) Updates `react-router-dom` from 7.18.2 to 7.18.4 - [Release notes](https://github.com/remix-run/react-router/releases) - [Changelog](https://github.com/remix-run/react-router/blob/react-router-dom@7.18.4/packages/react-router-dom/CHANGELOG.md) - [Commits](https://github.com/remix-run/react-router/commits/react-router-dom@7.18.4/packages/react-router-dom) Updates `styled-components` from 6.5.1 to 6.5.3 - [Release notes](https://github.com/styled-components/styled-components/releases) - [Commits](https://github.com/styled-components/styled-components/compare/styled-components@6.5.1...styled-components@6.5.3) Updates `@testing-library/dom` from 10.4.1 to 10.4.2 - [Release notes](https://github.com/testing-library/dom-testing-library/releases) - [Changelog](https://github.com/testing-library/dom-testing-library/blob/main/CHANGELOG.md) - [Commits](testing-library/dom-testing-library@v10.4.1...v10.4.2) Updates `@testing-library/react` from 16.3.2 to 16.3.3 - [Release notes](https://github.com/testing-library/react-testing-library/releases) - [Changelog](https://github.com/testing-library/react-testing-library/blob/main/CHANGELOG.md) - [Commits](testing-library/react-testing-library@v16.3.2...v16.3.3) Updates `@types/lodash` from 4.17.24 to 4.17.25 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/lodash) Updates `@types/node` from 26.4.1 to 26.6.1 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `@types/react` from 19.2.17 to 19.3.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) Updates `@types/react-dom` from 19.2.3 to 19.3.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom) Updates `@vitejs/plugin-react` from 6.0.3 to 6.1.1 - [Release notes](https://github.com/vitejs/vite-plugin-react/releases) - [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.1.1/packages/plugin-react) Updates `eslint` from 10.8.1 to 10.10.0 - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](eslint/eslint@v10.8.1...v10.10.0) Updates `globals` from 17.7.0 to 17.12.0 - [Release notes](https://github.com/sindresorhus/globals/releases) - [Commits](sindresorhus/globals@v17.7.0...v17.12.0) Updates `jsdom` from 30.0.1 to 30.1.0 - [Release notes](https://github.com/jsdom/jsdom/releases) - [Commits](jsdom/jsdom@v30.0.1...v30.1.0) Updates `lint-staged` from 17.0.8 to 17.5.1 - [Release notes](https://github.com/lint-staged/lint-staged/releases) - [Changelog](https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md) - [Commits](lint-staged/lint-staged@v17.0.8...v17.5.1) Updates `prettier` from 3.9.6 to 3.9.8 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](prettier/prettier@3.9.6...3.9.8) Updates `typescript-eslint` from 8.62.0 to 8.70.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.70.0/packages/typescript-eslint) Updates `vite` from 8.2.1 to 8.3.0 - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/create-vite@8.3.0/packages/vite) --- updated-dependencies: - dependency-name: "@ant-design/icons" dependency-version: 6.3.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: js-minor-patch - dependency-name: ahooks dependency-version: 3.10.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: antd dependency-version: 6.6.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: js-minor-patch - dependency-name: axios dependency-version: 1.20.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: cron-parser dependency-version: 5.10.1 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: dayjs dependency-version: 1.11.23 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: js-minor-patch - dependency-name: react dependency-version: 19.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: "@types/react" dependency-version: 19.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: react-dom dependency-version: 19.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: "@types/react-dom" dependency-version: 19.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: react-is dependency-version: 19.3.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: react-medium-image-zoom dependency-version: 5.4.9 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: js-minor-patch - dependency-name: react-router-dom dependency-version: 7.18.4 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: js-minor-patch - dependency-name: styled-components dependency-version: 6.5.3 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: js-minor-patch - dependency-name: "@testing-library/dom" dependency-version: 10.4.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: js-minor-patch - dependency-name: "@testing-library/react" dependency-version: 16.3.3 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: js-minor-patch - dependency-name: "@types/lodash" dependency-version: 4.17.25 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: js-minor-patch - dependency-name: "@types/node" dependency-version: 26.6.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: "@types/react" dependency-version: 19.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: "@types/react-dom" dependency-version: 19.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: "@vitejs/plugin-react" dependency-version: 6.1.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: eslint dependency-version: 10.10.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: globals dependency-version: 17.12.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: jsdom dependency-version: 30.1.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: lint-staged dependency-version: 17.5.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: prettier dependency-version: 3.9.8 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: js-minor-patch - dependency-name: typescript-eslint dependency-version: 8.70.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: js-minor-patch - dependency-name: vite dependency-version: 8.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: js-minor-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit c78bc74)
(cherry picked from commit 12912df)
) Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 4.1.10 to 5.0.1. - [Release notes](https://github.com/vitest-dev/vitest/releases) - [Changelog](https://github.com/vitest-dev/vitest/blob/main/docs/releases.md) - [Commits](https://github.com/vitest-dev/vitest/commits/v5.0.1/packages/vitest) --- updated-dependencies: - dependency-name: vitest dependency-version: 5.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> (cherry picked from commit 64e12d6)
Service-account 2LO can mint 60-minute Bearer tokens and call the Atlassian API gateway, so Jira Cloud connections no longer require a user API token. Co-authored-by: Cursor <cursoragent@cursor.com> (cherry picked from commit 9abdf41)
…e#9152) * fix(azuredevops_go) - consider runname for pipeline regex match * fix(lint): lint issue fix in azure devops extractor * fix(lint): migration file issue fix --------- Co-authored-by: root <root@inst-builder-debian-12-build-build-v4yxp.europe-west4-a.c.gce-image-builder.internal> (cherry picked from commit 54d4e91)
…KE_URL (apache#9166) Allow overriding the Vite dev server /api proxy target using VITE_DEVLAKE_URL, defaulting to http://localhost:8080. This avoids modifying the tracked vite.config.ts during local or dev container development. (cherry picked from commit b3f1885)
* feat(grafana_irm): add Grafana IRM incident collection plugin * test(grafana_irm): add richer live-captured e2e/unit fixtures; implement TestConnection - Seed 2 more real (non-drill) incidents on the dev stack with a real role assignment and multi-label data, closing gaps the original 2-incident fixture never exercised (assignment mapping, per-scope label exclusion). - Add a second e2e scenario proving label-based scope filtering end-to-end. - Update the extractor unit test to use real captured incident data instead of a drill incident's. - Implement TestConnection/TestExistingConnection via a cheap IncidentsService.QueryIncidents call, verified live against the real API. * refactor(grafana_irm): revert to connection-wide scoping, drop label filtering The originating feature request only asks for org-wide DORA correlation and never mentions per-team scoping. The label-based per-scope filtering added earlier this session was real and tested, but solved a problem nobody asked for, and config-ui has no generic manual-scope-entry component to build a UI for it on top of. Revert GrafanaIrmScopeConfig/GrafanaIrmOptions/the collector/converter to a single connection-wide scope with no filtering, same shape as incidentio/pagerduty. All incident labels are still collected and stored unconditionally, just no longer used to gate conversion. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(grafana_irm): add config-ui frontend and single-scope remote API Backend: add remote_api.go returning the one synthetic scope every connection has (config-ui's data-scope picker has no manual-entry flow to fall back to, so this feeds the standard remote-picker UI a single 'All Incidents' entry instead), wired into impl.go's routes. Frontend: add config-ui/src/plugins/register/grafana_irm (connection form, icon, registration) mirroring incidentio's shape, using the Grafana logo already vendored under grafana/img/. No custom scope-config UI is needed since GrafanaIrmScopeConfig carries no extra fields (Option A). Verified with tsc, eslint, and a production vite build - all clean. * fix(grafana_irm): fix error raised during testing * refactor(grafana_irm): collapse collect+refresh into one FinalizableApiCollector subtask The two-subtask design (CollectIncidents + RefreshOpenIncidents) caused three real bugs found via live pipeline testing: a panic, "Re-transform Data" silently deleting resolved incidents, and a genuine full sync also losing data because both subtasks independently wiped the raw table with no coordination between them. pagerduty solves the identical "list new/changed, then refresh still-open" need with DevLake's own FinalizableApiCollector as a single subtask, which prevents these bugs by construction (the framework never builds the "refresh" half on a full sync, and there's only one subtask name for Re-transform Data's filter to strip). Migrated CollectIncidents to that pattern; all existing collector logic (query building, change-detection via a request-scoped header) preserved, just re-wired. Live-verified against a real server: full sync restores all incidents correctly, incremental sync has no regression, and Re-transform Data no longer drops resolved incidents. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat(grafana_irm): add dedicated Grafana dashboard, docs, and domain board mapping - Add dedicated Grafana dashboards for MySQL and PostgreSQL dialects - Populate domain ticket.Board in ConvertIncidents to enable board filtering and joins - Update config-ui brand icon with official Grafana flame SVG - Add plugin documentation in backend/plugins/grafana_irm/README.md - Fix struct alignment formatting in models/incident.go * fix(grafana_irm): improve connection test error messages and add docs link * fix(grafana_irm): truncate timestamps to milliseconds and fix e2e postgres scope setup --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> (cherry picked from commit 6502e54)
* feat(youtrack): add plugin skeleton, init migration, and connection API
New youtrack plugin:
- 9 _tool_youtrack_* models (connection, project scope,
scope config with 6 field-name slots + flat name-keyed mappings,
account, issue, issue_comment, issue_label, workflow_state,
issue_changelog), all on common.NoPKModel with literal TableName()
- init migration over archived snapshots in GetTablesInfo() order,
with the ScopeConfig/Scope embeds hand-unrolled (archived helpers
don't carry them); schema_e2e gate passes against real MySQL
- permanent-token connection (helper.AccessToken, Bearer perm:...),
token encdec-encrypted, Sanitize-masked, MergeFromRequest-preserving
- endpoint hard-validated to end in /api at save and test time
- test-connection diagnostic matrix: guest-fallback assertion (a 2xx
proves nothing), 401, InCloud /youtrack-prefix hint on 404, soft
warning on non-perm: token shape, best-effort version probe
- registered in plugins/table_info_test.go and schema_e2e
Scope/scope-config/remote/proxy/blueprint APIs land in the next commit.
* feat(youtrack): add scope, scope-config, blueprint APIs, and proxy
Scope and API layer of the YouTrack plugin:
- remote-scopes lists the instance's projects via GET /admin/projects
with $top/$skip pagination, displaying 'shortName (name)' and
flagging archived projects
- scopes GET/PUT and per-scope GET/PATCH/DELETE via the datasource
helper; attaching a project creates the _tool_youtrack_projects row
- scope-config CRUD persists the six field-name slots and both JSON
mapping maps; Entities defaults to [TICKET, CROSS] on POST when the
body leaves it unset (handles both in-process []string and wire
[]interface{} shapes)
- singular un-nested scope-config/:scopeConfigId/projects route
(Linear asymmetry, copied verbatim)
- GET connections/:id/proxy/rest/*path for config-ui field/bundle
discovery
- blueprint v200 plan generation: scopes map to ticket.Board with ids
built from the internal project id (stable across shortName renames)
- swagger annotations on the new endpoints
* feat(youtrack): collect and convert issues with anonymised e2e fixtures
Add incremental issue and workflow-state collection, extraction and conversion for projects, accounts, issues and labels. Cover field mappings, retry behaviour and captured anonymised e2e fixtures.
* feat(youtrack): add comments slice — collect, extract, convert issue comments
Collect, Extract and Convert Comments subtasks, registered in
impl.go's SubTaskMetas order: per-issue comment collection
bounded by the incremental bookmark (input = tool issues with
updated >= since; all issues on full sync), extraction keeping the
deleted flag and deriving authors into accounts (CROSS-gated), and
conversion into issue_comments with didgen ids — deleted comments never
reach the domain layer.
The issues and comments endpoints now share one JSON-array response
parser (parseJsonArrayResponse in shared.go).
Fixture: 68 anonymised live-captured comments on the staged issues,
2 of them deleted; the issue_comments snapshot carries only the 66
non-deleted ones.
* feat(youtrack): add changelogs slice — collect, extract, convert issue changelogs
Collect, Extract and Convert Changelogs subtasks, registered in
impl.go's SubTaskMetas order: the activity feed flows into
issue_changelogs. Collection walks each changed issue's activitiesPage
cursor to hasAfter=false (cursors URL-encoded via url.Values, all filter
params repeated per request, the five configured categories mandatory).
Extraction lands one tool row per activity item with multi-value
added/removed JSON-encoded, deriving authors and assignee-change users
into accounts. Conversion maps state-field changes to std statuses via
the shared helper (mappings, else isResolved looked up from
_tool_youtrack_workflow_states by project+name, cached per run),
assignee changes to didgen account ids, everything else pass-through.
The comment collector's input bound is renamed to changedIssuesSince,
now shared by both per-issue collectors.
Fixture: 29 anonymised live-captured activity items covering all five
categories — State, Assignee and other custom-field changes, multi-value
Tags changes, Summary changes (text replaced with English filler), IssueCreated and
IssueResolved items.
E2e (changelog_test.go) covers these cases at the table seam plus a full-re-extract
idempotency assertion (upsert by activity id). Unit seams: cursor-walk
query/termination, added/removed value encoding, std-status and didgen
value conversion.
* feat(youtrack): add config-ui plugin — connection form, scope picker, transformation widget
* feat(youtrack): add MySQL and PostgreSQL Grafana dashboards
Provision the YouTrack dashboards for both database engines with Kanban metrics.
* fix(youtrack): preserve incremental state and replace stale data
Align changed-issue windows for comments and changelogs, keep only the latest issue and workflow-state snapshots on replay, and remove domain comments that were deleted upstream. Make API retries cancellation-aware with a single retry owner, and extend e2e scenarios and fixtures to cover these transitions.
Skip 404s from the per-issue comment and activity endpoints so an issue deleted upstream no longer fails the subtask and freezes its bookmark. Delete the scope's domain issue labels and assignees before converting, so they are replaced even when a run emits none.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* fix(youtrack): make e2e tests pass on a fresh MySQL and PostgreSQL database
CI runs the e2e suite against an empty database, where three things
failed that a reused local database hid:
- subtasks delete stale rows (labels, assignees, ...) before writing, so a
test that never created one of those tables failed with "table does not
exist"; newDataFlowTester now creates every table the subtasks touch
- rows appended after ImportCsvIntoRawTable collided with the CSV ids on
PostgreSQL, whose sequence the explicit-id import leaves at 1; they now
get an explicit id past the imported ones
- the mixed-language state-name check used MySQL-only REGEXP; it now runs
in Go
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
(cherry picked from commit b28f850)
(cherry picked from commit 7899890)
muzamilkm
force-pushed
the
chore/config-ui-upstream-sync
branch
from
October 5, 2026 16:17
8544810 to
3fcda8b
Compare
ubaidkhalidarbisoft
approved these changes
Oct 6, 2026
11 tasks done
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.
Summary
Syncs
config-uiwith upstream Apache DevLake, as the sync plan lays out (config-ui-upstream-sync-plan.md, sections 2–7). It cherry-picks the 47-commit ledger in chronological order with-xand ports our fork-only code to the new stack: React 19, antd 6, React Router 7, Vite 8, TypeScript 6, Node 24, Yarn 4, ESLint flat config and Vitest. It also brings dark mode (#8865) and connection grouping (#9130), the foundations of the reskin. The e2e suite from #81 runs green on the new stack in both auth states.Upstream cherry-picks
41 of the 47 ledger commits, in upstream order. Each keeps the upstream author, body and its
(cherry picked from commit …)line. Numbers are upstreamapache/devlakePRs.Stack and theme
#8865theme/tokens.ts, colour refactor#9006#9020#9130Fixes and features for plugins we ship
#8931#8972#9035#9024#9159#9034#9047#9014#9152#8935#8918#8952#8995initialValues#8903#9153#9135pathWithNamespace,scopeIdencoding#9097#9144#9097UI only,#9144whole#9166VITE_DEVLAKE_URLdev proxy#9093incubatorprefix removal.tool-versions)New upstream plugins, UI only
#8877Rootly ·#8884Tempo ·#8900Linear ·#9009ClickUp ·#9023incident.io ·#9076Kiro ·#9160Grafana IRM ·#9169YouTrackThese stay hidden: the UI lists only plugins the backend reports, and ours doesn't ship them.
Dependencies and images
#8940#9100#9188nginx ·#9044images and frontend deps ·#9112#9113#9114#9121#9158frontend bumps. Eachyarn.lockis regenerated with Yarn 4.17.0 rather than merged by hand.Not taken
#8878#9079#9084#9017cursorcollides with ours#9131#8808claude_code, already in via #79; resolves entirely to ours, so no commit#8935builds and passes its tests without upstream'suser_teams_collector.go.#9159registers only its own OAuth migration.#9159,#9152) have their imports rewritten togithub.com/apache/incubator-devlake/.fix(gitlab) - fix added…→fix(gitlab): …). The body and thecherry picked fromline are unchanged.Conflicts resolved toward ours
connection-form/index.tsx: our inline Test Connection payloads andpayload.tsstay. Upstream's new fields are added to both:enterprise(#8935) andcloudId(#9159). So is YouTrack's opt-in test-result message (#9169).utils/request.ts: our session verification, CSRF and 428 handling stay. Upstream's#9159change is added: a 401 from a plugin connection test no longer counts as a DevLake session expiry.routes/layout/layout.tsxandconfig.tsx: our account menu,OtelAttention,/accessentry and Grafana login link stay. The theme toggle is added. Upstream's unusedGRAFANA_PATHis dropped.routes/connection/connections.tsx: our Claude/OTel cards and credential counts stay. Grouping, the A–N / O–Z split by displayed name and the deprecation alert come from upstream.plugins/utils.ts:getPluginScopeIdlives in ourplugins/scope-id.ts, so the Linear (teamId) and ClickUp (folderId) cases go there.api/scopeencodesscopeId, andscope-id.tsdoesn't, so it's encoded exactly once.data-scope-select: our rewrite stays, with upstream's?? []guards from#9014re-applied.vite.config.ts: upstream's file, plus our Grafana OAuth proxy entries.package.json: upstream's, plus@playwright/test,test:e2eandtest:e2e:ui.yarn.lockis regenerated with Yarn 4.17.0 rather than merged by hand.#9044):grafana/Dockerfile13.2.2 and its provisioning lines);Fork code on the new stack
destroyOnClose→destroyOnHidden;maskClosable→mask={{ closable: false }};direction→orientation;message→title;addonAfter→Space.Compact.useRef<T>()calls becomeuseRef<T | undefined>(undefined)..eslintrc.jsande2e-tests/.eslintrc.cjsare gone;no-console: 'warn'moves toeslint.config.mjs;e2e-tests/**block turns offreact-hooks/rules-of-hooksfor Playwright'susefixture;eslint-plugin-headers.node --testfiles are ported to Vitest with identical test and assertion counts, andtsconfig.test.jsonis deleted.yarn testruns upstream's and ours together.access/utils.test.tsexpected a disabled OIDC provider to show as Configured.c98969b4bdeliberately added the Disabled state, and the test never ran because the old runner failed attscfirst. It now expects Disabled.E2E
.ant-modal-content.support/selectors.tsnow finds modals by accessible role (getByRole('dialog', { name })), which also survives the reskin.Typography.Text ellipsisin JS and keeps the full value only inaria-label. The test reads the cell's accessible name and still requires an exact match with the API'sorganizationId. On screen nothing changed: it's a truncated UUID with a copy button, as before.shell/themespec (sync plan, section 8.4):Other
chore(grafana): the Claude dashboard is titled "Claude Usage" instead of "Claude - MySQL".Test plan
devlakeandconfig-uilocally from this branch withFORCE_MIGRATION=true:AUTH_LOCAL_ENABLED=false): 40 passed, 24 skipped, 0 failed, identical tomain-arbisoft. The skips are exactly the local-auth specs.tsc --noEmit: 0 errors;eslint .: 0 errors;yarn test: 16 files, 91 tests passed;yarn build;yarn install --immutable.go buildandgo testpass for jira, github, gitlab, bitbucket, azuredevops_go and gh-copilot (the DB-backede2epackages run in CI). gitextractor needs libgit2 and compiles in the backend image.github.com/apache/devlake/imports remain. Every new migration is registered, and none collides with a fork migration.connection-form's test and save payloads is present in ours (scripted diff against upstream)./login,/access,/otel,/connections,/keys, projects and the account menu: everything is readable.connections/catalogspec).Notes for reviewers
config-ui. Runcorepack enable; the Yarn release is vendored under.yarn/releases. Node 18 and Yarn 3 no longer work.sub_query,extra_jql, OAuth 2.0 credentials) and Azure DevOps Go (endpoint,username,run_name). They're upstream migrations, but take a backup before deploying, as usual.yarn startdev proxy: Grafana now defaults tolocalhost:3001. Override it withVITE_GRAFANA_PROTOCOL/_HOST/_PORTif yours runs elsewhere.#9006. Reviewing commit by commit is easier: our own commits are227097827,bf0e167cf,d337cfed5,1504fa137,023691887,2c8f1224a,8a3dd355eand3fcda8bfb. The rest are upstream picks.