Skip to content
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

WIP: git sync #375

Open
wants to merge 61 commits into
base: main
Choose a base branch
from
Open

WIP: git sync #375

wants to merge 61 commits into from

Conversation

Felipe-gsilva
Copy link
Member

@Felipe-gsilva Felipe-gsilva commented Dec 19, 2024

fixes #257 #372 #366

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced OAuth sign-in functionality.
    • Added webhook handling capability with a new /webhook endpoint.
    • Enhanced GitHub API integration with new functions for file management.
    • New function to retrieve organizations by their slug.
    • Added git_install_id field to org and customer tables for improved tracking.
    • New optional fields in schemas for git_install_id, git_repo, and sha.
    • New functions for user retrieval by username and email.
    • Added support for GitHub integration in mock management.
    • Introduced new functions for creating and managing Git blobs and commits.
    • New functions for inspecting and updating mocks with SHA values.
    • Expanded database schema to include new columns for Git integration.
    • Added functionality to handle Git synchronization for organizations and users.
    • New functions for editing organizations and users with Git integration.
    • New functions for managing GitHub installation IDs and organization names.
    • Introduced a new settings-modal for user settings management.
    • New functions for handling GitHub webhook signatures and processing events.
    • New functions for logging and managing GitHub user and organization data.
    • New functions for creating and managing GitHub clients and commits.
    • New functions for retrieving organizations by their Git organization name.
    • New functions for managing GitHub user and organization data.
    • Added new dependencies for improved functionality.
  • Bug Fixes

    • Updated error handling in email sign-in process.
  • Improvements

    • Enhanced styling and structure of various components for consistency.
    • Refined CSS styles for better visual feedback.
    • Updated Tailwind CSS color definitions for improved design consistency.
    • Expanded input handling in existing functions to accommodate new data fields.
    • Improved logging context construction for clarity.
  • Refactor

    • Standardized attribute naming from :class-name to :class across components.
    • Streamlined component structure and imports for clarity.
    • Improved code readability through consistent formatting and indentation.
    • Modified context handling in logging statements for better clarity.
  • Chores

    • Removed unnecessary version declarations in configuration files.
    • Adjusted database schema for improved data handling.

Copy link

coderabbitai bot commented Dec 19, 2024

Walkthrough

This pull request introduces several significant changes across the Moclojer project, focusing on enhancing authentication, webhook handling, and preparing infrastructure for Git repository synchronization. The modifications span multiple components, including dependencies, configuration files, frontend components, and backend API interceptors. The changes lay the groundwork for implementing Git repository synchronization for paid plans, with a particular emphasis on GitHub integration.

Changes

File Change Summary
deps.edn Added dependencies: org.clojure/tools.deps, com.moclojer/mockingbird, dev.nubank/clj-github, org.clojure/data.json, nubank/clj-github-app
docker/docker-compose.yml Removed version declaration "3.7"
package.json Updated puppeteer package from ^20.7.2 to ^23.4.0
resources/back/config.edn Added new configuration for :git-sync with keys for GitHub integration
resources/front/index.src.html Updated favicon paths to ./images/favicon-moclojer.png
shadow-cljs.edn Added build hook for CSS processing and updated OAuth redirect handling
src/back/api/interceptors/verify_webhook.clj New file for GitHub webhook signature verification
src/back/api/ports/http_in.clj Added webhook payload handler for GitHub events
src/back/api/routes.clj Introduced new /webhook route with signature verification
src/back/api/controllers/mocks.clj Enhanced mock handling with GitHub integration functions
src/back/api/controllers/user.clj Added user retrieval functions by username and email
resources/back/migrations/20250107133701-install-id.up.sql Added git_install_id column to org and customer tables
resources/back/migrations/20250107133701-install-id.down.sql Removed git_install_id column from org and customer tables

Assessment against linked issues

Objective Addressed Explanation
Webhook Trigger Support [#257] New webhook verification and handling infrastructure implemented
GitHub Integration Added GitHub-related dependencies and webhook interceptor
Mock Sync Mechanism Basic infrastructure for syncing mocks with Git repository established

Poem

🐰 A Rabbit's Webhook Ballad 🌐
In GitHub's vast and starry night,
Moclojer's webhooks take their flight
Signatures checked with gentle care
Syncing mocks beyond compare
Code flows like a digital stream! 🚀


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Felipe-gsilva Felipe-gsilva self-assigned this Dec 19, 2024
@Felipe-gsilva Felipe-gsilva added :app :back :enhancement New feature or request labels Dec 19, 2024
Copy link

@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: 5

♻️ Duplicate comments (2)
src/front/app/dashboard/events.cljs (1)

268-279: ⚠️ Potential issue

Multiple issues in username update handler.

  1. Incorrect event registration (same as previous review).
  2. Debug logging in production code.
  3. Missing error handling.
  4. Incorrect URL construction.

Apply this diff to fix the issues:

-(refx/reg-event-db
+(refx/reg-event-fx
  :app.dashboard/set-new-username
- (fn [{{:keys [current-user]} :db} [_ username-to-save]]
-   (js/console.log username-to-save current-user)
-   (let [access-token (:access-token current-user)
-         user-id (:user_id (:user current-user))]
+ (fn [{db :db} [_ username-to-save]]
+   (let [access-token (get-in db [:current-user :access-token])
+         user-id (get-in db [:current-user :user :user_id])]
      {:http {:url (str "user/" user-id)
              :method :post
              :headers {"authorization" (str "Bearer " access-token)}
              :body {:username username-to-save}
-             :on-success []
-             :on-failure []}})))
+             :on-success [:app.dashboard/set-new-username-success]
+             :on-failure [:app.dashboard/set-new-username-failure]}})))

Additional handlers needed:

(refx/reg-event-fx
 :app.dashboard/set-new-username-success
 (fn [{db :db} _]
   {:notification {:type :info
                  :content "Username updated successfully!"}
    :dispatch [:app.dashboard/toggle-settings]}))

(refx/reg-event-fx
 :app.dashboard/set-new-username-failure
 (fn [{db :db} _]
   {:notification {:type :error
                  :content "Failed to update username."}}))
src/front/app/dashboard/editor.cljs (1)

96-105: 🛠️ Refactor suggestion

Fix push button logic and improve UX.

The button implementation needs improvements for better user experience and error handling.

Apply this diff to enhance the implementation:

 (defnc push-button [{:keys [mock]}]
-  (let [mock-valid? (refx/use-sub [:app.dashboard/mock-valid?])]
+  (let [mock-valid? (refx/use-sub [:app.dashboard/mock-valid?])
+        loading? (refx/use-sub [:app.dashboard/loading-push-mock])
+        error? (refx/use-sub [:app.dashboard/push-error])]
     (d/button
      {:class-name (str "px-3 py-2 bg-gray-500 rounded-lg flex justify-center items-center btn-add space-x-2 "
-                       (when-not mock-valid? " opacity-50 cursor-not-allowed"))
-      :on-click #(when mock-valid?
+                       (when (or (not mock-valid?) loading?) " opacity-50 cursor-not-allowed"))
+      :disabled (or (not mock-valid?) loading?)
+      :on-click #(when (and mock-valid? (not loading?))
                    (refx/dispatch-sync [:app.dashboard/push-mock mock])
                    (refx/dispatch-sync [:app.dashboard/reset-mock-pub-stts (:id mock)]))}
-     (d/div {:class-name "text-white text-xs font-bold leading-[18px]"} " push to origin")
-     ($ svg/save))))
+     (d/div {:class-name (str "text-white text-xs font-bold leading-[18px]"
+                             (when error? " text-red-200"))}
+            (cond
+              loading? "pushing..."
+              error? "push failed"
+              :else "push to origin"))
+     (cond
+       loading? ($ svg/spinner)
+       error? ($ svg/error)
+       :else ($ svg/save)))))
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 35ce360 and 603916e.

📒 Files selected for processing (4)
  • src/back/api/controllers/user.clj (1 hunks)
  • src/dev/shadow/hooks.clj (1 hunks)
  • src/front/app/dashboard/editor.cljs (1 hunks)
  • src/front/app/dashboard/events.cljs (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: WIP
🔇 Additional comments (7)
src/back/api/controllers/user.clj (4)

41-46: Use kebab-case for variable and keyword names.
Using git-username instead of git_username better aligns with Clojure conventions.


48-57: Looks good.
The function's error handling and logging are consistent with typical patterns in the codebase.


59-68: Consider adding valid email format checks for early failure.
This prevents invalid email strings from reaching the database and failing later.


70-81: Enrich the logging context with the install-id.
Including all key fields in the logging context facilitates easier debugging and traceability.

src/front/app/dashboard/events.cljs (3)

24-25: LGTM! Clean formatting changes.

The formatting changes improve readability while preserving the existing logic.


27-33: LGTM! Well-structured settings toggle handler.

The implementation follows the established pattern and correctly handles the db state toggle.


281-297: Clean up debug statements and improve code structure.

The handler contains unnecessary debug statements and can be simplified.

Apply this diff to clean up the code:

 (refx/reg-event-fx
  :app.dashboard/push-mock
  (fn [{db :db} [_ mock]]
-   (let [current-user (:current-user db)]
-     (prn db)
-     (prn mock)
-     ;; mock is already at source its sha is not nil
+   (let [access-token (get-in db [:current-user :access-token])]
      {:http  {:url "/mocks"
               :method :put
-              :headers {"authorization" (str "Bearer " (:access-token (-> db :current-user)))}
+              :headers {"authorization" (str "Bearer " access-token)}
               :body {:id (:id mock)
                      :content (:content mock)
                      :sha (or (:sha mock) "")
                      :git-repo (or (:git-repo mock) "")}
               :on-success [:app.dashboard/save-mock-success]
               :on-failure [:app.dashboard/save-mock-failed]}
       :db (assoc db :loading-edit-mock true)})))

src/dev/shadow/hooks.clj Show resolved Hide resolved
src/back/api/controllers/user.clj Show resolved Hide resolved
src/back/api/controllers/user.clj Outdated Show resolved Hide resolved
src/front/app/dashboard/editor.cljs Outdated Show resolved Hide resolved
src/front/app/dashboard/editor.cljs Show resolved Hide resolved
@Felipe-gsilva
Copy link
Member Author

@coderabbitai can you resolve all the outdated conversations, without commiting any changes, just resolve the chat?

Copy link

coderabbitai bot commented Jan 30, 2025

@Felipe-gsilva I'll resolve all outdated conversations in this PR.

✅ Actions performed

Comments resolved.

Copy link

@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: 15

♻️ Duplicate comments (7)
src/back/api/controllers/user.clj (2)

24-33: 🧹 Nitpick (assertive)

Add docstring to clarify the new arity.

The function now supports an optional install-id parameter but lacks documentation explaining its purpose and usage.


41-68: 🛠️ Refactor suggestion

Use kebab-case consistently.

The functions use snake_case for parameters and keywords (e.g., git_username, :git_username) which is inconsistent with Clojure conventions.

src/front/app/dashboard/events.cljs (1)

310-334: ⚠️ Potential issue

Remove debug prints and fix security concerns in push-mock handler.

The handler contains debug printing and sends unnecessary user data in the request.

src/back/api/controllers/sync.clj (4)

10-13: ⚠️ Potential issue

Correct the typo in the commit message.

There's a typo in the commit message: "Auto genereted commit" should be "Auto generated commit".

-(str "Auto genereted commit by " author "!!\n"
+(str "Auto generated commit by " author "!!\n"

41-58: 🛠️ Refactor suggestion

Use consistent API URL and remove debugging statement.

The function has two issues:

  1. Uses hardcoded GitHub API URL instead of the passed parameter
  2. Contains debugging statement (inspect)
-(defn create-blob [gh-client install-id owner repo file]
+(defn create-blob [gh-client install-id owner repo file github-api-url]
   (let [response (gh-app/request* gh-client install-id
                                   {:method :post
-                                   :url (inspect (format "%s/repos/%s/%s/git/blobs" "https://api.github.com" owner repo))
+                                   :url (format "%s/repos/%s/%s/git/blobs" github-api-url owner repo)

69-86: 🛠️ Refactor suggestion

Remove debugging statements from tree creation.

The function contains multiple debugging statements that should be removed.

-                                   :body (inspect (json/encode {:base_tree (str base-tree-sha)
+                                   :body (json/encode {:base_tree (str base-tree-sha)
...
-      (let [content (inspect (-> response
+      (let [content (-> response

200-235: ⚠️ Potential issue

Remove commented code containing sensitive information.

The commented section contains sensitive information such as:

  • Private keys
  • Installation IDs
  • Personal email addresses

This code should be removed to prevent accidental exposure of sensitive data.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 603916e and ec8b2e8.

📒 Files selected for processing (13)
  • src/back/api/adapters/customers.clj (1 hunks)
  • src/back/api/adapters/mocks.clj (2 hunks)
  • src/back/api/controllers/mocks.clj (2 hunks)
  • src/back/api/controllers/sync.clj (1 hunks)
  • src/back/api/controllers/user.clj (2 hunks)
  • src/back/api/logic/mocks.clj (3 hunks)
  • src/back/api/ports/http_in.clj (7 hunks)
  • src/back/api/routes.clj (5 hunks)
  • src/front/app/components/svg.cljs (9 hunks)
  • src/front/app/dashboard/base.cljs (3 hunks)
  • src/front/app/dashboard/editor.cljs (5 hunks)
  • src/front/app/dashboard/events.cljs (3 hunks)
  • src/front/app/dashboard/subs.cljs (3 hunks)
🧰 Additional context used
📓 Learnings (1)
src/back/api/ports/http_in.clj (1)
Learnt from: Felipe-gsilva
PR: moclojer/moclojer-app#375
File: src/back/api/ports/http_in.clj:218-277
Timestamp: 2025-01-24T13:37:14.472Z
Learning: The webhook endpoint in moclojer-app verifies GitHub webhook signatures using the verify-webhook-signature interceptor from back.api.interceptors.verify-webhook, which uses clj-github-app.webhook-signature library.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: WIP
🔇 Additional comments (34)
src/front/app/dashboard/base.cljs (6)

2-15: Imports look consistent and well-organized.
No issues found with the new or updated :require statements.


98-98: Replacing defnc with defn may cause issues in component definitions.
This was previously noted.


150-150: Possible typo in class name 'lm:col-span-3'.
Previously noted.


161-161: :on-load event handler on input element may not work as intended.
Previously noted.


176-177: Use :class instead of :class-name for DOM elements in Helix.
Previously noted.


321-334: Index component usage looks good.
No issues found. The defnc macro ensures proper hook usage if any are added later, and the layout is cohesive.

src/back/api/logic/mocks.clj (5)

2-5: Namespace import structure looks good.
The multi-line :require form is clear and makes each import easily identifiable.


59-59: Ensure consistent handling of new keys.
Adding :git-repo and :sha to the selected keys is fine. However, confirm if these new fields may sometimes be nil or empty strings and if further checks or validations are needed.


92-93: Consider validating SHA format.
To avoid storing invalid or non-40-character hex strings in :mock/sha, you could verify the input.

(defn update-sha [mock sha]
-  (assoc mock :mock/sha sha))
+  (when (re-matches #"^[0-9a-f]{40}$" sha)
+    (assoc mock :mock/sha sha)))

95-96: Consider validating repository URL.
If git-repo is intended to be a valid URL, you could add a basic check or rely on the calling code or schema validation.


98-99: Consider adding basic content checks.
If content is expected to be in a valid format or within certain size limits, you might add at least minimal validation to prevent issues downstream.

src/back/api/ports/http_in.clj (7)

2-14: Namespace imports are well-organized.
The clearly listed dependencies make the code easier to maintain.


25-30: Check for nil install-id usage.
Ensure that controllers.user/edit-user! handles nil values for install-id gracefully and does not overwrite or remove existing data unintentionally.


65-66: Avoid debug-only functions in production code.
inspect appears to be for debugging. Remove it or guard it behind a debug flag to maintain a cleaner production codebase.


106-106: Validate user existence.
Ensure handler-get-mocks handles cases where get-user-by-id returns nil, especially if the user is not found or session data is invalid.


236-239: Use path functions for more robust filtering.
Splitting on "/" works, but using java.io.File or a dedicated path library helps avoid corner cases (Linux vs. Windows paths, etc.).


244-348: Refactor large webhook handler.
handler-webhook is quite long and handles multiple logical flows. Splitting into dedicated functions (push event flow, installation event handling, etc.) would aid readability and testing.


240-243: ⚠️ Potential issue

Avoid duplicative inspect definitions.
You appear to have two implementations of inspect. Consolidate them into one or remove if unneeded.

- (defn inspect [a] (prn "inspeciona " a) a)
- (defn inspect [a]
-   (prn "inspecionando " a (newline))
-   a)
+ ;; Remove or guard behind a debug flag

Likely invalid or redundant comment.

src/back/api/adapters/customers.clj (1)

6-14: Prevent “nil” as string and validate ID fields.
Using (str org_id) might produce "nil". A safer approach to avoid stringifying nil is (when org_id (str org_id)). Similarly, add checks if git_install_id must be positive or if git_username must be non-empty:

(-> {:uuid (str uuid)
     :email email
     :external-id external_uuid}
-    (assoc-if :org-id (str org_id))
+    (assoc-if :org-id (when org_id (str org_id)))
     (assoc-if :username username)
     (assoc-if :git-install-id (when (pos? git_install_id) git_install_id))
     (assoc-if :git-username git_username))
src/front/app/dashboard/subs.cljs (3)

53-56: LGTM!

The subscription follows the standard pattern and correctly retrieves the settings modal state.


95-98: LGTM!

The subscription follows the standard pattern and correctly retrieves the Git repository requirement state.


100-103: LGTM!

The subscription follows the standard pattern and correctly retrieves the repositories list.

src/back/api/controllers/mocks.clj (2)

13-15: LGTM! Performance improvement.

Replacing merge with assoc for updating the logging context is a good optimization, as assoc is more efficient than merge for adding key-value pairs.


65-67: LGTM! Performance improvement.

Replacing merge with assoc for updating the logging context is a good optimization, as assoc is more efficient than merge for adding key-value pairs.

src/back/api/routes.clj (2)

157-158: LGTM! Consistent error handling.

Adding the error-handler-interceptor ensures consistent error handling across routes.


197-202: ⚠️ Potential issue

Reorder interceptors to verify webhook signature before parsing the request body.

The verify-webhook-signature interceptor should be placed before the parameters/parameters-interceptor to ensure the raw request body is available for signature verification. Parsing the body before verification can compromise security.

Apply this diff to reorder the interceptors:

-            :interceptors [(parameters/parameters-interceptor)
-                           (verify-webhook-signature)]
+            :interceptors [(verify-webhook-signature)
+                           (parameters/parameters-interceptor)]
⛔ Skipped due to learnings
Learnt from: Felipe-gsilva
PR: moclojer/moclojer-app#375
File: src/back/api/ports/http_in.clj:218-277
Timestamp: 2025-01-24T13:37:14.472Z
Learning: The webhook endpoint in moclojer-app verifies GitHub webhook signatures using the verify-webhook-signature interceptor from back.api.interceptors.verify-webhook, which uses clj-github-app.webhook-signature library.
src/front/app/dashboard/editor.cljs (4)

Line range hint 75-82: LGTM! Enhanced user interaction feedback.

Adding transition effects for hover states improves the user experience by providing visual feedback.


Line range hint 85-95: LGTM! Enhanced user interaction feedback.

Adding transition effects for hover states improves the user experience by providing visual feedback.


97-103: LGTM! Well-designed component.

The component follows the design system, includes transition effects, and correctly dispatches the remove action.


105-115: 🧹 Nitpick (assertive)

Enhance Git operations UX.

The component could be improved in several ways:

  1. Add loading state handling
  2. Use a more appropriate icon for the push action
  3. Add tooltips for better user guidance

Apply this diff to enhance the component:

-(defnc push-button [{:keys [mock-id]}]
-  (let [mock-valid? (refx/use-sub [:app.dashboard/mock-valid?])]
+(defnc push-button [{:keys [mock-id]}]
+  (let [mock-valid? (refx/use-sub [:app.dashboard/mock-valid?])
+        loading? (refx/use-sub [:app.dashboard/loading-push-mock])]
     (d/button
      {:class-name (str "px-3 py-2 bg-gray-500 rounded-lg flex justify-center items-center btn-add space-x-2 "
                        "hover:bg-gray-600 transition-all duration-75 "
-                       (when-not mock-valid? " opacity-50 cursor-not-allowed"))
+                       (when (or (not mock-valid?) loading?) " opacity-50 cursor-not-allowed"))
+      :title "Push changes to Git repository"
+      :disabled (or (not mock-valid?) loading?)
       :on-click #(when mock-valid?
                    (refx/dispatch-sync [:app.dashboard/push-mock mock-id])
                    (refx/dispatch-sync [:app.dashboard/reset-mock-pub-stts mock-id]))}
-     (d/div {:class-name "text-white text-xs font-bold leading-[18px]"} " push to origin")
-     ($ svg/save))))
+     (d/div {:class-name "text-white text-xs font-bold leading-[18px]"}
+            (if loading? "pushing..." " push to origin"))
+     (if loading?
+       ($ svg/spinner)
+       ($ svg/git-push)))))

Likely invalid or redundant comment.

src/back/api/adapters/mocks.clj (1)

Line range hint 5-17: LGTM! Clean addition of git sync fields.

The changes correctly add support for git sync related fields (sha and git_repo) while maintaining the existing pattern of using assoc-if for optional fields.

src/front/app/dashboard/events.cljs (1)

268-279: ⚠️ Potential issue

Fix incorrect event handler registration and debug logging.

The handler:

  1. Uses reg-event-db but returns effects (:http)
  2. Contains debug logging that should be removed
  3. Has incorrect URL construction

Apply this diff to fix the issues:

-(refx/reg-event-db
+(refx/reg-event-fx
  :app.dashboard/set-new-username
- (fn [{{:keys [current-user]} :db} [_ username-to-save]]
-   (js/console.log username-to-save current-user)
+ (fn [{db :db} [_ username-to-save]]
    (let [access-token (get-in db [:current-user :access-token])
          user-id (get-in db [:current-user :user :user_id])]
      {:http {:url (str "/user/" user-id)
              :method :post
              :headers {"authorization" (str "Bearer " access-token)}
              :body {:username username-to-save}
-             :on-success []
-             :on-failure []}})))
+             :on-success [:app.dashboard/toggle-settings]
+             :on-failure [:app.dashboard/save-mock-failed]}})))

Likely invalid or redundant comment.

src/front/app/components/svg.cljs (1)

Line range hint 34-334: LGTM! Clean SVG component updates.

The changes:

  1. Consistently use the class attribute instead of class-name
  2. Add new SVG components (github, docs) following the established patterns
  3. Maintain consistent formatting and structure
src/back/api/controllers/sync.clj (1)

108-159: LGTM! Well-implemented reference and repository operations.

The implementation includes:

  • Proper error handling
  • Consistent authentication
  • Clear response processing

src/front/app/dashboard/base.cljs Outdated Show resolved Hide resolved
Comment on lines +292 to +319
(defn update-repo-modal []
(let [require-git-repo? (refx/use-sub [:app.dashboard/require-git-repo?])
repos (refx/use-sub [:app.dashboard/repos])]
($ modal
{:title "Add a repo to your mock"
:open? require-git-repo?
:on-close #(refx/dispatch-sync [:app.dashboard/toggle-git-repo-modal require-git-repo?])
:children
(d/div
{:class "w-screen md:w-[600px] p-6 gap-4 z-10"}
(d/div
{:class "w-[calc(100%)]"}
(d/ul
{:class "space-y-2"}
(for [repo repos]
(d/li
{:key (:full_name repo)
:class "flex items-center p-3 border rounded-lg hover:bg-gray-50 cursor-pointer"
:on-click #(do
(close-modal!)
(refx/dispatch-sync [:app.dashboard/delete-mock mock]))}
(d/p
{:class "text-white"}
"Yes, I want to delete it"))
($ button
{:class-name "px-4 py-2 border-2 border-gray-400 rounded-lg hover:bg-gray-200"}
(d/p
{:class-name "text-gray-800 text-sm font-medium"
:on-click #(close-modal!)}
"No, cancel"))))})))
(refx/dispatch-sync [:app.dashboard/update-git-repo (:html_url repo)])
(refx/dispatch-sync [:app.dashboard/toggle-git-repo-modal require-git-repo?]))}
(d/img
{:src (get-in repo [:owner :avatar_url])
:alt (str (get-in repo [:owner :login]) "'s avatar")
:class "w-8 h-8 rounded-full mr-3"})
(d/span
{:class "flex-1"}
(:full_name repo)))))))})))
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Add a fallback message for empty repo lists.
If repos is empty, the modal remains blank. Consider displaying a “No repositories found” message for a better user experience.

Comment on lines 58 to 96
(d/div {:class "col-span-6 row-span-7 h-64 rounded-md bg-gray-50 space-y-4 p-4"}
(cond
(= (:view setting) "user")
(d/div
(d/form {:class "flex flex-col justify-between w-full items-start"
:on-submit (fn [e]
(.preventDefault e)
(when (and (not-empty username-to-save) available?)
(refx/dispatch [:app.dashboard/set-new-username username-to-save])))}
(d/div {:class "w-[calc(100%)]"}
($ input {:label "Edit Username"
:on-change (fn [e]
(.preventDefault e)
(refx/dispatch-sync [:app.auth/username-available? (.. e -target -value)]))
:placeholder username})
(d/p {:class "text-sm select-none "}
(str "<" username ">.moclojer.com")))
(d/div {:class (str "w-[calc(20%)] flex justify-center items-center text-white rounded-md "
"my-2 p-2 ")}
($ button {:class (when (not available?) "cursor-not-allowed ")
:theme :mockingbird
:padding :sm
:type :submit}
"Update"))))

(= (:view setting) "orgs")
(do
(d/div
(d/p "Work in Progress")
(if (> (count user-orgs) 1)
(doseq [org user-orgs]
(d/p org)))
(d/p user-orgs)))

(= (:view setting) "mocks")
(d/div
(d/p "Work in Progress"))
:else
(set-setting assoc :view "user")))))})))
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

doseq inside the organizations view prevents rendering of org elements.
Within the "orgs" view, line 88 uses (doseq [org user-orgs] (d/p org)), which does not produce a sequence of DOM elements. To actually render the organizations, replace doseq with a mapping function (e.g., map or mapv).

- (doseq [org user-orgs]
-   (d/p org))
+ (mapv (fn [org]
+         (d/p org))
+       user-orgs)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(d/div {:class "col-span-6 row-span-7 h-64 rounded-md bg-gray-50 space-y-4 p-4"}
(cond
(= (:view setting) "user")
(d/div
(d/form {:class "flex flex-col justify-between w-full items-start"
:on-submit (fn [e]
(.preventDefault e)
(when (and (not-empty username-to-save) available?)
(refx/dispatch [:app.dashboard/set-new-username username-to-save])))}
(d/div {:class "w-[calc(100%)]"}
($ input {:label "Edit Username"
:on-change (fn [e]
(.preventDefault e)
(refx/dispatch-sync [:app.auth/username-available? (.. e -target -value)]))
:placeholder username})
(d/p {:class "text-sm select-none "}
(str "<" username ">.moclojer.com")))
(d/div {:class (str "w-[calc(20%)] flex justify-center items-center text-white rounded-md "
"my-2 p-2 ")}
($ button {:class (when (not available?) "cursor-not-allowed ")
:theme :mockingbird
:padding :sm
:type :submit}
"Update"))))
(= (:view setting) "orgs")
(do
(d/div
(d/p "Work in Progress")
(if (> (count user-orgs) 1)
(doseq [org user-orgs]
(d/p org)))
(d/p user-orgs)))
(= (:view setting) "mocks")
(d/div
(d/p "Work in Progress"))
:else
(set-setting assoc :view "user")))))})))
(d/div {:class "col-span-6 row-span-7 h-64 rounded-md bg-gray-50 space-y-4 p-4"}
(cond
(= (:view setting) "user")
(d/div
(d/form {:class "flex flex-col justify-between w-full items-start"
:on-submit (fn [e]
(.preventDefault e)
(when (and (not-empty username-to-save) available?)
(refx/dispatch [:app.dashboard/set-new-username username-to-save])))}
(d/div {:class "w-[calc(100%)]"}
($ input {:label "Edit Username"
:on-change (fn [e]
(.preventDefault e)
(refx/dispatch-sync [:app.auth/username-available? (.. e -target -value)]))
:placeholder username})
(d/p {:class "text-sm select-none "}
(str "<" username ">.moclojer.com")))
(d/div {:class (str "w-[calc(20%)] flex justify-center items-center text-white rounded-md "
"my-2 p-2 ")}
($ button {:class (when (not available?) "cursor-not-allowed ")
:theme :mockingbird
:padding :sm
:type :submit}
"Update"))))
(= (:view setting) "orgs")
(do
(d/div
(d/p "Work in Progress")
(if (> (count user-orgs) 1)
(mapv (fn [org]
(d/p org))
user-orgs))
(d/p user-orgs)))
(= (:view setting) "mocks")
(d/div
(d/p "Work in Progress"))
:else
(set-setting assoc :view "user")))))})))

src/back/api/ports/http_in.clj Show resolved Hide resolved
src/back/api/ports/http_in.clj Outdated Show resolved Hide resolved
Comment on lines +70 to +81
(defn enable-sync
"Updates user install id field"
[install-id user-id {:keys [database]} ctx]
(logs/log :info "enabling git sync"
:ctx (assoc ctx :user user-id))
(or (-> {:customer/uuid (parse-uuid (str user-id))}
(logic.customers/update-install-id install-id)
(db.customers/update! database ctx)
(adapter.customers/->wire))
(throw (ex-info "Could not enable git sync"
{:status-code 412
:value (assoc ctx :user user-id)}))))
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Enhance error handling in enable-sync.

The function:

  1. Uses string concatenation with str before parse-uuid which is redundant if user-id is already a string
  2. Doesn't specify the error cause in the exception
  3. Could benefit from validating the install-id format

Apply this diff to improve the implementation:

 (defn enable-sync
   "Updates user install id field"
   [install-id user-id {:keys [database]} ctx]
+  (when-not (re-matches #"^\d+$" install-id)
+    (throw (ex-info "Invalid GitHub installation ID format"
+                    {:status-code 400
+                     :cause :invalid-install-id
+                     :value (assoc ctx :install-id install-id)})))
   (logs/log :info "enabling git sync"
-            :ctx (assoc ctx :user user-id))
+            :ctx (assoc ctx :user-id user-id :install-id install-id))
-  (or  (-> {:customer/uuid (parse-uuid (str user-id))}
+  (or  (-> {:customer/uuid (parse-uuid user-id)}
            (logic.customers/update-install-id install-id)
            (db.customers/update! database ctx)
            (adapter.customers/->wire))
        (throw (ex-info "Could not enable git sync"
                        {:status-code 412
+                        :cause :git-sync-failed
                         :value (assoc ctx :user user-id)}))))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(defn enable-sync
"Updates user install id field"
[install-id user-id {:keys [database]} ctx]
(logs/log :info "enabling git sync"
:ctx (assoc ctx :user user-id))
(or (-> {:customer/uuid (parse-uuid (str user-id))}
(logic.customers/update-install-id install-id)
(db.customers/update! database ctx)
(adapter.customers/->wire))
(throw (ex-info "Could not enable git sync"
{:status-code 412
:value (assoc ctx :user user-id)}))))
(defn enable-sync
"Updates user install id field"
[install-id user-id {:keys [database]} ctx]
(when-not (re-matches #"^\d+$" install-id)
(throw (ex-info "Invalid GitHub installation ID format"
{:status-code 400
:cause :invalid-install-id
:value (assoc ctx :install-id install-id)})))
(logs/log :info "enabling git sync"
:ctx (assoc ctx :user-id user-id :install-id install-id))
(or (-> {:customer/uuid (parse-uuid user-id)}
(logic.customers/update-install-id install-id)
(db.customers/update! database ctx)
(adapter.customers/->wire))
(throw (ex-info "Could not enable git sync"
{:status-code 412
:cause :git-sync-failed
:value (assoc ctx :user user-id)}))))

Comment on lines +41 to +46
(defn get-by-git-username
[git_username {:keys [database]} ctx]
(logs/log :info "retrieving user by its git_username"
:ctx (assoc ctx :git_username git_username))
(-> (db.customers/get-by-git-username git_username database ctx)
(adapter.customers/->wire)))
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Function may throw NPE when user not found.

The function doesn't handle the case where no user is found with the given git username, unlike similar functions that follow.

Apply this diff to add proper error handling:

 (defn get-by-git-username
   [git_username {:keys [database]} ctx]
   (logs/log :info "retrieving user by its git_username"
             :ctx (assoc ctx :git_username git_username))
-  (-> (db.customers/get-by-git-username git_username database ctx)
-      (adapter.customers/->wire)))
+  (or (-> (db.customers/get-by-git-username git_username database ctx)
+          (adapter.customers/->wire))
+      (throw (ex-info "No user with given git username was found"
+                      {:status-code 412
+                       :cause :invalid-git-username
+                       :value (assoc ctx :git-username git_username)}))))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(defn get-by-git-username
[git_username {:keys [database]} ctx]
(logs/log :info "retrieving user by its git_username"
:ctx (assoc ctx :git_username git_username))
(-> (db.customers/get-by-git-username git_username database ctx)
(adapter.customers/->wire)))
(defn get-by-git-username
[git_username {:keys [database]} ctx]
(logs/log :info "retrieving user by its git_username"
:ctx (assoc ctx :git_username git_username))
(or (-> (db.customers/get-by-git-username git_username database ctx)
(adapter.customers/->wire))
(throw (ex-info "No user with given git username was found"
{:status-code 412
:cause :invalid-git-username
:value (assoc ctx :git-username git_username)}))))

src/front/app/dashboard/events.cljs Outdated Show resolved Hide resolved
src/back/api/controllers/sync.clj Outdated Show resolved Hide resolved
src/back/api/controllers/sync.clj Outdated Show resolved Hide resolved
Copy link

@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: 14

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ec8b2e8 and 7f421a6.

📒 Files selected for processing (5)
  • src/back/api/ports/http_in.clj (7 hunks)
  • src/back/api/routes.clj (4 hunks)
  • src/front/app/dashboard/editor.cljs (6 hunks)
  • src/front/app/dashboard/events.cljs (3 hunks)
  • src/front/app/dashboard/subs.cljs (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: WIP
🔇 Additional comments (23)
src/back/api/routes.clj (2)

67-67: LGTM! Good use of schema validation.

The change from a generic map to schemas.wire-in/UserUpdate improves type safety and documentation.


32-38: ⚠️ Potential issue

Reorder interceptors for secure webhook signature verification.

The verify-webhook-signature interceptor should be placed before the parameters/parameters-interceptor to ensure the raw request body is available for signature verification.

Apply this diff to fix the interceptor order:

 {:post {:summary "Handles a webhook"
         :parameters {:body map?}
         ;; TODO check if this can be removed
         :interceptors [(parameters/parameters-interceptor)
-                      (verify-webhook-signature)]
+                      (verify-webhook-signature)]}

Also, please clarify or remove the TODO comment about interceptor removal. The parameters/parameters-interceptor is required to parse the request body into a Clojure map.

✅ Verification successful

Confirmed: Interceptor order must be changed for secure webhook signature verification

The implementation shows that verify-webhook-signature requires access to the raw request body to verify the signature. The current order allows parameters-interceptor to modify the body before signature verification, which would cause verification to fail. The suggested reordering is correct.

  • In src/back/api/routes.clj, reorder interceptors to put verify-webhook-signature first
  • The TODO comment can be safely removed as both interceptors serve distinct, necessary purposes:
    • verify-webhook-signature: Validates request authenticity
    • parameters-interceptor: Parses the request body into Clojure data structures
🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for verify-webhook-signature implementation
echo "=== Searching for verify-webhook-signature implementation ==="
rg -A 10 "verify-webhook-signature" --type clojure

echo -e "\n=== Searching for webhook signature verification tests ==="
rg -A 10 "verify-webhook-signature" --type clojure --glob "*test*"

echo -e "\n=== Searching for parameters-interceptor usage and documentation ==="
rg "parameters-interceptor" --type clojure

Length of output: 2957


Script:

#!/bin/bash
# Search for webhook signature verification implementation
echo "=== Searching for webhook-signature namespace ==="
rg -A 10 "check-payload-signature-256" --type clojure

echo -e "\n=== Looking for parameters interceptor implementation ==="
fd -e clj -e cljc -H parameters

Length of output: 1257

src/back/api/ports/http_in.clj (4)

25-30: LGTM! Function signature matches schema update.

The addition of install-id parameter aligns with the schema changes in routes.clj.


65-65: ⚠️ Potential issue

Remove debug function from production code.

The inspect function uses prn for debugging and should be removed from production code.

Apply this diff:

-(defn inspect [a] (prn "inspeciona " a) a)

Likely invalid or redundant comment.


237-240: 🧹 Nitpick (assertive)

Use path manipulation functions for robustness.

String operations for path manipulation can be fragile. Consider using proper path manipulation functions.

Apply this diff:

-(defn- filter-mocks [files]
-  (into [] (filter #(and (= (last (str/split % #"/")) "moclojer.yml")
-                        (str/includes? % "mocks/"))
-                  files)))
+(defn- filter-mocks [files]
+  (let [mock-filename "moclojer.yml"
+        mock-dir "mocks"]
+    (into [] (filter #(let [path (java.nio.file.Paths/get % (into-array String []))]
+                       (and (= (.getFileName path) mock-filename)
+                            (.startsWith path mock-dir)))
+                    files))))

Likely invalid or redundant comment.


68-101: ⚠️ Potential issue

Improve path manipulation and error handling.

Several issues need attention:

  1. String splitting for git path is fragile
  2. Missing error handling for path manipulation
  3. Unaddressed TODO comment

Apply these improvements:

-(let [owner (inspect (-> (str/split git-path  #"/")
-                        (as-> [e] (take-last 2 e))
-                        (first)))]
+(let [path-parts (str/split git-path #"/")
+     owner (try
+             (-> path-parts
+                 reverse
+                 second)
+             (catch Exception e
+               (throw (ex-info "Invalid git repository path"
+                             {:status-code 400
+                              :cause :invalid-git-path
+                              :value git-path}))))]

Also, please clarify the TODO comment about org/user check or implement the necessary logic.

✅ Verification successful

Confirmed: Path handling needs improvement and error handling standardization

The review suggestions are valid and align with existing patterns in the codebase. The proposed changes should:

  1. Follow the established error handling pattern:
(throw (ex-info "Invalid git repository path"
                {:status-code 400
                 :cause :invalid-git-path
                 :value git-path}))
  1. The TODO comment about org/user check is valid as the codebase handles both types differently in controllers. This distinction needs to be implemented.

  2. Path manipulation should be standardized across the codebase, as currently there are inconsistent approaches.

🏁 Scripts executed

The following scripts were executed for the analysis:

Error: No shell scripts found


Script:

#!/bin/bash
# Search for git path handling patterns
echo "=== Git Path Handling Patterns ==="
rg -A 2 "str/split.*#\"/\"" 

echo -e "\n=== Error Handling Patterns ==="
# Search for similar error handling patterns with ex-info
rg "throw.*ex-info.*:invalid-git" 

echo -e "\n=== Org/User Check Patterns ==="
# Search for org/user check implementations
rg -B 2 -A 2 "check.*org.*user|org.*user.*check"

Length of output: 2023


Script:

#!/bin/bash
# Search for general error handling patterns with ex-info
echo "=== Error Handling Patterns ==="
rg "throw.*ex-info.*:status-code 400" -A 2

echo -e "\n=== Organization vs User Implementation ==="
# Search for organization/user related code in controllers
rg -l "org.*user|organization.*user" src/back/controllers/

Length of output: 343


Script:

#!/bin/bash
# Find directory structure
echo "=== Directory Structure ==="
fd -t d controllers

echo -e "\n=== Error Handling Patterns ==="
# Broader search for error handling
rg "throw.*ex-info" -A 2

echo -e "\n=== Controller Files ==="
# Find controller files
fd -t f -e clj ".*controller.*"

Length of output: 6839

src/front/app/dashboard/events.cljs (5)

2-3: No issues spotted in the require statement.


24-25: Toggle logic looks good.


268-280: Incorrect usage of reg-event-db; should use reg-event-fx.
This handler returns HTTP effects but is using reg-event-db. This is a duplicate of a past comment regarding mixing effects and reg-event-db. Ensure you return a :db key alongside your effects or switch to reg-event-fx.

-(refx/reg-event-db
+(refx/reg-event-fx
 :app.dashboard/set-new-username
 (fn [{db :db} [_ username-to-save]]
   (js/console.log username-to-save current-user)
   (let [access-token (:access-token current-user)
         user-id (:user_id (:user current-user))]
     {:db   db
      :http {:url (str "user/" user-id)
             :method :post
             :headers {"authorization" (str "Bearer " access-token)}
             :body {:username username-to-save}
             :on-success []
             :on-failure []}})))

300-309: Storing repositories looks good.


286-298: Verify correctness of pushing the mock after clearing :curr-mock-id.
on-success triggers :app.dashboard/push-mock with the old :curr-mock-id, but you set :curr-mock-id to nil in the same effect. This could cause confusion if subsequent handlers rely on that ID. Please confirm it behaves as intended.

src/front/app/dashboard/subs.cljs (5)

2-3: No issues with updated require statement.


53-57: Subscription logic for is-settings-open? is good.


95-99: Subscription to require-git-repo? is straightforward.


100-104: Storing repos in :repositories is fine.


105-108: is-sync-enabled? subscription looks good.

src/front/app/dashboard/editor.cljs (7)

1-2: Namespace configuration is acceptable.


75-75: Styling update is fine.


85-85: File upload button handling is fine.


95-96: No issues with the final part of the file-upload block.


105-116: Push button logic is correctly disabling interaction when invalid.


141-142: Retrieving mock-to-delete and sync-enabled? looks fine.


203-207: Conditional push vs. enable sync is correct.

src/back/api/ports/http_in.clj Outdated Show resolved Hide resolved
src/back/api/ports/http_in.clj Outdated Show resolved Hide resolved
src/back/api/ports/http_in.clj Show resolved Hide resolved
Comment on lines +281 to +285
(refx/reg-event-db
:app.dashboard/toggle-git-repo-modal
(fn [db [_ modal-open?]]
(assoc db :require-git-repo? (not modal-open?))))

Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Confirm naming consistency.
Toggling the git-repo modal inverts :require-git-repo?. Verify that this accurately reflects the desired logic, as the naming can be confusing.

src/front/app/dashboard/events.cljs Outdated Show resolved Hide resolved
src/front/app/dashboard/events.cljs Outdated Show resolved Hide resolved
src/front/app/dashboard/events.cljs Outdated Show resolved Hide resolved
src/front/app/dashboard/events.cljs Outdated Show resolved Hide resolved
src/front/app/dashboard/editor.cljs Outdated Show resolved Hide resolved
src/front/app/dashboard/editor.cljs Outdated Show resolved Hide resolved
Copy link

@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: 25

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7f421a6 and 2d43661.

📒 Files selected for processing (13)
  • src/back/api/controllers/mocks.clj (2 hunks)
  • src/back/api/controllers/sync.clj (1 hunks)
  • src/back/api/ports/http_in.clj (8 hunks)
  • src/back/api/routes.clj (6 hunks)
  • src/back/api/schemas/wire_in.clj (2 hunks)
  • src/back/api/utils.clj (1 hunks)
  • src/front/app/auth/supabase.cljs (3 hunks)
  • src/front/app/auth/views.cljs (2 hunks)
  • src/front/app/components/svg.cljs (9 hunks)
  • src/front/app/dashboard/editor.cljs (7 hunks)
  • src/front/app/dashboard/events.cljs (5 hunks)
  • src/front/app/dashboard/mocks.cljs (4 hunks)
  • src/front/app/dashboard/subs.cljs (3 hunks)
🧰 Additional context used
📓 Learnings (1)
src/back/api/ports/http_in.clj (1)
Learnt from: Felipe-gsilva
PR: moclojer/moclojer-app#375
File: src/back/api/ports/http_in.clj:218-277
Timestamp: 2025-01-24T13:37:14.472Z
Learning: The webhook endpoint in moclojer-app verifies GitHub webhook signatures using the verify-webhook-signature interceptor from back.api.interceptors.verify-webhook, which uses clj-github-app.webhook-signature library.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: WIP
🔇 Additional comments (51)
src/front/app/components/svg.cljs (2)

318-324: Well-structured new components with proper styling!

The new github and docs components follow best practices:

  • Consistent styling with other icons
  • Proper dark mode support
  • Responsive sizing with flex utilities

Also applies to: 326-332


Line range hint 1-334: Overall well-structured SVG components!

The file demonstrates good practices:

  • Consistent component structure
  • Proper accessibility attributes
  • Dark mode support
  • Responsive design considerations
src/front/app/dashboard/subs.cljs (1)

54-58: LGTM! Clean subscription implementations.

The new subscriptions follow re-frame/refx patterns correctly and implement simple database lookups.

Also applies to: 96-100, 101-105, 106-110, 111-115

src/front/app/auth/supabase.cljs (4)

11-12: Add a check for SUPABASE_OAUTH_REDIRECT to prevent undefined redirection issues

The validation check should include SUPABASE_OAUTH_REDIRECT to ensure it's properly set.


39-41: Simplify the construction of options by removing unnecessary clj->js call

The :options key is being converted to a JavaScript object twice.


67-68: Add comprehensive test coverage for authentication flows

While the comment block provides useful examples, proper test coverage is needed.


36-37: Consider expanding supported OAuth providers

The provider validation is currently limited to GitHub only. If there are plans to support additional providers in the future (e.g., GitLab, Bitbucket), consider:

  1. Documenting this limitation
  2. Making the provider list configurable

Run this script to check for other OAuth providers in the codebase:

✅ Verification successful

Provider Validation Matches Current Usage

The search confirms that only "github" is being referenced (e.g., in src/front/app/auth/views.cljs). As no other providers (e.g., GitLab or Bitbucket) are used, the strict provider validation in src/front/app/auth/supabase.cljs is consistent with the current implementation. If additional providers are planned, consider documenting this limitation or making the provider list configurable.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for OAuth provider references
rg -i "provider.*(?:github|gitlab|bitbucket)" --type clojure

Length of output: 213

src/front/app/auth/views.cljs (6)

3-5: Great use of mockingbird UI components.

The imports for button, image, and input appear valid and properly referenced. This integration simplifies the code and increases consistency with pre-built, well-tested components.


11-11: SVG import looks appropriate.

Importing the github component here is clear and consistent, ensuring that the GitHub icon is readily available without repeatedly defining SVG assets in-line.


60-63: Clarify the login method selection logic when email is blank.

Currently, the logic triggers an email-based login whenever :email is present in the state. If the email is an empty string, the user might experience confusion or fail silently. Explicitly checking for non-blank emails can prevent user experience issues.


91-99: Ensure consistent state management when switching to OAuth login.

The on-click handler sets :provider to "github" but does not reset or remove :email. If the user previously entered an email, consider clearing it or updating additional state if needed, to avoid conflicting conditions in the login flow.


145-146: Implement debouncing for username availability checks.

Checking username availability on every keystroke can cause frequent backend calls and potential performance overhead. Consider wrapping the dispatch in a debounce utility to reduce extraneous calls while the user is typing.


160-162: Simplify the :disabled attribute expression.

Replacing the if statement with the direct boolean expression can make the code more concise and readable. For instance:

- :disabled (if (or loading? (not available?))
-             true
-             false)
+ :disabled (or loading? (not available?))
src/back/api/utils.clj (5)

1-3: LGTM!

The namespace declaration and imports are appropriate for the functionality provided by this utility namespace.


5-11: Enhance docstring clarity.

The docstring could be more specific about what constitutes a valid value (truthy vs. falsy in Clojure).


13-18: Add input validation and error handling for decode function.

The function should handle edge cases and malformed input safely, especially important for webhook payloads.


26-31: Optimize validation order and enhance docstring.

The validation checks can be reordered for better performance, and the docstring could be more descriptive.


20-24: ⚠️ Potential issue

Improve input validation for encode function.

While the function attempts to handle non-string inputs with str, it should still include proper validation and error handling.

Apply this diff to improve the implementation:

-(defn encode [content]
-  (let [content-str (str content)
-        bytes (.getBytes content-str "UTF-8")
-        encoder (Base64/getEncoder)]
-    (.encodeToString encoder bytes)))
+(defn encode
+  "Encodes a given value into base64 format after converting it to string"
+  [content]
+  (try
+    (let [content-str (str content)
+          bytes (.getBytes content-str "UTF-8")
+          encoder (Base64/getEncoder)]
+      (.encodeToString encoder bytes))
+    (catch Exception e
+      (throw (ex-info "Failed to encode to base64"
+                     {:type :encode-error
+                      :value content
+                      :cause (.getMessage e)})))))

Likely invalid or redundant comment.

src/front/app/dashboard/editor.cljs (6)

1-18: No immediate concerns with the namespace and imports
All required dependencies appear correctly imported, and the namespace declaration is consistent with the rest of the dashboard code.


31-36: Effectful polling logic verified
The use-effect hook properly starts and stops mock polling based on the id, and the cleanup function is returned correctly.


75-79: Drag-drop appearance looks good
No issues identified in the presentation and structure of the drop zone elements.


107-114: Use standard Tailwind color scale
Tailwind typically expects classes like hover:bg-red-500 rather than hover:bg-red.


237-239: Toolbar and file upload integration
No issues found. The integration of editor-toolbar and file-upload-button is straightforward and appears correct.


240-250: Drag-drop and editor usage
The drag-drop flow is well orchestrated and the editor hooking looks consistent.

src/front/app/dashboard/mocks.cljs (2)

2-12: LGTM! Clean import organization.

The imports are well-organized and the addition of the Mockingbird button component aligns with the modernization effort.


Line range hint 96-118: Well-structured component with proper hooks usage.

The implementation follows React/Helix best practices with proper hooks usage for data fetching and state management. The auto-opening of the mock modal for empty states is a good UX touch.

src/back/api/controllers/sync.clj (3)

11-11: Correct the typographical error in the commit message.

The string "Auto genereted commit by" should be changed to "Auto generated commit by".

-  (str "Auto genereted commit by " author "!!\n"
+  (str "Auto generated commit by " author "!!\n"
       "Co-authored-by: " co-author " <" email ">"))

217-243: Remove or secure commented-out code containing sensitive information.

This block includes references to private keys, installation IDs, and other sensitive data. It should be removed or securely stored to avoid accidental exposure.


43-43: 🛠️ Refactor suggestion

Use the configured GitHub API URL instead of the hard-coded URL.

In create-blob, the URL is currently hard-coded to "https://api.github.com". Use github-api-url from the function’s parameters or config to ensure consistency and to enable custom GitHub endpoints if needed.

- :url (format "%s/repos/%s/%s/git/blobs" "https://api.github.com" owner repo)
+ :url (format "%s/repos/%s/%s/git/blobs" github-api-url owner repo)

Likely invalid or redundant comment.

src/back/api/schemas/wire_in.clj (2)

5-6: Add format validation for GitHub username.

While :git-username is optional and typed as string?, consider adding a regex or a predicate to validate the GitHub username format. This helps ensure data correctness and consistency.


42-43: Enforce positivity checks on git-install-id.

[:git-install-id {:optional true} integer?] might allow negative values. Consider a validation rule to ensure the value is non-negative (or strictly positive if required).

src/back/api/controllers/mocks.clj (2)

13-15: Logging context looks good.

The approach of associating :mock and :user-id into the logging context is consistent and helpful for debugging. No issues found here.


43-50: Add SHA validation when updating the mock.

Currently, the code updates the sha field without verifying if it’s a valid 40-character hex string. Adding a check ensures data integrity and avoids unexpected errors downstream.

src/front/app/dashboard/events.cljs (13)

311-319: LGTM!

The handler correctly updates the db with repository data.


321-329: LGTM!

The handler correctly initiates the Git sync check and sets loading state.


331-343: LGTM!

The handler correctly updates sync status and shows appropriate notifications based on the response.


345-352: LGTM!

The handler correctly handles the failure case by updating sync status and showing an error notification.


381-386: LGTM!

The handler correctly updates loading state and shows a success notification.


397-401: LGTM!

The handler correctly initiates mock polling.


403-406: LGTM!

The handler correctly stops mock polling.


408-418: LGTM!

The handler correctly implements mock polling with a 5-second interval.


429-435: LGTM!

The handler correctly updates server mock data with appropriate validation.


437-445: LGTM!

The handler correctly reloads mock data from the server.


286-289: Verify naming consistency.

The handler name and parameter suggest toggling a modal, but the db key is :require-git-repo?. This naming inconsistency could lead to confusion.

Run the following script to verify the usage of these terms:


273-284: ⚠️ Potential issue

Fix incorrect event handler registration.

The event handler is registered using reg-event-db but returns an HTTP effect. When an event handler produces effects, it should be registered using reg-event-fx.

Apply this diff to fix the registration:

-(refx/reg-event-db
+(refx/reg-event-fx
 :app.dashboard/set-new-username
 (fn [{{:keys [current-user]} :db} [_ username-to-save]]
   (let [access-token (:access-token current-user)
         user-id (:user_id (:user current-user))]
     {:http {:url (str "user/" user-id)
             :method :post
             :headers {"authorization" (str "Bearer " access-token)}
             :body {:username username-to-save}
             :on-success [:app.auth/save-username]
             :on-failure []}})))

Likely invalid or redundant comment.


291-309: 🛠️ Refactor suggestion

Add loading state cleanup on failure.

The handler sets loading state but doesn't clean it up on failure.

Apply this diff to clean up loading state:

 (refx/reg-event-fx
  :app.dashboard/update-git-repo
  (fn [{db :db} [_ git-repo]]
    (let [mock-id (:curr-mock-id db)
          mock (->> db :mocks-raw
                    (filter #(= (str (:id %)) (str mock-id)))
                    first)]
      {:http {:url "/mocks"
              :method :put
              :headers {"authorization" (str "Bearer " (-> db :current-user :access-token))}
              :body {:id mock-id
                     :git-repo git-repo
                     :content (:content mock)}
              :on-success [:app.dashboard/save-mock-success]
-             :on-failure [:app.dashboard/save-mock-failed]}
+             :on-failure [:app.dashboard/update-git-repo-failed]}
       :db (-> db
               (assoc :loading-edit-mock true)
               (dissoc :curr-mock-id))})))

+(refx/reg-event-db
+ :app.dashboard/update-git-repo-failed
+ (fn [db _]
+   (-> db
+       (assoc :loading-edit-mock false)
+       (dissoc :curr-mock-id))))

Likely invalid or redundant comment.

src/back/api/ports/http_in.clj (5)

356-366: LGTM!

The function correctly checks Git sync status based on the installation ID.


368-417: LGTM!

The function correctly handles pushing mock changes to GitHub with appropriate error handling and logging.


419-428: Move example code to tests.

Example code in comment blocks should be moved to test files for better maintainability and to ensure it stays up to date.
[ref


236-239: 🧹 Nitpick (assertive)

Use path manipulation functions.

Instead of using string operations for path handling, consider using proper path manipulation functions.

Apply this diff to improve path handling:

 (defn- filter-mocks [files]
-  (into [] (filter #(and (= (last (str/split % #"/")) "moclojer.yml")
-                         (str/includes? % "mocks/"))
-                   files)))
+  (let [mock-filename "moclojer.yml"
+        mock-dir "mocks"]
+    (into [] (filter #(and (= (.getName (java.io.File. %)) mock-filename)
+                          (.startsWith % (str mock-dir "/")))
+                     files))))

Likely invalid or redundant comment.


345-354: 🧹 Nitpick (assertive)

Enhance error messages for better debugging.

The error message could be more descriptive about why repos couldn't be retrieved.

Apply this diff to improve error messages:

       {:status 404
-       :body {:message "Could not retrieve user repos"}})))
+       :body {:message "Could not retrieve user repos: Git installation ID not found"
+              :user_id (:uuid user)}})))

Likely invalid or redundant comment.

src/front/app/components/svg.cljs Show resolved Hide resolved
src/front/app/components/svg.cljs Show resolved Hide resolved
src/front/app/dashboard/subs.cljs Outdated Show resolved Hide resolved
src/front/app/dashboard/subs.cljs Outdated Show resolved Hide resolved
src/front/app/dashboard/editor.cljs Outdated Show resolved Hide resolved
Comment on lines +388 to +395
(refx/reg-event-fx
:app.dashboard/push-mock-failed
(fn [{db :db} [_ response]]
(js/console.error "Push failed:", (clj->js response))
{:db (assoc db :loading-push false)
:notification {:type :error
:content (or (-> response :body :message)
"Failed to push to GitHub")}}))
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Remove debug print statement.

Debug print statements should not be in production code.

Apply this diff to remove the debug print:

-   (js/console.error "Push failed:", (clj->js response))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(refx/reg-event-fx
:app.dashboard/push-mock-failed
(fn [{db :db} [_ response]]
(js/console.error "Push failed:", (clj->js response))
{:db (assoc db :loading-push false)
:notification {:type :error
:content (or (-> response :body :message)
"Failed to push to GitHub")}}))
(refx/reg-event-fx
:app.dashboard/push-mock-failed
(fn [{db :db} [_ response]]
{:db (assoc db :loading-push false)
:notification {:type :error
:content (or (-> response :body :message)
"Failed to push to GitHub")}}))

(refx/reg-event-db
:app.dashboard/set-new-username
(fn [{{:keys [current-user]} :db} [_ username-to-save]]
(js/console.log username-to-save current-user)
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Remove debug print statement.

Debug print statements should not be in production code.

Apply this diff to remove the debug print:

-  (js/console.log username-to-save current-user)

mock (->> db :mocks-raw
(filter #(= (str (:id %)) (str mock-id)))
first)]
(js/console.log "Updating git repo with:" git-repo)
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Remove debug print statement.

Debug print statements should not be in production code.

Apply this diff to remove the debug print:

-    (js/console.log "Updating git repo with:" git-repo)

Comment on lines +360 to +361
(js/console.log "Mock being pushed:" (clj->js mock))
(js/console.log "Content type:" (type (:content mock)))
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Remove debug print statements.

Debug print statements should not be in production code.

Apply this diff to remove the debug prints:

-    (js/console.log "Mock being pushed:" (clj->js mock))
-    (js/console.log "Content type:" (type (:content mock)))

src/back/api/ports/http_in.clj Outdated Show resolved Hide resolved
@Felipe-gsilva
Copy link
Member Author

Felipe-gsilva commented Feb 1, 2025

@avelino @J0sueTM for you guys to know, the user can now use git sync, but not in prod, yet, because we will need to add a few things first (I mentioned it in #379 #378 #381 specially), but it is working within dev context (hit me out in discord so I can explain how to set things up, since we need some secrets for handling git ops

however, orgs are yet no perfectly implemented in UI (as it should already be #377), for that I'm sorry, because things got a little messy with the scale of this feature here 🙏

if anything seems off, just tag me here and I will explain it better for you all

Copy link

@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: 6

♻️ Duplicate comments (1)
src/back/api/ports/http_in.clj (1)

241-344: 🧹 Nitpick (assertive)

Consider concurrency and multiple matches in the push-event logic.

  • For large commits, processing each file in doseq might be slow. Evaluate whether parallel or batched operations could help.
  • Lines 294–309: If multiple existing mocks match the same wildcard, consider clarifying how duplicates should be handled.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d43661 and 30660c4.

📒 Files selected for processing (4)
  • src/back/api/adapters/orgs.clj (1 hunks)
  • src/back/api/controllers/orgs.clj (2 hunks)
  • src/back/api/logic/orgs.clj (2 hunks)
  • src/back/api/ports/http_in.clj (8 hunks)
🧰 Additional context used
📓 Learnings (1)
src/back/api/ports/http_in.clj (1)
Learnt from: Felipe-gsilva
PR: moclojer/moclojer-app#375
File: src/back/api/ports/http_in.clj:218-277
Timestamp: 2025-01-24T13:37:14.472Z
Learning: The webhook endpoint in moclojer-app verifies GitHub webhook signatures using the verify-webhook-signature interceptor from back.api.interceptors.verify-webhook, which uses clj-github-app.webhook-signature library.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: WIP
🔇 Additional comments (10)
src/back/api/adapters/orgs.clj (2)

1-2: LGTM! Good choice of utility function.

The addition of assoc-if from utils is appropriate for handling conditional key association.


5-13: Verify Git-related field usage across the codebase.

The function modifications look good. The conditional association of Git fields is implemented correctly, maintaining consistent naming conventions.

Let's verify the usage of these new fields:

✅ Verification successful

Git-related field naming and usage are consistent across the codebase.

The search results confirm that the new fields (git-install-id and git-orgname) and their corresponding snake_case forms (git_install_id, etc.) are used consistently across the adapters, schemas, controllers, and database logic. No naming discrepancies or typos were detected.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for git-install-id and git-orgname usage to ensure consistent naming
rg -l "git-install-id|git_install_id|git-orgname|git_orgname" --type clojure

# Check for any potential typos or inconsistent naming
rg -i "git.*install.*id|git.*org.*name" --type clojure

Length of output: 2950

src/back/api/ports/http_in.clj (6)

2-15: Imports look consistent and appropriate.
No issues found with the required namespaces. The dependencies match up with the usage throughout the file.


26-31: Handle potential edge cases for install-id.
If install-id is provided, ensure it’s a valid value. You might also handle scenarios where install-id is absent or fails validation, returning an error message or status code.


89-91: Remove debug print statements from production code.
The (prn mocks) call appears to be for debugging or inspection and might accidentally expose details in production logs.


236-239: Use a more robust path manipulation approach.
Manually splitting file paths with str/split can be brittle. If feasible, consider using a path library or a more standardized approach to avoid edge cases.


368-417: Ensure robust parsing for git-repo in handler-push-mock!.
When splitting git-repo to derive [owner repo-name], verify that the resulting vector indeed has two parts. If the user supplies an unexpected or invalid URL, a runtime error may occur.


172-177: 🧹 Nitpick (assertive)

Validate organization creation and membership more robustly.

  • Lines 172–177: Consider concurrency or conflict checks for handler-create-org if multiple requests create the same org simultaneously.
  • Line 224: Ensure new-org-user is never nil; otherwise, (:user-id new-org-user) might fail.

Also applies to: 224-224

src/back/api/controllers/orgs.clj (2)

57-60: LGTM!

The changes to logging context in add-org-user! and remove-org-user! functions look good. Using assoc instead of merge makes the context handling clearer.

Also applies to: 71-73


80-85: ⚠️ Potential issue

Fix inconsistent function name and add error handling.

The function has two issues:

  1. The database function call uses a different name (get-by-git-org-name vs git-orgname).
  2. Missing error handling for non-existent organizations.

Apply this diff to fix the issues:

 (defn get-by-git-orgname
   [git-orgname {:keys [database]} ctx]
   (logs/log :info "retrieving org by its git_orgname"
             (assoc ctx :git-orgname git-orgname))
-  (-> (db.orgs/get-by-git-org-name git-orgname database ctx)
-      (adapter.orgs/->wire)))
+  (or (-> (db.orgs/get-by-git-org-name git-orgname database ctx)
+          (adapter.orgs/->wire))
+      (throw (ex-info "No organization with given Git organization name was found"
+                      {:status-code 412
+                       :cause :invalid-git-orgname
+                       :value git-orgname}))))

Likely invalid or redundant comment.

src/back/api/adapters/orgs.clj Show resolved Hide resolved
src/back/api/logic/orgs.clj Show resolved Hide resolved
src/back/api/logic/orgs.clj Show resolved Hide resolved
src/back/api/controllers/orgs.clj Show resolved Hide resolved
@Felipe-gsilva
Copy link
Member Author

@coderabbitai give us a brief summary about what has been changed in this PR

Copy link

coderabbitai bot commented Feb 1, 2025

Tip

For best results, initiate chat on the files or code changes.

@Felipe-gsilva Here's a summary of the key changes in this PR:

  1. Git Sync Integration:

    • Added GitHub integration capabilities allowing mocks to be synced with git repositories
    • Implemented GitHub App authentication and repository operations
    • Added new database columns to support git sync (repo URLs, SHA hashes, install IDs)
  2. User & Organization Updates:

    • Enhanced user and organization models with GitHub-related fields
    • Added support for GitHub usernames and organization names
    • Implemented installation ID tracking for GitHub App
  3. UI Enhancements:

    • Added new settings modal for git sync configuration
    • Implemented repository selection interface
    • Updated mock editor with git sync controls
  4. Dependencies & Configuration:

    • Added GitHub-related dependencies (clj-github, data.json)
    • Updated puppeteer to version 23.4.0
    • Added git sync configuration section in config.edn

Note: As mentioned, while the feature is functional in development, it requires additional work before production deployment, including proper organization UI implementation (#377) and other related issues (#379, #378, #381).

@Felipe-gsilva
Copy link
Member Author

Tip

For best results, initiate chat on the files or code changes.

@Felipe-gsilva Here's a summary of the key changes in this PR:

1. **Git Sync Integration**:
   
   * Added GitHub integration capabilities allowing mocks to be synced with git repositories
   * Implemented GitHub App authentication and repository operations
   * Added new database columns to support git sync (repo URLs, SHA hashes, install IDs)

2. **User & Organization Updates**:
   
   * Enhanced user and organization models with GitHub-related fields
   * Added support for GitHub usernames and organization names
   * Implemented installation ID tracking for GitHub App

3. **UI Enhancements**:
   
   * Added new settings modal for git sync configuration
   * Implemented repository selection interface
   * Updated mock editor with git sync controls

4. **Dependencies & Configuration**:
   
   * Added GitHub-related dependencies (clj-github, data.json)
   * Updated puppeteer to version 23.4.0
   * Added git sync configuration section in config.edn

Note: As mentioned, while the feature is functional in development, it requires additional work before production deployment, including proper organization UI implementation (#377) and other related issues (#379, #378, #381).

@coderabbitai you can be more specific over this answer, I said brief but I meant, not that brief

Copy link

coderabbitai bot commented Feb 1, 2025

Tip

For best results, initiate chat on the files or code changes.

@Felipe-gsilva Here's a more detailed breakdown of the changes in this PR:

  1. Database Schema Changes:

    • Added git_repo (VARCHAR) and sha (CHAR) columns to mock table with validation constraints
    • Added git_install_id (INT) to both org and customer tables
    • Added unique git_orgname (VARCHAR) to org table and git_username (VARCHAR) to customer table
  2. Backend API Changes:

    • New Controllers:

      • back.api.controllers.sync: Implements GitHub operations (commit, blob, tree creation)
      • Enhanced back.api.controllers.user: Added git username and sync capabilities
      • Enhanced back.api.controllers.orgs: Added git organization management
    • New Schemas:

      • Wire-in: Added MockPush, UserUpdate with git-related fields
      • Wire-out: Enhanced User, Mock, Org schemas with git sync fields
    • Database Layer:

      • Added get-by-git-username and get-by-email to customers
      • Added get-by-git-org-name to orgs
      • Enhanced mock operations with git sync support
  3. Frontend Changes:

    • Components:

      • New settings modal for git sync configuration
      • Updated editor toolbar with git sync controls
      • Migrated to Mockingbird components library
    • State Management:

      • Added git sync events and subscriptions
      • Enhanced mock management with git sync capabilities
      • Added repository selection and sync status handling
  4. Authentication & Authorization:

    • Enhanced login flow with GitHub OAuth support
    • Added GitHub App authentication for repository operations
    • Implemented installation tracking for organizations and users
  5. Configuration & Dependencies:

    • Added GitHub-related dependencies:
      dev.nubank/clj-github {:mvn/version "0.6.3"}
      org.clojure/data.json {:mvn/version "2.5.1"}
      nubank/clj-github-app {:mvn/version "0.3.0"}
    • Added git sync configuration in config.edn:
      :git-sync {:secret "ok"
                 :app-id ""
                 :api-url "https://api.github.com"
                 :private-key ""}
    • Updated puppeteer from 20.7.2 to 23.4.0
  6. Testing Infrastructure:

    • Added tests for git sync operations
    • Enhanced existing tests with git-related fields
    • Updated test fixtures and helpers

The implementation allows for:

  • Two-way sync between mocks and git repositories
  • GitHub App-based authentication for secure repository access
  • Organization-level git sync configuration
  • User-level repository management

Development status:

Copy link

@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: 8

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30660c4 and 89a709b.

📒 Files selected for processing (6)
  • src/back/api/ports/http_in.clj (8 hunks)
  • src/front/app/dashboard/base.cljs (3 hunks)
  • src/front/app/dashboard/editor.cljs (6 hunks)
  • src/front/app/dashboard/events.cljs (5 hunks)
  • src/front/app/dashboard/subs.cljs (3 hunks)
  • src/front/app/routes/bookmarks.cljs (1 hunks)
🧰 Additional context used
📓 Learnings (1)
src/back/api/ports/http_in.clj (1)
Learnt from: Felipe-gsilva
PR: moclojer/moclojer-app#375
File: src/back/api/ports/http_in.clj:218-277
Timestamp: 2025-01-24T13:37:14.472Z
Learning: The webhook endpoint in moclojer-app verifies GitHub webhook signatures using the verify-webhook-signature interceptor from back.api.interceptors.verify-webhook, which uses clj-github-app.webhook-signature library.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: WIP
🔇 Additional comments (51)
src/front/app/routes/bookmarks.cljs (2)

2-6: Improved Indentation in :require Block.
The adjusted indentation in the :require block enhances readability and aligns with common Clojure style practices. No functionality has changed.


8-43: Clear and Consistent Route Definitions.
The route definitions remain clear and consistent. The structure for each route—including the naming, view mapping, and public accessibility—is well maintained.

src/front/app/dashboard/base.cljs (6)

17-61: Consider using defnc instead of defn for React components using Helix hooks.

This file defines settings-modal with defn but internally uses Helix hooks (hooks/use-state). In Helix, defnc is typically preferred to ensure correct hook usage and name resolution during macro expansion.


88-89: doseq doesn't render DOM elements in React.

Using (doseq [org user-orgs] (d/p org)) inside the return expression won't produce any rendered elements. Convert this to a mapping function (e.g., mapv) to display the organizations.


150-150: Possible typo in class name 'lm:col-span-3'.

Did you intend sm:col-span-3 or another breakpoint? Helix doesn't recognize 'lm:col-span-3' as a standard class name.


161-161: :on-load event on input is not supported in React.

Consider removing :on-load and using a use-effect hook or :default-value for initialization.


176-177: Inconsistent use of class vs class-name.

You’re using :class-name here but :class elsewhere. In Helix, DOM elements typically expect the :class attribute.


292-335: Consider using defnc if you are calling Helix hooks within update-repo-modal.

Helix’s defnc macro is recommended for function components that utilize hooks for state or effect management.

src/front/app/dashboard/events.cljs (27)

2-2: No issues found in import changes.


26-31: Looks good.

Toggling the settings modal is implemented as a side-effecting event with reg-event-fx, returning a new :db state.


39-45: No issues found.


113-120: Implementation is clean and consistent.


122-130: No apparent problems with the error handling logic here.


145-145: No issues found.


160-160: No issues found.


271-277: No concerns here.


279-283: No issues with the failure event logic.


285-286: No issues with the event parameters.


287-287: Remove debug print statement.

Debug print statements (js/console.log) should not remain in production code.


297-301: Confirm naming consistency for toggling the git-repo modal.

Inverting :require-git-repo? by passing modal-open? might be confusing. Please verify.


303-321: Logic appears fine.


323-330: No issues found.


333-347: Implementation looks correct for enabling Git sync.


349-359: No problems found with the alert logic here.


361-369: Event handler is consistent.


371-378: Error handling is straightforward here.


380-385: Push logic initialization looks fine.


386-387: Remove debug print statements.

Consider removing js/console.log to prevent noise in production logs.


388-405: Push request logic is correct.


407-413: Good handling of success event.


415-421: Remove the debug print at line 417.

js/console.error is used for a server error message. Consider more structured logging or removing debug prints for production.


424-448: Polling logic is clearly implemented.


449-449: Remove console.warn.

Debugging statements can clutter production logs.


450-453: No issues in the rest of the failure handler.


455-461: Reload event logic looks good.

src/front/app/dashboard/subs.cljs (8)

2-2: No issues found in import changes.


53-56: Subscription registration is straightforward.


90-90: Changes here appear minimal.


95-98: require-git-repo? subscription is well-defined.


100-103: Subscription for repos looks fine.


105-108: is-sync-enabled? subscription logic is correct.


110-113: Loading state subscription is consistent.


115-122: Comparison logic for mock-has-changes? is valid.

src/back/api/ports/http_in.clj (4)

2-15: All good on the import statements.
No issues found; everything looks fine here, and no import reordering is required.


235-238: Use path manipulation functions for reliability.
A similar suggestion was previously made. Using Java’s path utilities (e.g., java.io.File) or a library can robustly handle edge cases and enhance readability.


239-342: Consider concurrency/batching for large mock sets.
Prior feedback suggested parallel or batched processing to avoid performance bottlenecks when many mocks are updated.


357-357: Remove debug print statement.
Printing out session-data in production code can be noisy. Use structured logging if you need visibility.

src/front/app/dashboard/editor.cljs (4)

1-18: Inconsistent namespace usage remains partially unaddressed
This file still mixes the front.app.dashboard namespace with imports from mockingbird.lib. As noted previously, the namespace migration appears incomplete.


31-35: Well-structured polling lifecycle
This use-effect correctly starts and stops the mock polling when the component mounts or unmounts (or when id changes).


118-125: Reload button always showing spinner
As previously noted, the spinner is displayed unconditionally. Consider toggling it based on a loading state for clarity.


216-217: Check the items-left utility
Please confirm items-left is a valid custom Tailwind class or switch to items-start.

Comment on lines +26 to +31
[{{{:keys [username install-id]} :body} :parameters
{:keys [user-id]} :session-data
{:keys [database]} :components
ctx :ctx}]
{:status 200
:body {:user (controllers.user/edit-user! user-id username database ctx)}})
:body {:user (controllers.user/edit-user! user-id username install-id database ctx)}})
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider validating or normalizing the install-id.
While adding install-id is a sensible extension, it might benefit from a simple validation (e.g., checking whether it’s numeric or not) before saving.

Comment on lines +375 to +377
[owner repo-name] (-> git-repo
(str/replace #"https://github.com/" "")
(str/split #"/"))
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add robust validation when extracting owner and repo.
Splitting git-repo by slashes can fail if it does not include “github.com/owner/repo”. Consider safely validating the string structure or gracefully handling malformed URLs.

(let [git-user (controllers.user/get-user-by-id user-id components ctx)
-      [owner repo-name] (-> git-repo
-                            (str/replace #"https://github.com/" "")
-                            (str/split #"/"))
+      [owner repo-name :as segments] (some-> git-repo
+                                            (str/replace #"^https://github.com/" "")
+                                            (str/split #"/"))
+      ;; Validate segments length before destructuring,
+      ;; e.g. (when (not= (count segments) 2) ...)
       install-id (:git-install-id git-user)
       ...]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[owner repo-name] (-> git-repo
(str/replace #"https://github.com/" "")
(str/split #"/"))
(let [git-user (controllers.user/get-user-by-id user-id components ctx)
[owner repo-name :as segments] (some-> git-repo
(str/replace #"^https://github.com/" "")
(str/split #"/"))
;; Validate segments length before proceeding, e.g.:
;; (when (not= (count segments) 2)
;; (throw (ex-info "Invalid git-repo format" {:git-repo git-repo})))
install-id (:git-install-id git-user)
...]

Comment on lines 67 to 84
[{:keys [parameters session-data components ctx]}]
(let [user-id (:user-id session-data)
old-mock (:body parameters)
content (:content old-mock)
id (:id old-mock)
sha (:sha old-mock)
git-path (:git-repo old-mock)
git-repo (when git-path (last (str/split git-path #"/")))
new-mock (controllers.mocks/update-mock! (parse-uuid (str id))
(-> {}
(utils/assoc-if :content content)
(cond->
(not= sha "") (utils/assoc-if :sha sha)
(not= git-repo "") (utils/assoc-if :git-repo git-path)))
components
ctx)]
{:status 200
:body {:mock mock}}))
:body {:mock new-mock}}))
Copy link

@coderabbitai coderabbitai bot Feb 3, 2025

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Refine checks for sha and git-repo.
Using (not= sha "") or (not= git-repo "") could inadvertently allow nil values. Consider (some? sha) or (not-empty sha) for clarity, ensuring only non-blank strings are used.

- (cond->
-  (not= sha "") (utils/assoc-if :sha sha)
-  (not= git-repo "") (utils/assoc-if :git-repo git-path))
+ (cond->
+  (not-empty sha) (utils/assoc-if :sha sha)
+  (not-empty git-repo) (utils/assoc-if :git-repo git-path))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
[{:keys [parameters session-data components ctx]}]
(let [user-id (:user-id session-data)
old-mock (:body parameters)
content (:content old-mock)
id (:id old-mock)
sha (:sha old-mock)
git-path (:git-repo old-mock)
git-repo (when git-path (last (str/split git-path #"/")))
new-mock (controllers.mocks/update-mock! (parse-uuid (str id))
(-> {}
(utils/assoc-if :content content)
(cond->
(not= sha "") (utils/assoc-if :sha sha)
(not= git-repo "") (utils/assoc-if :git-repo git-path)))
components
ctx)]
{:status 200
:body {:mock mock}}))
:body {:mock new-mock}}))
[{:keys [parameters session-data components ctx]}]
(let [user-id (:user-id session-data)
old-mock (:body parameters)
content (:content old-mock)
id (:id old-mock)
sha (:sha old-mock)
git-path (:git-repo old-mock)
git-repo (when git-path (last (str/split git-path #"/")))
new-mock (controllers.mocks/update-mock! (parse-uuid (str id))
(-> {}
(utils/assoc-if :content content)
(cond->
(not-empty sha) (utils/assoc-if :sha sha)
(not-empty git-repo) (utils/assoc-if :git-repo git-path)))
components
ctx)]
{:status 200
:body {:mock new-mock}}))

Copy link
Member

Choose a reason for hiding this comment

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

@Felipe-gsilva acredito que isso faça sentido, não validar só ""

Copy link

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Member Author

Choose a reason for hiding this comment

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

@avelino realmente, eu nao coloquei a funcao q eu criei pra validar o sha ai 🫠

Comment on lines +150 to +164
(defnc editor-toolbar [{:keys [mock-id]}]
(let [has-changes? (refx/use-sub [:app.dashboard/mock-has-changes? mock-id])
sync-enabled? (refx/use-sub [:app.dashboard/is-sync-enabled?])]
(d/div {:class "flex items-center space-x-2"}
(when-not sync-enabled?
($ enable-sync-button {:mock-id mock-id}))
(when (and sync-enabled? has-changes?)
($ reload-button {:mock-id mock-id}))
($ remove-button {:mock-id mock-id})
(if sync-enabled?
($ save-button {:mock-id mock-id
:sync-enabled? sync-enabled?
:class "ml-auto "})
($ enable-sync-status {:mock-id mock-id
:sync-enabled? sync-enabled?})))))
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Conflicting enable-sync logic
editor-toolbar calls enable-sync-button, yet actual sync enabling is done in enable-sync-status.
• The button dispatches a reload instead of enabling sync.
These duplicated or conflicting flows risk confusion. Unify your approach so the user’s click on “Enable Git Sync” actually enables sync.

+;; Option 1: Make the button directly enable sync, remove auto-enabling from `enable-sync-status`.
+;; Option 2: Remove the button if enabling is purely automatic.

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +127 to +135
(defnc enable-sync-button [{:keys [mock-id]}]
(d/button
{:class (str "px-3 py-2 rounded-lg flex justify-center items-center space-x-2 "
"transition-all duration-75 ")
:on-click #(refx/dispatch-sync [:app.dashboard/reload-mock mock-id])}
(d/div {:class "text-black text-xs font-bold leading-[18px]"}
"enable git sync")
($ loading-spinner)))

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Mismatch between button label and dispatch action
Despite being called enable-sync-button, this component dispatches [:app.dashboard/reload-mock]. Update the dispatch action or rename the component to match its intent. Also consider conditionally showing the spinner.

Proposed fix

(defnc enable-sync-button [{:keys [mock-id]}]
  (d/button
    {:class (str "px-3 py-2 rounded-lg flex justify-center items-center space-x-2 "
                 "transition-all duration-75 ")
-    :on-click #(refx/dispatch-sync [:app.dashboard/reload-mock mock-id])}
+    :on-click #(refx/dispatch-sync [:app.dashboard/enable-git-sync mock-id])}
    (d/div {:class "text-black text-xs font-bold leading-[18px]"}
           "enable git sync")
-   ($ loading-spinner)))
+   ;; Optionally render the spinner only if enabling is actually in progress
+   ))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(defnc enable-sync-button [{:keys [mock-id]}]
(d/button
{:class (str "px-3 py-2 rounded-lg flex justify-center items-center space-x-2 "
"transition-all duration-75 ")
:on-click #(refx/dispatch-sync [:app.dashboard/reload-mock mock-id])}
(d/div {:class "text-black text-xs font-bold leading-[18px]"}
"enable git sync")
($ loading-spinner)))
(defnc enable-sync-button [{:keys [mock-id]}]
(d/button
{:class (str "px-3 py-2 rounded-lg flex justify-center items-center space-x-2 "
"transition-all duration-75 ")
:on-click #(refx/dispatch-sync [:app.dashboard/enable-git-sync mock-id])}
(d/div {:class "text-black text-xs font-bold leading-[18px]"}
"enable git sync")
;; Optionally render the spinner only if enabling is actually in progress
))

Copy link

@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: 8

♻️ Duplicate comments (1)
resources/back/config.edn (1)

6-8: ⚠️ Potential issue

Remove hardcoded sensitive values from configuration.

Multiple sensitive configurations are exposed with potentially valid default values:

  • Supabase API key and JWT secret
  • AWS credentials
  • Digital Ocean token
  • Cloudflare token
  • Database credentials

This poses a significant security risk if these values are valid or if they're accidentally used in production.

Recommendations:

  1. Remove all default values for sensitive configurations
  2. Use placeholder values (e.g., "REQUIRED") or throw errors when environment variables are missing
  3. Rotate any potentially valid tokens that have been exposed
  4. Consider using a secure secrets management solution

Example fix for one section:

-:supabase-api-key #or [#env SUPABASE_API_KEY "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InRndmRmeHVyZ3NkZHhvdXhtdWdzIiwicm9sZSI6ImFub24iLCJpYXQiOjE2ODE1MDM0NDMsImV4cCI6MTk5NzA3OTQ0M30.7pq4MM_ZldiWvOk_cnQuxlvUF8eFcxlPDB7jMTNMYb0"]
+:supabase-api-key #or [#env SUPABASE_API_KEY ""]

Apply similar changes to all sensitive configurations.

Also applies to: 18-20, 34-34, 37-37, 44-44

🧰 Tools
🪛 Gitleaks (8.21.2)

6-6: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 89a709b and 35290e1.

📒 Files selected for processing (4)
  • resources/back/config.edn (1 hunks)
  • src/front/app/dashboard/base.cljs (3 hunks)
  • src/front/app/dashboard/editor.cljs (6 hunks)
  • src/front/app/dashboard/events.cljs (5 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: WIP
🔇 Additional comments (39)
resources/back/config.edn (1)

9-12: Add validation for required GitHub App credentials.

While using empty defaults for sensitive values is good practice, the application should validate that required values are provided before attempting GitHub integration.

Consider adding runtime validation:

 :git-sync {:secret #or [#env GITHUB_APP_SECRET ""]
            :app-id #or [#env GITHUB_APP_ID ""]
            :api-url #or [#env GITHUB_API_URL "https://api.github.com"]
-            :private-key #or [#env GITHUB_PRIVATE_KEY ""]}
+            :private-key #or [#env GITHUB_PRIVATE_KEY ""]
+            :validate-required? true}

Then add validation logic in your initialization code to ensure these values are set when :validate-required? is true.

src/front/app/dashboard/base.cljs (7)

88-88: Use a mapping function instead of doseq to render DOM elements.
This is a repeat of a past review comment. Replacing doseq with map or mapv ensures that each org element is returned and properly rendered in the DOM.


98-98: Revisit the switch from defnc to defn.
This repeats a prior concern that using defn in components leveraging hooks may cause issues. Consider reverting to defnc unless there is a specific reason to avoid it.


150-150: Possible typo in class name 'lm:col-span-3'.
This repeats a previous suggestion that 'lm:col-span-3' might be a typo (e.g., 'sm:col-span-3') or an unintended breakpoint.


161-161: on-load event handler is not supported on input elements.
Repeating a past comment: use hooks/use-effect or a default value to initialize :wildcard instead of :on-load.


176-176: Inconsistent usage of :class vs. :class-name.
This mirrors an earlier suggestion: replace :class-name with :class to maintain consistency within Helix DOM elements.


292-319: Provide a fallback message when no repositories are available.
This is a repeat of a past comment: if repos is empty, the modal remains blank. Consider rendering a short message like “No repositories found” for clarity.


321-321: Good usage of defnc in a Helix component.
This usage helps ensure correct hook handling and naming resolution. No issues to report here.

src/front/app/dashboard/editor.cljs (11)

1-12: All good here.
No major issues found in these lines; the namespace declaration and required libraries look appropriate.

Also applies to: 14-18


13-13: Inconsistent namespace usage


31-35: Consider passing the mock ID to stop the polling
While the cleanup function calls [:app.dashboard/stop-mock-polling], it doesn’t specify the mock-id. If the underlying logic supports multiple parallel polls, you might need to stop polling for the correct mock. Otherwise, verify that only one mock is polled at a time.

Would you like me to generate a script to identify other occurrences of stop-mock-polling to confirm whether it needs the mock-id argument?


77-81: LGTM: Drag-and-drop label
The drag-and-drop label, icon, and text are user-friendly and clear.


99-110: Add multi-file support if required


112-119: No issues found
The removal button logic is straightforward and consistent with typical re-frame patterns.


120-128: Unconditional spinner display


129-137: Mismatch between button label and dispatch action


152-166: Conflicting enable-sync logic


218-219: Check the items-left class


243-258: LGTM: Top-level layout
These lines effectively combine the editor toolbar, file upload button, drag-drop interface, and editor in a cohesive UI.

src/front/app/dashboard/events.cljs (20)

2-3: Imports look correct
The refx.alpha import is referenced properly. No issues found here.


24-25: Switch to reg-event-db if only returning :db
This event returns only :db without additional effects. Using reg-event-db would simplify the handler.


26-31: Switch to reg-event-db if only returning :db
This handler likewise returns only :db. Consider using reg-event-db for consistency with recommended patterns.


39-45: Use reg-event-db if no side effects
This handler updates only the database. Converting it to reg-event-db clarifies that no other effects occur.


106-110: Headers and body construction look correct
No issues found; the construction of HTTP request headers and body is properly handled.


114-115: Appropriate use of reg-event-fx
You dispatch a follow-up event and a user-facing notification, both of which are side effects, so using reg-event-fx is correct.


160-161: LGTM
Changing :mocks-raw in the database after success is correctly handled here.


271-296: Remove debug print statements
(js/console.log username-to-save current-user) may leak user info and clutter production logs. Please remove or replace with a more secure logging approach.


297-301: Confirm naming consistency
Toggling the modal inverts :require-git-repo?. Verify that this accurately reflects the intended logic.


302-321: Remove debug prints
(js/console.log "Updating git repo with:" git-repo) is likely a leftover debug statement and should be removed for production.


322-331: Repository data handling is clear
Storing :repositories from the API response looks correct.


332-348: Usage of reg-event-fx for multiple side effects
Dispatching a check for missing repos and triggering the /sync call is well-organized.


361-370: Synchronization enabling logic looks correct
You handle success by toggling flags and showing a notification. No concerns here.


371-379: Error-handling approach is consistent
Properly sets :sync-enabled to false and notifies the user on sync failure.


380-406: Remove leftover debug logs
Lines 386 and 387 log the pushed mock details. These appear to be debug prints and should be removed or replaced with sanitized logs.


407-413: Clear success feedback
Marking :loading-push false and showing a success notification is standard practice.


423-445: Periodic polling logic is well-structured
You schedule repeated API calls and handle success/failure outcomes. No immediate issues noted.


446-454: Remove debug statements or confirm necessity
js/console.warn "Poll failed:" ... might be needed for diagnosing errors, but it can also clutter logs.


455-462: Server mock update logic is clean
Conditionally updating :server-mock in the DB if data is present appears correct.


463-472: Reloading mock from server
Dispatching a partial edit request with server content, followed by a user-facing notification, looks well-defined.

@@ -6,6 +6,10 @@
:supabase-api-key #or [#env SUPABASE_API_KEY "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InRndmRmeHVyZ3NkZHhvdXhtdWdzIiwicm9sZSI6ImFub24iLCJpYXQiOjE2ODE1MDM0NDMsImV4cCI6MTk5NzA3OTQ0M30.7pq4MM_ZldiWvOk_cnQuxlvUF8eFcxlPDB7jMTNMYb0"]
:supabase-url #or [#env SUPABASE_URL "https://tgvdfxurgsddxouxmugs.supabase.co"]
:supabase-jwt-secret #or [#env SUPABASE_JWT_SECRET "OP6cAnR4J7im0KH2sWeeTlwf4xQOZTuYtoO1mJ3vpON/szjCMpixe4r+9X3HvhZphxV79wl+2amIxo/AkfR28g=="]
:git-sync {:secret #or [#env GITHUB_APP_SECRET ""]
:app-id #or [#env GITHUB_APP_ID ""]
:api-url #or [#env GITHUB_API_URL "https://api.github.com"]
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Make API URL environment-specific.

The GitHub API URL should be configurable per environment to support testing with GitHub Enterprise or mock servers in non-production environments.

-            :api-url #or [#env GITHUB_API_URL "https://api.github.com"]
+            :api-url #profile {:dev #or [#env GITHUB_API_URL "http://localhost:8000"]
+                              :prod #or [#env GITHUB_API_URL "https://api.github.com"]
+                              :default #or [#env GITHUB_API_URL "https://api.github.com"]}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:api-url #or [#env GITHUB_API_URL "https://api.github.com"]
:api-url #profile {:dev #or [#env GITHUB_API_URL "http://localhost:8000"]
:prod #or [#env GITHUB_API_URL "https://api.github.com"]
:default #or [#env GITHUB_API_URL "https://api.github.com"]}

[helix.hooks :as hooks]
[refx.alpha :as refx]))

(defn settings-modal []
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider using defnc for Helix components using hooks.
Even though this function works with defn, it leverages Helix hooks (hooks/use-state), which typically requires Helix’s defnc macro to ensure proper hook usage and scope. Converting this to defnc can help prevent potential issues.

Comment on lines +138 to +150
(defnc enable-sync-status [{:keys [mock-id sync-enabled?]}]
(let [loading-sync? (refx/use-sub [:app.dashboard/loading-sync?])]
(hooks/use-effect
[]
(when-not sync-enabled?
(refx/dispatch-sync [:app.dashboard/enable-git-sync mock-id])))

(when loading-sync?
(d/div
{:class "px-3 py-2 bg-gray-500 rounded-lg flex justify-center items-center space-x-2"}
(d/div {:class "text-white text-xs font-bold leading-[18px]"}
"Enabling sync...")
($ loading-spinner)))))
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider re-running effect if sync state changes
The effect is only triggered once and won’t re-run if sync-enabled? toggles. If that’s intentional, keep as is; otherwise, consider adding sync-enabled? to the dependency vector.

Comment on lines +84 to +97
(defnc save-button [{:keys [mock-id full-width? sync-enabled?]}]
(let [mock-valid? (refx/use-sub [:app.dashboard/mock-valid?])]
(d/button
{:class-name (str "px-3 py-2 bg-pink-600 rounded-lg flex justify-center items-center btn-add space-x-2 "
(when full-width? "w-full ")
(when-not mock-valid? " opacity-50 cursor-not-allowed"))
{:class (str "w-full px-3 py-2 bg-pink-600 rounded-lg flex justify-center items-center btn-add space-x-2 transition-all duration-75 "
(when full-width? "w-full ")
(when-not mock-valid? " opacity-50 cursor-not-allowed"))
:on-click #(when mock-valid?
(refx/dispatch-sync [:app.dashboard/save-mock mock-id])
(refx/dispatch-sync [:app.dashboard/push-mock mock-id])
(refx/dispatch-sync [:app.dashboard/reset-mock-pub-stts mock-id]))}
(d/div {:class-name "text-white text-xs font-bold leading-[18px]"} " save")
($ svg/save))))
(d/div {:class "text-white text-xs font-bold leading-[18px]"} "save")
(if sync-enabled?
($ svg/github)
($ svg/save)))))
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Separate push action from save if needed
Currently “save” also triggers push-mock. This may surprise users who want to save local changes without pushing. If that’s desirable, great. Otherwise, consider splitting “save” and “push” to give finer control.

:on-click #(when mock-valid?
              (refx/dispatch-sync [:app.dashboard/save-mock mock-id])
-             (refx/dispatch-sync [:app.dashboard/push-mock mock-id])
              (refx/dispatch-sync [:app.dashboard/reset-mock-pub-stts mock-id]))
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(defnc save-button [{:keys [mock-id full-width? sync-enabled?]}]
(let [mock-valid? (refx/use-sub [:app.dashboard/mock-valid?])]
(d/button
{:class-name (str "px-3 py-2 bg-pink-600 rounded-lg flex justify-center items-center btn-add space-x-2 "
(when full-width? "w-full ")
(when-not mock-valid? " opacity-50 cursor-not-allowed"))
{:class (str "w-full px-3 py-2 bg-pink-600 rounded-lg flex justify-center items-center btn-add space-x-2 transition-all duration-75 "
(when full-width? "w-full ")
(when-not mock-valid? " opacity-50 cursor-not-allowed"))
:on-click #(when mock-valid?
(refx/dispatch-sync [:app.dashboard/save-mock mock-id])
(refx/dispatch-sync [:app.dashboard/push-mock mock-id])
(refx/dispatch-sync [:app.dashboard/reset-mock-pub-stts mock-id]))}
(d/div {:class-name "text-white text-xs font-bold leading-[18px]"} " save")
($ svg/save))))
(d/div {:class "text-white text-xs font-bold leading-[18px]"} "save")
(if sync-enabled?
($ svg/github)
($ svg/save)))))
(defnc save-button [{:keys [mock-id full-width? sync-enabled?]}]
(let [mock-valid? (refx/use-sub [:app.dashboard/mock-valid?])]
(d/button
{:class (str "w-full px-3 py-2 bg-pink-600 rounded-lg flex justify-center items-center btn-add space-x-2 transition-all duration-75 "
(when full-width? "w-full ")
(when-not mock-valid? " opacity-50 cursor-not-allowed"))
:on-click #(when mock-valid?
(refx/dispatch-sync [:app.dashboard/save-mock mock-id])
(refx/dispatch-sync [:app.dashboard/reset-mock-pub-stts mock-id]))}
(d/div {:class "text-white text-xs font-bold leading-[18px]"} "save")
(if sync-enabled?
($ svg/github)
($ svg/save)))))

Comment on lines +37 to +42
(let [mock-id (:id data)
has-changes? (refx/use-sub [:app.dashboard/mock-has-changes? mock-id])]
(d/div {:class (str "relative w-full h-full rounded-lg overflow-hidden m-2 "
(if has-changes? "border-2 border-yellow-500 "
"border-none "
))}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Remove the extra trailing space in the border style
The if has an additional space after "border-none ". While harmless, it slightly clutters the string construction. Consider removing it for consistency.

- (if has-changes? "border-2 border-yellow-500 " "border-none ")
+ (if has-changes? "border-2 border-yellow-500 " "border-none")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(let [mock-id (:id data)
has-changes? (refx/use-sub [:app.dashboard/mock-has-changes? mock-id])]
(d/div {:class (str "relative w-full h-full rounded-lg overflow-hidden m-2 "
(if has-changes? "border-2 border-yellow-500 "
"border-none "
))}
(let [mock-id (:id data)
has-changes? (refx/use-sub [:app.dashboard/mock-has-changes? mock-id])]
(d/div {:class (str "relative w-full h-full rounded-lg overflow-hidden m-2 "
(if has-changes? "border-2 border-yellow-500 " "border-none"))}

Comment on lines +122 to 130
(fn [{db :db} [_ response]]
(js/console.error "Save mock failed:", (clj->js response))
{:db (assoc db
:loading-edit-mock false
:loading-sync? false)
:notification {:type :error
:content (or (-> response :body :error :message)
"Failed to save mock")}}))

Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Ensure no sensitive data is logged
Logging errors is useful, but verify that response does not contain tokens or PII to avoid console exposure.

Comment on lines +349 to +360
(refx/reg-event-fx
:app.dashboard/verify-mock-repo
(fn [db [_ mock-id]]
{:notification {:type :error
:content "Mock has no linked repo"}
:http {:url "/repos"
:method :get
:headers {"authorization" (str "Bearer " (-> db :current-user :access-token))}
:on-success [:app.dashboard/save-repos]
:on-failure [:app.dashboard/save-mock-failed]}
:db (assoc db :curr-mock-id mock-id)}))

Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Inconsistent destructuring for reg-event-fx
Currently (fn [db [_ mock-id]] ...) is used, but other handlers destructure {db :db}. Consider adopting a consistent pattern for clarity.

Comment on lines +414 to +422
(refx/reg-event-fx
:app.dashboard/push-mock-failed
(fn [{db :db} [_ response]]
(js/console.error "Push failed:", (clj->js response))
{:db (assoc db :loading-push false)
:notification {:type :error
:content (or (-> response :body :message)
"Failed to push to GitHub")}}))

Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Ensure no sensitive info is printed
(js/console.error "Push failed:", ...) helps debugging, but confirm that it doesn’t expose tokens or PII in production logs.

Copy link

@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: 4

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 35290e1 and 94eb683.

📒 Files selected for processing (2)
  • src/back/api/ports/http_in.clj (8 hunks)
  • src/back/api/utils.clj (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/back/api/ports/http_in.clj (1)
Learnt from: Felipe-gsilva
PR: moclojer/moclojer-app#375
File: src/back/api/ports/http_in.clj:218-277
Timestamp: 2025-01-24T13:37:14.472Z
Learning: The webhook endpoint in moclojer-app verifies GitHub webhook signatures using the verify-webhook-signature interceptor from back.api.interceptors.verify-webhook, which uses clj-github-app.webhook-signature library.
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: WIP
🔇 Additional comments (12)
src/back/api/utils.clj (5)

1-3: LGTM!

The namespace declaration and imports are appropriate for the functionality provided.


5-11: Enhance docstring clarity.

The docstring could be more specific about what constitutes a valid value (truthy vs. falsy in Clojure).

-(defn assoc-if
-  "This function returns a map with a respective associated key and value 
-  if it is given as argument."
-  [m k v]
+(defn assoc-if
+  "Associates key k with value v in map m, only if v is not nil or false.
+   Returns the original map unchanged if v is nil or false."
+  [m k v]

13-18: Add input validation and error handling for decode function.

The function should handle edge cases and malformed input safely, especially important for webhook payloads.

 (defn decode
   "Decodes a given string from base64 format"
   [s]
-  (let [cleaned-str (str/replace s #"\s+" "")
-        decoder (java.util.Base64/getDecoder)]
-    (String. (.decode decoder cleaned-str) "UTF-8")))
+  (when (string? s)
+    (try
+      (let [cleaned-str (str/replace s #"\s+" "")
+            decoder (java.util.Base64/getDecoder)]
+        (String. (.decode decoder cleaned-str) "UTF-8"))
+      (catch IllegalArgumentException e
+        (throw (ex-info "Invalid base64 input" 
+                       {:type :validation-error 
+                        :cause (.getMessage e)})))
+      (catch Exception e
+        (throw (ex-info "Failed to decode base64" 
+                       {:type :decode-error 
+                        :cause (.getMessage e)}))))))

20-24: Add input validation and error handling for encode function.

Similar to decode, the function should handle edge cases safely.

 (defn encode
   "Encodes a given string into base64 format"
   [s]
-  (let [encoder (java.util.Base64/getEncoder)]
-    (.encodeToString encoder (.getBytes s "UTF-8"))))
+  (when (string? s)
+    (try
+      (let [encoder (java.util.Base64/getEncoder)]
+        (.encodeToString encoder (.getBytes s "UTF-8")))
+      (catch Exception e
+        (throw (ex-info "Failed to encode to base64" 
+                       {:type :encode-error 
+                        :cause (.getMessage e)}))))))

26-31: Optimize validation order and enhance docstring.

The validation checks can be reordered for better performance, and the docstring could be more descriptive.

 (defn sha256?
-  "Checks if the input string is a valid SHA-256 hash."
+  "Validates if the input is a valid SHA-256 hash string.
+   Returns true if the input is a 64-character string containing only hexadecimal digits (0-9, a-f, A-F)."
   [s]
-  (and (string? s)
-       (= 64 (count s))
-       (re-matches #"^[0-9a-fA-F]{64}$" s)))
+  (and (= 64 (count s))        ; fastest check first
+       (string? s)             ; type check second
+       (re-matches #"^[0-9a-fA-F]{64}$" s))) ; regex last
src/back/api/ports/http_in.clj (7)

2-15: All set with the new require statements.
These additions cleanly integrate the controllers and logic namespaces without obvious duplication or circular references.


26-31: No concerns with the extended parameters.
Allowing install-id in edit-user! appears consistent with broader sync logic.


45-45: Good retrieval approach for user data.
Passing {:database database} to get-user-by-id matches existing patterns.


66-68: Expanded function signature is cohesive.
Extracting parameters, session-data, and components in one map ensures easier maintenance.


235-238: Filtering approach is straightforward.
The filter-mocks helper is clear and helps isolate the logic for locating moclojer.yml files.


355-358: Remove debug print statement in production code.
Printing session data to stdout may leak sensitive data. This mirrors a previous comment about removing debug statements.


375-377: Robust parsing needed for owner/repo extraction.
When splitting git-repo, handle edge cases (extra slashes, missing scheme, trailing slash) to avoid partial or malformed splits. This duplicates earlier suggestions about making path parsing more reliable.

Comment on lines +33 to +38
(defn github-link?
"Checks if the input string correctly represents a github repo link"
[s]
(and (string? s)
(not-empty s)
(str/starts-with? s "https://github.com/")))
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Enhance GitHub repository link validation.

The current validation is basic and might miss edge cases. Consider using a more specific regex pattern to validate repository names.

 (defn github-link?
   "Checks if the input string correctly represents a github repo link"
   [s]
   (and (string? s)
        (not-empty s)
-       (str/starts-with? s "https://github.com/")))
+       (re-matches #"^https://github\.com/[a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38}/[a-zA-Z0-9_.-]+$" s)))

This regex pattern ensures:

  • Valid GitHub username format (39 chars max, alphanumeric with single hyphens between)
  • Valid repository name format (alphanumeric with underscores, dots, and hyphens)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(defn github-link?
"Checks if the input string correctly represents a github repo link"
[s]
(and (string? s)
(not-empty s)
(str/starts-with? s "https://github.com/")))
(defn github-link?
"Checks if the input string correctly represents a github repo link"
[s]
(and (string? s)
(not-empty s)
(re-matches #"^https://github\.com/[a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38}/[a-zA-Z0-9_.-]+$" s)))

Comment on lines +143 to +157
(defn handler-get-mock-by-id
[{:keys [parameters session-data components ctx]}]
(let [id (-> parameters :path :id)
user (controllers.user/get-user-by-id
(:user-id session-data) components ctx)
mocks (controllers.mocks/get-mocks user components ctx)
mock (->> mocks
(mapcat :apis)
(filter #(= (str (:id %)) id))
first)]
(if mock
{:status 200
:body {:mock mock}}
{:status 404
:body {:error "Mock not found"}})))
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Potential performance concern for large datasets.
Collecting all mocks and filtering in memory (mapcat :apis) may become costly if the user has a large number of mocks. If performance is impacted, consider an indexed or direct query approach.

Comment on lines +239 to +342
install-id (get-in body [:installation :id])]
(logs/log :info "Webhook received"
:ctx (assoc ctx :event-type event-type))
(cond
(nil? install-id)
{:status 401
:body {:message "Forbidden"}}
(= event-type "push")
(let [repo (:repository body)
commits (:commits body)
git-slug (get-in repo [:owner :name])
repo-name (:name repo)
org (controllers.orgs/get-by-git-orgname git-slug components ctx)
user (controllers.user/get-by-git-username git-slug components ctx)
id (or (parse-uuid (:id org)) (parse-uuid (:uuid user)))
slug (or (:orgname org) (:username user))]
(logs/log :info "Processing Push Event"
:ctx (assoc ctx
:id id
:repo repo-name))

(if-not id
{:status 404
:body {:message "User and org not found"}}
(let [user-mocks (controllers.mocks/get-mocks {:uuid id :username slug} components ctx)
mocks (filter-mocks (->> commits
(mapcat #(vals (select-keys % [:added :modified])))
(apply concat)
vec))
source-files (when mocks (controllers.sync/pull! install-id git-slug repo-name mocks components ctx))]
(when (seq source-files)
(logs/log :info "Processing modified mocks"
:ctx (assoc ctx
:mocks mocks
:user-mocks user-mocks
:modified-count (count source-files)))
(doseq [mock source-files
:let [content (utils/decode (get-in mock [:content :content]))
sha (get-in mock [:content :sha])
;; "resources/mocks/moclojer-test/moclojer.yml" ==> moclojer-test
wildcard (-> (:file mock)
(str/split #"/")
(as-> e (take-last 2 e))
(first))
existing-mock (when user-mocks
(first (filter #(= (:wildcard %) wildcard)
(->> user-mocks
first
:apis
(map #(select-keys % [:wildcard :id]))))))]]
(if (seq existing-mock)
(if-let [mock-id (:id existing-mock)]
(try
(controllers.mocks/update-mock! mock-id
{:content content
:git-repo (:url repo)
:sha sha}
components ctx)
(catch Exception e
(logs/log :error "Failed to update mock"
:ctx (assoc ctx :error (.getMessage e) :mock-id mock-id))
{:status 500
:body {:message (.getMessage e)}}))
(logs/log :error "Mock found but has no ID"
:ctx (assoc ctx :wildcard wildcard)))
(try
(controllers.mocks/create-mock!
id
(logic.mocks/create {:content content
:sha sha
:wildcard wildcard
:subdomain slug
:enabled true
:git-repo (:url repo)})
components ctx)
(catch Exception e
(logs/log :error "Failed to create mock"
:ctx (assoc ctx :error (.getMessage e)))
{:status 500
:body {:message (.getMessage e)}})))))
{:status 200
:body {:message "Files updated from source"}})))
(#{"installation" "installation_repositories"} event-type)
(let [sender-type (get-in body [:installation :account :type])
git-slug (get-in body [:installation :account :login])
org (when (= sender-type "Organization") (controllers.orgs/get-by-git-orgname git-slug components ctx))
user (when (= sender-type "User") (controllers.user/get-by-git-username git-slug components ctx))
id (or (parse-uuid (:id org)) (parse-uuid (:uuid user)))]
(logs/log :info "Processing Installation Event"
:ctx (assoc ctx :id id))
(if-not (nil? (or (:id org) (:uuid user)))
{:status 200
:body {:message "Enabled Git Sync"
:content (if org
(controllers.orgs/enable-sync install-id id components ctx)
(controllers.user/enable-sync install-id id components ctx))}}
{:status 404
:body {:message "no org or user found"}}))
:else {:status 400
:body {:message "Unhandled event type"}})))
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Consider extracting logic from this large handler-webhook for maintainability.
Processing installation events, push events, and file updates in one function can be broken down into smaller, focused functions (e.g., handle-push-event, handle-installation-event). This reduces complexity and clarifies the flow.

Comment on lines +73 to 83
git-path (:git-repo old-mock)
git-repo (when git-path (last (str/split git-path #"/")))
new-mock (controllers.mocks/update-mock! (parse-uuid (str id))
(-> {}
(utils/assoc-if :content content)
(cond->
(utils/sha256? sha) (utils/assoc-if :sha sha)
(utils/github-link? git-repo) (utils/assoc-if :git-repo git-path)))
components
ctx)]
{:status 200
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Potential mismatch in GitHub link check and missing UUID error handling.

  1. You are only retaining the last path segment in git-repo (line 74) but using (utils/github-link? git-repo) for the conditional check (line 80). This likely yields false for valid GitHub URLs since git-repo is no longer the full link. Instead, consider:
-        git-repo (when git-path (last (str/split git-path #"/")))
-        ...
-        (cond->
-          (utils/sha256? sha) (utils/assoc-if :sha sha)
-          (utils/github-link? git-repo) (utils/assoc-if :git-repo git-path))
+        repo-name (when git-path (last (str/split git-path #"/")))
+        ...
+        (cond->
+          (utils/sha256? sha) (utils/assoc-if :sha sha)
+          (utils/github-link? git-path) (utils/assoc-if :git-repo git-path))
  1. (parse-uuid (str id)) can throw an exception if id is invalid. Consider safe parsing or returning a clear error.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
git-path (:git-repo old-mock)
git-repo (when git-path (last (str/split git-path #"/")))
new-mock (controllers.mocks/update-mock! (parse-uuid (str id))
(-> {}
(utils/assoc-if :content content)
(cond->
(utils/sha256? sha) (utils/assoc-if :sha sha)
(utils/github-link? git-repo) (utils/assoc-if :git-repo git-path)))
components
ctx)]
{:status 200
git-path (:git-repo old-mock)
repo-name (when git-path (last (str/split git-path #"/")))
new-mock (controllers.mocks/update-mock! (parse-uuid (str id))
(-> {}
(utils/assoc-if :content content)
(cond->
(utils/sha256? sha) (utils/assoc-if :sha sha)
(utils/github-link? git-path) (utils/assoc-if :git-repo git-path)))
components
ctx)]
{:status 200

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:app :back :enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

icon on tab not appearing feature: signin e signup pelo github feature: sync em repositório git
2 participants