Skip to content

feat: add issues resolution endpoint under v1-alpha - #2236

Merged
epipav merged 4 commits into
mainfrom
feat/IN-1331-issues-resolution
Sep 21, 2026
Merged

epipav merged 4 commits into
mainfrom
feat/IN-1331-issues-resolution

Conversation

@epipav

@epipav epipav commented Sep 21, 2026 •

Copy link
Copy Markdown
Collaborator

What

Adds the first Development metric route to the alpha API:

GET /v1-alpha/projects/{slug}/development/issues-resolution?granularity=monthly&startDate=2025-06-20&endDate=2025-09-18&repos=<url>&repos=<url>

It returns the issues closed in the requested period against the previous period of the same length, the average time to resolve an issue in seconds, and one bucket per granularity step with the issues opened (totalIssues) and closed (closedIssues) in it.

{
  "summary": {
    "current": 100,
    "previous": 50,
    "percentageChange": 100,
    "changeValue": 50,
    "periodFrom": "2025-06-20T00:00:00Z",
    "periodTo": "2025-09-18T00:00:00Z",
    "avgResolveTimeSeconds": 7451999
  },
  "data": [
    { "startDate": "2025-06-01T00:00:00Z", "endDate": "2025-06-30T00:00:00Z", "totalIssues": 12, "closedIssues": 8 }
  ]
}

It ports frontend/server/data/tinybird/development/issues-resolution.ts call for call: one project_buckets lookup, then four activities_count calls (current summary, previous summary, opened series, closed series) and one issues_average_resolve_velocity call, all in flight together, with the same filter params the widget sends and dates as YYYY-MM-DD 00:00:00.

Renames against the Nuxt handler

  • avgVelocityInDays is now avgResolveTimeSeconds; the value was always seconds.
  • Bucket keys dateFrom / dateTo are now startDate / endDate.

Decisions

  • granularity is required. Without it the pipe returns a single summary row with no bucket dates, so the series would be malformed; the UI always sends it.
  • The route resolves the project's bucketId once through client.getBucketIdForProject and passes it on the five pipe calls (six Tinybird round trips instead of ten). A project without a bucket returns 200 with zero counts and data: [], per the epic's definition of done for metric endpoints.
  • Every Tinybird failure (any status, network error, non-JSON body) becomes 503 upstream_unavailable, logged with the pipe name. Tinybird's own status never reaches the caller.
  • percentageChange is signed (the widget used Math.abs), via the shared toPeriodSummary.
  • Output dates are YYYY-MM-DDT00:00:00Z everywhere in the response; bucket bounds take the same shape as periodFrom / periodTo.
  • avgResolveTimeSeconds is nullable: the velocity pipe returns no row, or a null average, when nothing was closed in scope.
  • The summary schema reuses PeriodSummary field by field and gives the three count fields endpoint-specific descriptions, since every response field carries a unit-bearing description (that is the docs reference entry). Shared files stay untouched so the four sibling Development PRs merge cleanly; the small helpers in this route (Tinybird day formatter, UTC midnight formatter, 503 wrapper, bucket merge) are candidates for the consolidation chore that follows.

Tests

api/tests/development-issues-resolution.test.ts: 33 tests with fetch stubbed at the HTTP boundary and routed by pipe path and params. They cover the response shape, every Tinybird call's params, concurrency of the five calls, omitted dates, merge edge cases, the unknown slug, validation (missing or unknown granularity, timestamp dates, inverted range), 503 mapping for pipe and lookup failures, Cache-Control, and the OpenAPI entry (tag Development, required granularity enum, a description on every response field, absent from /v1).

From api/: pnpm test (14 files, 195 tests), pnpm tsc-check, pnpm lint and pnpm format:check pass.

Includes the routing-test parser fix from the base branch (62b136b).

Based on main, which includes #2231 (IN-1345) as ef31c9e. Jira: IN-1331

Copilot AI balanced review requested due to automatic review settings September 21, 2026 11:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

Required API CI remains failing and the stacked base pull request has not merged.

Review effort: Balanced
Findings: 1 Low severity

Open (1)
What changed in this PR

Adds the first Development metric endpoint under /v1-alpha, backed by Tinybird.

Changes:

  • Registers the issues-resolution route.
  • Adds schemas, period summaries, bucket merging, and upstream error mapping.
  • Adds comprehensive integration and OpenAPI tests.
File Description
api/​src/​versions/​v1-alpha/​index.ts Registers the new route.
api/​src/​versions/​v1-alpha/​development/​issues-resolution.ts Implements the endpoint and response schema.
api/​tests/​development-issues-resolution.test.ts Covers behavior, validation, failures, and documentation.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread api/src/versions/v1-alpha/development/issues-resolution.ts Outdated
Copilot AI review requested due to automatic review settings September 21, 2026 11:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

The public period descriptions need correction, and required API CI remains failing on the stacked branch.

Review effort: Balanced
Findings: None

Resolved since last review (1)
Previously missed (1)

In code that hasn't changed since last review

Low severity getPreviousDates produces unequal elapsed-day periods

api/​src/​versions/​v1-alpha/​development/​issues-resolution.ts:56

getPreviousDates preserves a calendar-month/day duration, not an equal number of days: Jan 31–Mar 1 (30 days inclusive) compares against Dec 29–Jan 30 (33 days). Describing these periods as the same length misstates this field’s public contract.

This issue also appears on line 151 of the same file.

Copilot AI review requested due to automatic review settings September 21, 2026 11:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Two public schema descriptions incorrectly guarantee equal-length comparison periods.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Low severity

Open (1)

Comment thread api/src/versions/v1-alpha/development/issues-resolution.ts Outdated
Copilot AI review requested due to automatic review settings September 21, 2026 11:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The implementation matches the stated contract and includes thorough integration coverage for normal and failure paths.

Review effort: Balanced
Findings: None

Resolved since last review (1)

Copilot AI review requested due to automatic review settings September 21, 2026 11:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

The implementation matches the described contract and includes comprehensive integration coverage with no unresolved issues found.

Review effort: Balanced
Findings: None

@epipav epipav self-assigned this Sep 21, 2026

@gaspergrom gaspergrom left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed avgResolveTimeSeconds passes straight through from averageIssueResolveVelocitySeconds with no conversion, and the test on line 196 pins the exact seconds value from the mock to prove it. The five pipe calls run through Promise.all sharing one resolved bucketId, an unknown slug returns zero data after just the bucket lookup, and every Tinybird failure maps to 503 without leaking upstream detail. Solid test coverage.

Base automatically changed from feat/IN-1345-project-endpoint to main September 21, 2026 12:26
@epipav
epipav force-pushed the feat/IN-1331-issues-resolution branch from 0390a37 to d9dfc4e Compare September 21, 2026 12:29
@epipav
epipav merged commit 213f917 into main Sep 21, 2026
11 checks passed
@epipav
epipav deleted the feat/IN-1331-issues-resolution branch September 21, 2026 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants