Skip to content

Add nested license object and search sort=updated/releases#13

Merged
rainxchzed merged 1 commit intomainfrom
license-object-and-search-sort
May 5, 2026
Merged

Add nested license object and search sort=updated/releases#13
rainxchzed merged 1 commit intomainfrom
license-object-and-search-sort

Conversation

@rainxchzed
Copy link
Copy Markdown
Member

Summary

Two client-blocking asks landed together because they share a common denominator (every `RepoResponse` mapper).

1. Nested `license` object on RepoResponse

Client's `DetailsRepositoryImpl.getRepoStats` is still firing a direct-GitHub `/repos/{owner}/{name}` call for signed-in users to grab license info -- one full GitHub quota hit per stats fetch -- because the previously-shipped flat fields (`licenseSpdxId` / `licenseName`) didn't match the upstream shape.

Add the nested form alongside the flat fields:

```json
"license": { "spdxId": "MIT", "name": "MIT License" } | null
```

Same data, different shape, matches the upstream GitHub object verbatim. Once client switches to `license`, the direct-GitHub enrichment call goes away -- anon and signed-in both get license from backend, full quota preserved for the cases where direct-GitHub really is needed (refresh, signing-fingerprint, attestations).

`license` is null when both `licenseSpdxId` and `licenseName` are null (no LICENSE file detected). Otherwise it carries whatever subset of the two values is populated.

The flat fields remain on the response for back-compat with shipped client builds. They will be removed in a follow-up after the next client release migrates to `license.spdxId` / `license.name`.

Wired in every mapper: `RepoRepository.toRepoResponse`, `SearchRoutes.MeiliRepoHit.toRepoResponse`, `RepoRoutes.toMetadataOnlyResponse`, `GitHubSearchClient.RepoWithRelease.toRepoResponse`, `SearchRepository.search` (Postgres FTS path -- which previously didn't even SELECT the license columns; now does).

2. Search `sort` options + browse mode

Client's "Recently Updated" sort (PR #520) currently routes around the backend to direct GitHub `/search/repositories?sort=updated`, costing each user 60/hr (anon) or 5000/hr (signed-in) of their GitHub quota and breaking on networks that can't reach `api.github.com`.

Backend now accepts:

`sort` value Order Notes
`relevance` (default) ts_rank / Meili default requires `q`
`stars` `stars DESC` unchanged
`recent` `latest_release_date DESC` back-compat alias for `releases`
`releases` `latest_release_date DESC` new public name -- "fresh stable releases first"
`updated` `updated_at_gh DESC` new -- repo-level updated_at, GitHub-parity

`relevance` still requires a non-empty `q` (text-rank needs a query). Every other sort accepts an empty `q` for browse-mode listings -- "Recently Updated" / "Recent Releases" home tabs render against the indexed catalog without a search box.

`sort=updated` is routed directly to Postgres FTS until the fetcher repo's `meili_sync.py` adds `updated_at_gh` to Meili's sortable-attributes config. Postgres has the column already; Meili-side support comes for free once that fetcher PR lands.

The on-demand passthrough + miss-logging paths skip when `q` is blank -- a browse-mode catalog listing has no query to log or passthrough.

Test plan

  • Local: cannot run -- workstation Gradle cache lives on an unplugged external SSD. Relying on CI.
  • After deploy, hit `/v1/repo/sindresorhus/refined-github` -- expect both flat (`licenseSpdxId`) and nested (`license: { spdxId, name }`) fields populated.
  • Hit `/v1/search?sort=releases` (no `q`) -- expect 200 with items ordered by `latest_release_date DESC`.
  • Hit `/v1/search?sort=updated` (no `q`) -- expect 200 from Postgres path with items ordered by `updated_at_gh DESC`.
  • Hit `/v1/search?sort=relevance` (no `q`) -- expect 400 with the existing missing-q error.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 5, 2026

Warning

Rate limit exceeded

@rainxchzed has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 49 minutes and 1 second before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f2c8069e-9734-4ecc-88fb-fad0a6072bf7

📥 Commits

Reviewing files that changed from the base of the PR and between 0ece28a and f654317.

📒 Files selected for processing (8)
  • CLAUDE.md
  • src/main/kotlin/zed/rainxch/githubstore/db/MeilisearchClient.kt
  • src/main/kotlin/zed/rainxch/githubstore/db/RepoRepository.kt
  • src/main/kotlin/zed/rainxch/githubstore/db/SearchRepository.kt
  • src/main/kotlin/zed/rainxch/githubstore/ingest/GitHubSearchClient.kt
  • src/main/kotlin/zed/rainxch/githubstore/model/RepoResponse.kt
  • src/main/kotlin/zed/rainxch/githubstore/routes/RepoRoutes.kt
  • src/main/kotlin/zed/rainxch/githubstore/routes/SearchRoutes.kt
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch license-object-and-search-sort

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@rainxchzed rainxchzed merged commit a27580a into main May 5, 2026
2 checks passed
@rainxchzed rainxchzed deleted the license-object-and-search-sort branch May 5, 2026 10:47
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.

1 participant