-
-
Notifications
You must be signed in to change notification settings - Fork 821
feat(api): accept OATs in preview branch related endpoints #2517
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Adjusts the authentication in a couple of endpoints to accept OATs too.
|
WalkthroughThis change standardizes identity handling for branch operations by replacing raw userId parameters with a discriminated union context ({ type: "userMembership"; userId } | { type: "orgId"; organizationId }). Services updated: UpsertBranchService and ArchiveBranchService. Call sites updated in four routes to pass the new context and, where applicable, switch to authenticateRequest supporting personal and organization tokens. Prisma queries in services now branch on context type to authorize by membership or organizationId. Public method signatures in both services changed accordingly; surrounding control flow and payload structures remain the same. Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests
Tip 👮 Agentic pre-merge checks are now available in preview!Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.
Please see the documentation for more information. Example: reviews:
pre_merge_checks:
custom_checks:
- name: "Undocumented Breaking Changes"
mode: "warning"
instructions: |
Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal). Please share your feedback with us on this Discord post. 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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (9)
apps/webapp/app/services/archiveBranch.server.ts (2)
13-26
: Consolidate the identity type (OrgFilter) in a shared module.The discriminated union is duplicated across services. Export a single OrgFilter type (e.g., app/services/authz.ts) to prevent drift and ease future changes.
28-41
: Push the “must be a branch” check into the query (optional).Adding parentEnvironmentId: { not: null } to the where clause avoids fetching non-branch envs only to reject them later.
Apply this diff:
const environment = await this.#prismaClient.runtimeEnvironment.findFirstOrThrow({ where: { id: environmentId, + parentEnvironmentId: { not: null }, organization: orgFilter.type === "userMembership" ? { members: { some: { userId: orgFilter.userId, }, }, } : { id: orgFilter.organizationId }, },
apps/webapp/app/services/upsertBranch.server.ts (3)
17-26
: Unify OrgFilter type and decouple from route schema.
- Export a shared OrgFilter type to avoid duplication with ArchiveBranchService.
- Avoid importing CreateBranchOptions from a route; define a local/service‑level type or move the schema to a shared module to fix dependency direction.
151-156
: Fix logger message to reflect the service name.Rename the log label for clarity.
Apply this diff:
- logger.error("CreateBranchService error", { error: e }); + logger.error("UpsertBranchService error", { error: e });
167-179
: Use COUNT instead of fetching rows for limits (optional).Replace findMany + length with count queries to reduce I/O for large projects.
Apply this diff:
- const usedEnvs = await prisma.runtimeEnvironment.findMany({ - where: { - projectId, - branchName: { - not: null, - }, - archivedAt: null, - }, - }); - - const count = newBranchName - ? usedEnvs.filter((env) => env.branchName !== newBranchName).length - : usedEnvs.length; + const totalCount = await prisma.runtimeEnvironment.count({ + where: { projectId, branchName: { not: null }, archivedAt: null }, + }); + const existingWithSameName = newBranchName + ? await prisma.runtimeEnvironment.count({ + where: { projectId, branchName: newBranchName, archivedAt: null }, + }) + : 0; + const count = totalCount - existingWithSameName;apps/webapp/app/routes/api.v1.projects.$projectRef.branches.archive.ts (1)
52-73
: Minor perf tidy: filter archived in SQL and use findFirst (optional).You can avoid fetching multiple rows and in‑memory filtering by adding archivedAt: null and switching to findFirst. If you still need the “already archived” distinction, fall back to a second quick existence check when no active env is found.
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.ts (3)
5-5
: Consider unifying loader auth toauthenticateRequest
as wellAction now accepts org tokens; loader still uses PAT-only. If OATs should work for GET too, switch loader to
authenticateRequest
for consistency.Is the intent to allow OATs on the GET endpoint as well?
46-56
: Tighten Prisma filter: prefer scalar key for org path; use explicit relation filter for membershipFor clarity and query planning, filter by
organizationId
when you already have it, and use an explicit relation filter for the membership branch.Apply this diff:
- organization: - authenticationResult.type === "organizationAccessToken" - ? { id: authenticationResult.result.organizationId } - : { - members: { - some: { - userId: authenticationResult.result.userId, - }, - }, - }, + ...(authenticationResult.type === "organizationAccessToken" + ? { organizationId: authenticationResult.result.organizationId } + : { + organization: { + members: { + some: { userId: authenticationResult.result.userId }, + }, + }, + }),Note: If you prefer relation filters everywhere, use
organization: { is: { id: ... } }
explicitly for the org branch.
92-101
: Service identity handoff looks correct; drop unusedenv
var abovePassing
{ type: "orgId" | "userMembership", ... }
matches the new service signature. The destructuredenv
from Line 89 is unused; remove to satisfynoUnusedLocals
.Example:
// Line 89 const { branch, git } = parsed.data;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx
(1 hunks)apps/webapp/app/routes/api.v1.projects.$projectRef.branches.archive.ts
(4 hunks)apps/webapp/app/routes/api.v1.projects.$projectRef.branches.ts
(4 hunks)apps/webapp/app/routes/resources.branches.archive.tsx
(1 hunks)apps/webapp/app/services/archiveBranch.server.ts
(1 hunks)apps/webapp/app/services/upsertBranch.server.ts
(2 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
**/*.{ts,tsx}
: Always prefer using isomorphic code like fetch, ReadableStream, etc. instead of Node.js specific code
For TypeScript, we usually use types over interfaces
Avoid enums
No default exports, use function declarations
Files:
apps/webapp/app/routes/resources.branches.archive.tsx
apps/webapp/app/services/archiveBranch.server.ts
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.ts
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.archive.ts
apps/webapp/app/services/upsertBranch.server.ts
{packages/core,apps/webapp}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
We use zod a lot in packages/core and in the webapp
Files:
apps/webapp/app/routes/resources.branches.archive.tsx
apps/webapp/app/services/archiveBranch.server.ts
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.ts
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.archive.ts
apps/webapp/app/services/upsertBranch.server.ts
apps/webapp/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
When importing from @trigger.dev/core in the webapp, never import the root package path; always use one of the documented subpath exports from @trigger.dev/core’s package.json
Files:
apps/webapp/app/routes/resources.branches.archive.tsx
apps/webapp/app/services/archiveBranch.server.ts
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.ts
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.archive.ts
apps/webapp/app/services/upsertBranch.server.ts
{apps/webapp/app/**/*.server.{ts,tsx},apps/webapp/app/routes/**/*.ts}
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
Access environment variables only via the env export from app/env.server.ts; do not reference process.env directly
Files:
apps/webapp/app/services/archiveBranch.server.ts
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.ts
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.archive.ts
apps/webapp/app/services/upsertBranch.server.ts
apps/webapp/app/**/*.ts
📄 CodeRabbit inference engine (.cursor/rules/webapp.mdc)
Modules intended for test consumption under apps/webapp/app/**/*.ts must not read environment variables; accept configuration via options instead
Files:
apps/webapp/app/services/archiveBranch.server.ts
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.ts
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.archive.ts
apps/webapp/app/services/upsertBranch.server.ts
🧬 Code graph analysis (3)
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.ts (1)
apps/webapp/app/services/apiAuth.server.ts (1)
authenticateRequest
(379-441)
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.archive.ts (1)
apps/webapp/app/services/apiAuth.server.ts (1)
authenticateRequest
(379-441)
apps/webapp/app/services/upsertBranch.server.ts (1)
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx (2)
CreateBranchOptions
(108-112)CreateBranchOptions
(114-114)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (22)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
- GitHub Check: typecheck / typecheck
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (8)
apps/webapp/app/services/upsertBranch.server.ts (1)
46-56
: LGTM: authorization filter matches token context.Conditional organization filter via membership vs orgId is correct and consistent with archive flow.
apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.$projectParam.env.$envParam.branches/route.tsx (1)
132-136
: LGTM: updated call signature is correct.Route now passes the identity descriptor and payload as separate args, aligned with the service change.
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.archive.ts (3)
24-29
: Auth path updated to allow OATs — good.authenticateRequest with personalAccessToken + organizationAccessToken (apiKey disabled) aligns with the PR goal.
58-67
: DB filtering matches auth context — good.Org membership vs orgId branching is correct.
85-92
: LGTM: service call uses the correct identity descriptor.Organization tokens map to { type: "orgId" } and PATs to { type: "userMembership" } as expected.
apps/webapp/app/routes/resources.branches.archive.tsx (1)
40-45
: LGTM for this file — identity descriptor passed correctly; repo still contains legacy single-object .call(...) sites.ArchiveBranchService calls in this PR use the identity descriptor correctly.
Examples of remaining single-object .call({...}) usages found:
- apps/webapp/app/routes/api.v1.projects.$projectRef.branches.archive.ts:85-86
- apps/webapp/app/services/projectSettings.server.ts:36
- apps/webapp/app/services/deleteOrganization.server.ts:72
- apps/webapp/app/v3/services/createCheckpoint.server.ts:320
Confirm whether those sites should be migrated to the (identityDescriptor, payload) signature.
apps/webapp/app/routes/api.v1.projects.$projectRef.branches.ts (2)
1-1
: Type-only imports: good changeUsing type-only imports reduces runtime bundle size and matches our TS guidelines.
23-27
: OATs are handled as organizationAccessToken in authenticateRequest — no action required.
authenticateRequest checks allowedMethods.organizationAccessToken and calls authenticateApiRequestWithOrganizationAccessToken; organizationAccessToken.server.ts uses the "tr_oat_" prefix and isOrganizationAccessToken(token) checks startsWith(tokenPrefix).
Adjusts the authentication in a couple of endpoints to accept OATs too.