Skip to content

fix(deployment): scope GitHub repo list to app installations#2510

Merged
ygrishajev merged 1 commit intomainfrom
fix/deployment
Jan 16, 2026
Merged

fix(deployment): scope GitHub repo list to app installations#2510
ygrishajev merged 1 commit intomainfrom
fix/deployment

Conversation

@ygrishajev
Copy link
Contributor

@ygrishajev ygrishajev commented Jan 15, 2026

refs #2509, #2511

Summary by CodeRabbit

  • New Features

    • Configurable GitHub integration settings for login (installation URL, client ID, redirect).
  • Bug Fixes

    • Improved GitHub repo discovery: aggregates repos across installations, supports pagination, and deduplicates results.
    • More reliable OAuth token exchange and added re-login validation when client ID is missing.
  • Behavior Change

    • Deployment page now proceeds only when a template ID or repo URL is present; removed prior auto-selection by repo URL.
  • UI / Stability

    • Stabilized callbacks and memoization for repo listing, CPU input handling, and folder selection.

✏️ Tip: You can customize this high-level summary in your review settings.

@ygrishajev ygrishajev requested a review from a team as a code owner January 15, 2026 14:32
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 15, 2026

📝 Walkthrough

Walkthrough

Accepts GitHubService options, makes API clients and options private, changes repo fetching to list installations and paginate per-installation repositories with deduplication, updates DI to pass new options, and adjusts several UI hooks/components and server-side props flow.

Changes

Cohort / File(s) Summary
GitHub HTTP service
apps/deploy-web/src/services/remote-deploy/github-http.service.ts
Added GitHubServiceOptions; converted API clients and options to private class fields (#githubApiService, #internalApiService, #options); constructor signature updated to accept options; loginWithGithub/reLoginWithGithub now use provided options and validate clientId; fetchRepos lists /user/installations then paginates /user/installations/{installationId}/repositories via #fetchAllReposForInstallation, flattens and deduplicates repos; other fetch methods and token exchange use private clients.
DI container / instantiation
apps/deploy-web/src/services/app-di-container/browser-di-container.ts
githubService factory updated to instantiate GitHubService with the new options object { githubAppInstallationUrl, githubClientId, redirectUrl } sourced from publicConfig.
Server-side props / New deployment flow
apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts
Removed early-return when repoUrl present; now requires at least one of templateId or repoUrl; uses query.templateId or CI_CD_TEMPLATE_ID for template lookup; adjusts returned props shape to conditionally include template.
UI: Repos component
apps/deploy-web/src/components/remote-deploy/Repos.tsx
Replaced inline handlers with memoized useCallback wrappers for CPU clamping (handleSetCpus) and folder setting (setFolders) to stabilize dependencies.
UI: GitHub manager
apps/deploy-web/src/components/remote-deploy/github/GithubManager.tsx
Added useMemo computed mappedRepos (filter/map) and pass it to Repos to avoid inline recomputation; added useMemo import.
Config removal
apps/deploy-web/src/config/remote-deploy.config.ts
Removed exported REDIRECT_URL and its browserEnvConfig dependency.
Hook: remote deploy framework
apps/deploy-web/src/hooks/useRemoteDeployFramework.tsx
Replaced inline setValueHandler with a useCallback memoized handler for package.json processing and CPU calculation; stabilizes dependent queries.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant GitHubService
  participant GitHubAPI as "GitHub API"
  participant InternalAPI as "Internal API"

  Client->>GitHubService: fetchRepos()
  GitHubService->>GitHubAPI: GET /user/installations
  GitHubAPI-->>GitHubService: installations[]
  alt no installations
    GitHubService-->>Client: []
  else
    loop for each installation
      GitHubService->>GitHubAPI: GET /user/installations/{installationId}/repositories?per_page=150&page=N
      GitHubAPI-->>GitHubService: repositories_page[]
      GitHubService->>GitHubService: accumulate pages (`#fetchAllReposForInstallation`)
    end
    GitHubService->>GitHubService: flatten + dedupe repos by id
    GitHubService-->>Client: deduplicated repos[]
  end
  Client->>GitHubService: fetchAccessToken(code)
  GitHubService->>InternalAPI: POST /exchange-token (uses `#internalApiService`)
  InternalAPI-->>GitHubService: access_token
  GitHubService-->>Client: access_token
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • baktun14
  • stalniy

Poem

🐇 I hop through installs and gather each tree,

Page by page I fetch them so merrily,
I flatten the lists and drop duplicates fine,
Then hand you the repos to deploy on time.
🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: scoping GitHub repository retrieval to app installations instead of a single user endpoint.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

🧹 Recent nitpick comments
apps/deploy-web/src/components/remote-deploy/Repos.tsx (1)

68-73: Minor: Redundant unary plus operator.

Since cpus is already typed as number, the +cpus conversion is unnecessary. Consider simplifying:

Suggested simplification
 const handleSetCpus = useCallback(
   (cpus: number) => {
-    setValue("services.0.profile.cpu", +cpus > 2 ? +cpus : 2);
+    setValue("services.0.profile.cpu", cpus > 2 ? cpus : 2);
   },
   [setValue]
 );
apps/deploy-web/src/components/remote-deploy/github/GithubManager.tsx (1)

28-41: Inconsistent optional chaining usage.

The optional chaining is applied inconsistently across property accesses, which may cause runtime errors if repo or nested properties are unexpectedly undefined:

  • repo.owner?.login vs repo?.owner?.type
  • repo.name vs repo?.default_branch
Suggested fix for consistent null safety
 const mappedRepos = useMemo(
   () =>
     repos
-      ?.filter(repo => repo.owner?.login === profile?.login || repo?.owner?.type === "Organization")
+      ?.filter(repo => repo?.owner?.login === profile?.login || repo?.owner?.type === "Organization")
       ?.map(repo => ({
-        name: repo.name,
+        name: repo?.name,
         default_branch: repo?.default_branch,
         html_url: repo?.html_url,
         private: repo?.private,
-        id: repo.id?.toString(),
+        id: repo?.id?.toString(),
         owner: repo?.owner
       })),
   [profile?.login, repos]
 );

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 97f2bc5 and 8ef5689.

📒 Files selected for processing (7)
  • apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts
  • apps/deploy-web/src/components/remote-deploy/Repos.tsx
  • apps/deploy-web/src/components/remote-deploy/github/GithubManager.tsx
  • apps/deploy-web/src/config/remote-deploy.config.ts
  • apps/deploy-web/src/hooks/useRemoteDeployFramework.tsx
  • apps/deploy-web/src/services/app-di-container/browser-di-container.ts
  • apps/deploy-web/src/services/remote-deploy/github-http.service.ts
💤 Files with no reviewable changes (1)
  • apps/deploy-web/src/config/remote-deploy.config.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/deploy-web/src/hooks/useRemoteDeployFramework.tsx
  • apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{ts,tsx,js}: Never use type any or cast to type any. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.

Files:

  • apps/deploy-web/src/services/remote-deploy/github-http.service.ts
  • apps/deploy-web/src/components/remote-deploy/github/GithubManager.tsx
  • apps/deploy-web/src/components/remote-deploy/Repos.tsx
  • apps/deploy-web/src/services/app-di-container/browser-di-container.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: baktun14
Repo: akash-network/console PR: 1725
File: apps/api/src/utils/constants.ts:5-5
Timestamp: 2025-07-24T17:00:52.361Z
Learning: In the Akash Network Console project, when cross-cutting concerns or broader refactoring issues are identified during PR review, the preferred approach is to create a separate GitHub issue to track the work rather than expanding the scope of the current PR. This maintains focus and allows for proper planning of architectural improvements.
📚 Learning: 2025-06-05T21:07:51.985Z
Learnt from: baktun14
Repo: akash-network/console PR: 1432
File: apps/deploy-web/src/components/deployments/DeploymentAlerts/DeploymentCloseAlert.tsx:38-38
Timestamp: 2025-06-05T21:07:51.985Z
Learning: The ContactPointSelect component in apps/deploy-web/src/components/alerts/ContactPointSelectForm/ContactPointSelect.tsx uses the useFormContext hook internally to connect to React Hook Form, so it doesn't need to be wrapped in a FormField component.

Applied to files:

  • apps/deploy-web/src/components/remote-deploy/github/GithubManager.tsx
  • apps/deploy-web/src/components/remote-deploy/Repos.tsx
📚 Learning: 2025-06-19T16:00:05.428Z
Learnt from: ygrishajev
Repo: akash-network/console PR: 1512
File: apps/deploy-web/src/components/deployments/DeploymentBalanceAlert/DeploymentBalanceAlert.tsx:47-68
Timestamp: 2025-06-19T16:00:05.428Z
Learning: In React Hook Form setups with zod validation, child components using useFormContext() can rely on parent form validation rather than implementing local input validation. Invalid inputs like NaN from parseFloat() are handled by the parent schema validation, eliminating the need for additional local validation in child components.

Applied to files:

  • apps/deploy-web/src/components/remote-deploy/github/GithubManager.tsx
  • apps/deploy-web/src/components/remote-deploy/Repos.tsx
🧬 Code graph analysis (3)
apps/deploy-web/src/services/remote-deploy/github-http.service.ts (4)
apps/deploy-web/src/types/remotedeploy.ts (1)
  • GithubRepository (2-2)
packages/http-sdk/src/index.ts (1)
  • createHttpClient (27-27)
apps/deploy-web/src/types/remoteProfile.ts (1)
  • GitHubProfile (2-2)
apps/deploy-web/src/types/remoteCommits.ts (1)
  • GitCommit (2-2)
apps/deploy-web/src/components/remote-deploy/Repos.tsx (2)
apps/deploy-web/src/types/remotedeploy.ts (1)
  • IGithubDirectoryItem (3-5)
apps/deploy-web/src/config/remote-deploy.config.ts (1)
  • protectedEnvironmentVariables (5-22)
apps/deploy-web/src/services/app-di-container/browser-di-container.ts (1)
apps/deploy-web/src/services/remote-deploy/github-http.service.ts (1)
  • GitHubService (24-174)
⏰ 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). (3)
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (10)
apps/deploy-web/src/components/remote-deploy/Repos.tsx (2)

74-80: LGTM!

The setFolders callback correctly uses an empty dependency array since setDirectory is a state setter with a stable reference. The conditional logic for handling empty data is clear.


83-89: LGTM!

Passing the memoized handleSetCpus callback stabilizes the reference, which is beneficial for preventing unnecessary re-computations in useRemoteDeployFramework.

apps/deploy-web/src/components/remote-deploy/github/GithubManager.tsx (1)

45-53: LGTM!

Good refactoring to move the repo filtering and mapping logic into a memoized computation, keeping the JSX cleaner and preventing unnecessary recalculations.

apps/deploy-web/src/services/app-di-container/browser-di-container.ts (1)

31-36: LGTM!

The options object correctly provides the required configuration for the updated GitHubService constructor. The property names align with GitHubServiceOptions, and sourcing these values from publicConfig is appropriate for browser-side configuration.

apps/deploy-web/src/services/remote-deploy/github-http.service.ts (6)

9-22: Clean type definitions.

The new types are well-structured. GitHubInstallationsResponse and GitHubInstallationReposResponse properly model the GitHub API responses, and GitHubServiceOptions correctly marks githubClientId as optional since it's only required for reLoginWithGithub.


24-41: LGTM!

Good use of private class fields (#) for encapsulation. The constructor properly initializes the GitHub API client with appropriate headers and stores the configuration options.


47-61: OAuth URL construction properly implemented.

The use of URL and URLSearchParams APIs ensures proper RFC 3986 encoding of the redirect URI, preventing parameter dropping issues. The validation for githubClientId presence is appropriate.


72-99: Well-implemented installations-scoped repository fetching.

Good design choices:

  • Promise.allSettled ensures partial results on failures rather than complete failure
  • Deduplication by repo.id handles potential overlaps across installations
  • Early return for no installations avoids unnecessary processing

101-132: Pagination logic is robust.

The implementation correctly:

  • Uses per_page=100 (GitHub's maximum)
  • Includes empty-page guard to prevent infinite loops (line 122-124)
  • Includes max-pages guard as additional safety (line 125-127)

134-173: LGTM!

All remaining methods consistently use the private class fields. The update to #internalApiService for fetchAccessToken is correct.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/deploy-web/src/services/remote-deploy/github-http.service.ts`:
- Around line 62-71: The current fetch for installation repositories uses
per_page=150, lacks pagination, and uses Promise.all which fails fast; change
the query to per_page=100, implement paginated fetching for each installation by
following the Link header (or next page URL) returned by githubApiService.get
until no next link, aggregating all response.data.repositories, and replace
Promise.all over installations.installations with Promise.allSettled so you
collect successful results and ignore/record failures; update the block that
builds repos (referencing installations.installations, the githubApiService.get
call, and the repos variable) to accumulate repositories per installation from
all pages and return the flattened successful lists while logging or capturing
errors from rejected promises.
🧹 Nitpick comments (1)
apps/deploy-web/src/services/remote-deploy/github-http.service.ts (1)

51-59: Consider the case when token is null/undefined.

The token parameter is optional (token?: string | null), but when null or undefined, the Authorization: Bearer ${token} header will send "Bearer null" or "Bearer undefined", which will fail authentication. This pattern is consistent with other methods in the class, but worth noting.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3bfa541 and 8bd84d7.

📒 Files selected for processing (1)
  • apps/deploy-web/src/services/remote-deploy/github-http.service.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{ts,tsx,js}: Never use type any or cast to type any. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.

Files:

  • apps/deploy-web/src/services/remote-deploy/github-http.service.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: baktun14
Repo: akash-network/console PR: 1725
File: apps/api/src/utils/constants.ts:5-5
Timestamp: 2025-07-24T17:00:52.361Z
Learning: In the Akash Network Console project, when cross-cutting concerns or broader refactoring issues are identified during PR review, the preferred approach is to create a separate GitHub issue to track the work rather than expanding the scope of the current PR. This maintains focus and allows for proper planning of architectural improvements.
🧬 Code graph analysis (1)
apps/deploy-web/src/services/remote-deploy/github-http.service.ts (1)
apps/deploy-web/src/types/remotedeploy.ts (1)
  • GithubRepository (2-2)
🔇 Additional comments (2)
apps/deploy-web/src/services/remote-deploy/github-http.service.ts (2)

73-78: Deduplication logic looks correct.

Using a Map keyed by repo.id is an effective way to deduplicate repositories that may appear across multiple installations.


11-16: > Likely an incorrect or invalid review comment.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@codecov
Copy link

codecov bot commented Jan 15, 2026

Codecov Report

❌ Patch coverage is 6.09756% with 77 lines in your changes missing coverage. Please review.
✅ Project coverage is 50.48%. Comparing base (52ed0b8) to head (8ef5689).
⚠️ Report is 1 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
.../src/services/remote-deploy/github-http.service.ts 8.33% 44 Missing ⚠️
.../deploy-web/src/components/remote-deploy/Repos.tsx 0.00% 12 Missing ⚠️
.../deploy-web/src/hooks/useRemoteDeployFramework.tsx 0.00% 11 Missing ⚠️
.../components/remote-deploy/github/GithubManager.tsx 0.00% 8 Missing ⚠️
...loyment/NewDeploymentPage/createServerSideProps.ts 0.00% 2 Missing ⚠️

❌ Your patch status has failed because the patch coverage (6.09%) is below the target coverage (50.00%). You can increase the patch coverage or adjust the target coverage.
❌ Your project status has failed because the head coverage (79.31%) is below the target coverage (80.00%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2510      +/-   ##
==========================================
- Coverage   50.86%   50.48%   -0.39%     
==========================================
  Files        1063     1053      -10     
  Lines       29432    29127     -305     
  Branches     6497     6467      -30     
==========================================
- Hits        14972    14705     -267     
+ Misses      14056    14018      -38     
  Partials      404      404              
Flag Coverage Δ *Carryforward flag
api 79.31% <ø> (ø) Carriedforward from 52ed0b8
deploy-web 31.23% <6.09%> (-0.10%) ⬇️
log-collector ?
notifications 87.94% <ø> (ø) Carriedforward from 52ed0b8
provider-console 81.48% <ø> (ø) Carriedforward from 52ed0b8
provider-proxy 84.35% <ø> (ø) Carriedforward from 52ed0b8

*This pull request uses carry forward flags. Click here to find out more.

Files with missing lines Coverage Δ
apps/deploy-web/src/config/remote-deploy.config.ts 100.00% <ø> (ø)
.../services/app-di-container/browser-di-container.ts 68.75% <100.00%> (ø)
...loyment/NewDeploymentPage/createServerSideProps.ts 0.00% <0.00%> (ø)
.../components/remote-deploy/github/GithubManager.tsx 0.00% <0.00%> (ø)
.../deploy-web/src/hooks/useRemoteDeployFramework.tsx 0.00% <0.00%> (ø)
.../deploy-web/src/components/remote-deploy/Repos.tsx 0.00% <0.00%> (ø)
.../src/services/remote-deploy/github-http.service.ts 9.23% <8.33%> (-12.65%) ⬇️

... and 11 files with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

stalniy
stalniy previously approved these changes Jan 15, 2026
baktun14
baktun14 previously approved these changes Jan 15, 2026
@ygrishajev ygrishajev force-pushed the fix/deployment branch 2 times, most recently from 72fd4ad to 9860f0f Compare January 15, 2026 17:27
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/deploy-web/src/services/remote-deploy/github-http.service.ts`:
- Around line 93-116: In `#fetchAllReposForInstallation` add a safeguard to avoid
an infinite loop when the API reports total_count > 0 but returns empty page
results: after extracting pageRepos, if pageRepos.length === 0 then break the
loop (or throw a descriptive error) to stop pagination; optionally also add a
max-iterations safety using page or perPage to cap the loop. Update the loop
logic to use the new guard so repositories, totalCount, pageRepos, perPage and
page are consistent and the function always terminates.
🧹 Nitpick comments (1)
apps/deploy-web/src/services/remote-deploy/github-http.service.ts (1)

47-53: URL construction may break if redirectUrl contains existing query parameters.

Line 52 appends ?step=edit-deployment&type=github directly. If redirectUrl already includes query parameters, this would produce an invalid URL (e.g., ...?existing=param?step=...).

Consider using URL API or a conditional separator:

♻️ Suggested fix
  reLoginWithGithub() {
    if (!this.#options.githubClientId) {
      throw new Error("GitHub client ID is required to re-login with GitHub");
    }

-   window.location.href = `https://github.com/login/oauth/authorize?client_id=${this.#options.githubClientId}&redirect_uri=${this.#options.redirectUrl}?step=edit-deployment&type=github`;
+   const separator = this.#options.redirectUrl.includes("?") ? "&" : "?";
+   const redirectUri = `${this.#options.redirectUrl}${separator}step=edit-deployment&type=github`;
+   window.location.href = `https://github.com/login/oauth/authorize?client_id=${this.#options.githubClientId}&redirect_uri=${encodeURIComponent(redirectUri)}`;
  }

Note: The redirect_uri parameter value should also be URL-encoded to handle special characters safely.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a773519 and 9860f0f.

📒 Files selected for processing (3)
  • apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts
  • apps/deploy-web/src/services/app-di-container/browser-di-container.ts
  • apps/deploy-web/src/services/remote-deploy/github-http.service.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{ts,tsx,js}: Never use type any or cast to type any. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.

Files:

  • apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts
  • apps/deploy-web/src/services/app-di-container/browser-di-container.ts
  • apps/deploy-web/src/services/remote-deploy/github-http.service.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: baktun14
Repo: akash-network/console PR: 1725
File: apps/api/src/utils/constants.ts:5-5
Timestamp: 2025-07-24T17:00:52.361Z
Learning: In the Akash Network Console project, when cross-cutting concerns or broader refactoring issues are identified during PR review, the preferred approach is to create a separate GitHub issue to track the work rather than expanding the scope of the current PR. This maintains focus and allows for proper planning of architectural improvements.
🧬 Code graph analysis (2)
apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts (1)
apps/deploy-web/src/config/remote-deploy.config.ts (1)
  • CI_CD_TEMPLATE_ID (3-3)
apps/deploy-web/src/services/app-di-container/browser-di-container.ts (1)
apps/deploy-web/src/services/remote-deploy/github-http.service.ts (1)
  • GitHubService (24-158)
⏰ 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). (2)
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
🔇 Additional comments (4)
apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts (1)

21-34: Verify: fetched template is discarded when only repoUrl is provided.

When only repoUrl is provided (no templateId):

  1. Template is fetched using CI_CD_TEMPLATE_ID (Line 25)
  2. However, Line 30's condition template && query.templateId is falsy since query.templateId is undefined
  3. Line 34 returns { templateId: undefined }, discarding the fetched template

If the intent is to always return the template when repoUrl triggers the CI/CD flow, the condition on Line 30 may need adjustment. Otherwise, the findById call is unnecessary overhead when only repoUrl is provided.

apps/deploy-web/src/services/remote-deploy/github-http.service.ts (2)

64-91: Good use of Promise.allSettled for resilience.

The implementation correctly handles partial failures when fetching repositories from multiple installations, and the deduplication logic using Map by repo.id is sound. This addresses the concerns from the previous review.


118-157: LGTM!

The remaining API methods consistently use the private #githubApiService client with proper authorization headers. The fetchAccessToken method correctly uses #internalApiService for internal API communication.

apps/deploy-web/src/services/app-di-container/browser-di-container.ts (1)

31-36: LGTM!

The GitHubService factory correctly passes the required options object matching the GitHubServiceOptions type. Configuration values are properly sourced from publicConfig.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

@ygrishajev ygrishajev force-pushed the fix/deployment branch 2 times, most recently from e348660 to 7ee1527 Compare January 16, 2026 09:29
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts (1)

21-34: Return the fetched CI/CD template when repoUrl is provided without explicit templateId.

Lines 21-34 have a logic flaw: when a user provides only repoUrl (without templateId), the code fetches the CI/CD template as a fallback on line 25, but then fails to return it because the condition on line 30 requires both template to exist and query.templateId to be explicitly set. This causes line 34 to return { templateId: undefined }, leaving the component without a template to work with.

While the deploy button flow mitigates this by always including templateId: CI_CD_TEMPLATE_ID alongside repoUrl, manually constructed URLs with only repoUrl will fail silently. Consider:

  • Return the template object when successfully fetched
  • Set templateId to CI_CD_TEMPLATE_ID in the response when it was used as the fallback
🧹 Nitpick comments (1)
apps/deploy-web/src/services/remote-deploy/github-http.service.ts (1)

81-88: Consider logging failed installation fetches for observability.

When Promise.allSettled returns rejected results, they are silently ignored. While this is acceptable for resilience, logging failures would help with debugging and monitoring.

♻️ Optional: Add logging for failed fetches
     const uniqueRepos = new Map<number, GithubRepository>();
     repoResults.forEach(result => {
       if (result.status === "fulfilled") {
         result.value.forEach(repo => {
           uniqueRepos.set(repo.id, repo);
         });
+      } else {
+        console.warn("Failed to fetch repositories for installation:", result.reason);
       }
     });

Note: If a logging service is available in the codebase, prefer using that over console.warn.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9860f0f and e348660.

📒 Files selected for processing (3)
  • apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts
  • apps/deploy-web/src/services/app-di-container/browser-di-container.ts
  • apps/deploy-web/src/services/remote-deploy/github-http.service.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{ts,tsx,js}: Never use type any or cast to type any. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.

Files:

  • apps/deploy-web/src/services/app-di-container/browser-di-container.ts
  • apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts
  • apps/deploy-web/src/services/remote-deploy/github-http.service.ts
🧬 Code graph analysis (1)
apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts (1)
apps/deploy-web/src/config/remote-deploy.config.ts (1)
  • CI_CD_TEMPLATE_ID (3-3)
⏰ 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). (4)
  • GitHub Check: validate (apps/deploy-web) / validate-unsafe
  • GitHub Check: validate / validate-app
  • GitHub Check: test-build
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
apps/deploy-web/src/services/remote-deploy/github-http.service.ts (4)

1-22: LGTM! Well-structured type definitions.

The new types GitHubInstallationsResponse, GitHubInstallationReposResponse, and GitHubServiceOptions are properly defined with appropriate typing. Good use of components["schemas"]["installation"] from @octokit/openapi-types for type safety.


24-41: LGTM! Clean constructor refactor with proper encapsulation.

Good use of private class fields (#) for encapsulation. The constructor properly initializes all dependencies and the options pattern allows for flexible configuration injection.


64-91: LGTM! Robust implementation with proper error handling and deduplication.

Good improvements over previous implementation:

  • Promise.allSettled ensures partial failures don't break the entire operation
  • Deduplication via Map<number, GithubRepository> handles repos accessible through multiple installations
  • Early return for empty installations avoids unnecessary API calls

93-124: LGTM! Pagination logic with proper safeguards.

The implementation addresses previous review concerns:

  • per_page=100 respects GitHub API limits
  • Empty page guard (pageRepos.length === 0) prevents infinite loops
  • maxPages calculation provides additional termination safety
apps/deploy-web/src/services/app-di-container/browser-di-container.ts (1)

31-36: LGTM! Correct DI configuration for the updated GitHubService.

The options object correctly maps environment configuration values to the GitHubServiceOptions type expected by the new GitHubService constructor. The property names align properly with the service's requirements.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts (1)

25-35: Fix undefined templateId in repoUrl-only flow.
When repoUrl is present but templateId isn’t, you fetch a template using CI_CD_TEMPLATE_ID but still return templateId: undefined. This regresses the repoUrl-only path. Return the resolved ID (or the template’s id) when a template is found, and avoid passing undefined.

🔧 Suggested fix
-      const template = await services.template.findById(query.templateId || CI_CD_TEMPLATE_ID).catch(error => {
+      const resolvedTemplateId = query.templateId ?? CI_CD_TEMPLATE_ID;
+      const template = await services.template.findById(resolvedTemplateId).catch(error => {
         services.logger.warn({ error });
         return null;
       });

-      if (template && query.templateId) {
-        return { props: { template, templateId: query.templateId } };
+      if (template && query.templateId) {
+        return { props: { template, templateId: resolvedTemplateId } };
       }
 
-      return { props: { templateId: query.templateId } };
+      if (template) {
+        return { props: { templateId: resolvedTemplateId } };
+      }
+
+      return { props: query.templateId ? { templateId: resolvedTemplateId } : {} };
🤖 Fix all issues with AI agents
In `@apps/deploy-web/src/services/remote-deploy/github-http.service.ts`:
- Around line 47-53: In reLoginWithGithub(), the redirect_uri query is being
inlined and not URL-encoded causing the inner “?step=…” to be treated as
top-level OAuth params; instead construct the redirect URI using the URL and
URLSearchParams APIs (e.g., create a new URL from this.#options.redirectUrl,
append step=edit-deployment and type=github via searchParams) then use its
toString() (or encodeURIComponent if composing manually) when building the OAuth
URL with client_id; update reLoginWithGithub to throw if githubClientId missing,
build the properly encoded redirect_uri via URL/URLSearchParams, and set
window.location.href to the OAuth authorize URL with that encoded redirect_uri.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e348660 and 7ee1527.

📒 Files selected for processing (3)
  • apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts
  • apps/deploy-web/src/services/app-di-container/browser-di-container.ts
  • apps/deploy-web/src/services/remote-deploy/github-http.service.ts
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (.cursor/rules/general.mdc)

**/*.{ts,tsx,js}: Never use type any or cast to type any. Always define the proper TypeScript types.
Never use deprecated methods from libraries.
Don't add unnecessary comments to the code.

Files:

  • apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts
  • apps/deploy-web/src/services/app-di-container/browser-di-container.ts
  • apps/deploy-web/src/services/remote-deploy/github-http.service.ts
🧠 Learnings (1)
📓 Common learnings
Learnt from: baktun14
Repo: akash-network/console PR: 1725
File: apps/api/src/utils/constants.ts:5-5
Timestamp: 2025-07-24T17:00:52.361Z
Learning: In the Akash Network Console project, when cross-cutting concerns or broader refactoring issues are identified during PR review, the preferred approach is to create a separate GitHub issue to track the work rather than expanding the scope of the current PR. This maintains focus and allows for proper planning of architectural improvements.
🧬 Code graph analysis (2)
apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts (1)
apps/deploy-web/src/config/remote-deploy.config.ts (1)
  • CI_CD_TEMPLATE_ID (3-3)
apps/deploy-web/src/services/remote-deploy/github-http.service.ts (3)
apps/deploy-web/src/types/remotedeploy.ts (1)
  • GithubRepository (2-2)
apps/deploy-web/src/types/remoteProfile.ts (1)
  • GitHubProfile (2-2)
apps/deploy-web/src/types/remoteCommits.ts (1)
  • GitCommit (2-2)
⏰ 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). (1)
  • GitHub Check: test-build
🔇 Additional comments (6)
apps/deploy-web/src/components/new-deployment/NewDeploymentPage/createServerSideProps.ts (1)

21-23: Guard for missing inputs looks good.
Prevents unnecessary lookups when neither templateId nor repoUrl is present.

apps/deploy-web/src/services/app-di-container/browser-di-container.ts (1)

31-36: LGTM: GitHubService options wiring looks correct.

Nice alignment with the new constructor signature and public config wiring.

apps/deploy-web/src/services/remote-deploy/github-http.service.ts (4)

18-41: Solid encapsulation with private clients + options.

Constructor/fields are clean and match the intended DI usage.


43-45: LGTM: direct app installation redirect.

Simple and aligned with the new installation URL flow.


64-124: Nice: installations-based pagination with dedupe.

The installations flow with Promise.allSettled + Map dedup reads clean and resilient.


126-164: LGTM: API calls consistently use the private clients.

Consistent use of #githubApiService and #internalApiService keeps the surface tidy.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Also fixes:
- no template loading during the deploy button flow
- infinite state loop on private repo selection

refs #2509, #2511
@ygrishajev ygrishajev merged commit 4b7e316 into main Jan 16, 2026
63 of 65 checks passed
@ygrishajev ygrishajev deleted the fix/deployment branch January 16, 2026 10:51
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

Comments