Skip to content

Support creating repositories under organizations during init#656

Merged
guysmoilov merged 4 commits intomainfrom
claude/fix-dagshub-org-creation-PCBI9
Feb 23, 2026
Merged

Support creating repositories under organizations during init#656
guysmoilov merged 4 commits intomainfrom
claude/fix-dagshub-org-creation-PCBI9

Conversation

@guysmoilov
Copy link
Member

@guysmoilov guysmoilov commented Feb 23, 2026

Summary

Enhanced the repository initialization logic to support creating repositories under organizations when a repo_owner is specified, rather than always creating under the current user.

Key Changes

  • Added logic to fetch the current user information when a repository doesn't exist
  • Implemented conditional repository creation:
    • If repo_owner is specified and differs from the current user, create the repository under the specified organization
    • Otherwise, create the repository under the current user (existing behavior)
  • Updated log messages to reflect whether the repository is being created under an organization or the current user
  • Added host parameter to create_repo() calls to ensure consistency with the API host

Implementation Details

  • Uses UserAPI.get_current_user() to retrieve the current user's information for comparison
  • Passes org_name=repo_owner parameter to create_repo() when creating under an organization
  • Maintains backward compatibility by preserving the original behavior when no repo_owner is specified or when it matches the current user

https://claude.ai/code/session_01DaAdy77PhB4KNXRzuQ3FhD

Implementation Details

Updated dagshub/common/init.py to make repository creation organization-aware when a repository is missing:

  • When RepoAPI.get_repo_info() raises RepoNotFoundError:
    • Calls UserAPI.get_current_user(host=host) to obtain the current username.
    • If repo_owner is provided and differs from the current user, logs creation under the organization and calls create_repo(repo_name, org_name=repo_owner, host=host).
    • If repo_owner matches the current user or is not provided, logs creation under the current user and calls create_repo(repo_name, host=host).
  • All create_repo calls now forward host to ensure consistency with the API host.
  • Log messages were adjusted to indicate whether creation is under an organization or the current user.
  • No behavioral change when repo_owner is omitted or equals the current user.

Tests added (tests/common/test_init.py):

  • test_init_creates_repo_under_org_when_owner_differs: verifies organization creation path, create_repo args, and logging.
  • test_init_creates_repo_under_current_user_when_owner_matches: verifies user creation path, create_repo args, and logging.
  • test_init_creates_repo_under_current_user_from_url: verifies creation when repo is derived from URL.

Supporting changes (unchanged behavior elsewhere):

  • dagshub/upload/wrapper.create_repo already accepts org_name and host; init.py now uses those parameters.
  • .gitignore updated to ignore "*.iml".

Files modified:

  • dagshub/common/init.py: conditional org-aware repo creation, host forwarding to create_repo (+13/-2 as in PR metadata).
  • tests/common/test_init.py: new unit tests (+70/-0).
  • .gitignore: added "*.iml" (+1/-0).

When dagshub.init(repo_owner='org', repo_name='repo') is called and the
repo doesn't exist, it now compares repo_owner against the current user's
username. If they differ, the repo is created under the org via the org
API endpoint. Previously it always created repos under the calling user,
ignoring the repo_owner parameter entirely.

Also forwards the host parameter to create_repo() for correctness.

https://claude.ai/code/session_01DaAdy77PhB4KNXRzuQ3FhD
@dagshub
Copy link

dagshub bot commented Feb 23, 2026

@guysmoilov guysmoilov requested a review from Copilot February 23, 2026 10:00
@coderabbitai
Copy link

coderabbitai bot commented Feb 23, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The pull request enhances repository creation logic to support both user-owned and organization-owned repositories. When a repository is not found, the code now queries the current user and branches the creation path based on whether the repo_owner differs from the current user, with appropriate parameters passed to the repository creation function.

Changes

Cohort / File(s) Summary
Repository creation logic
dagshub/common/init.py, dagshub/upload
Added branching logic to distinguish between creating repositories under the current user versus an organization. The create_repo method signature now accepts org_name and host parameters. When a repository is not found, the code fetches the current user, compares with repo_owner, and calls create_repo with appropriate arguments based on this comparison.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/fix-dagshub-org-creation-PCBI9

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

@guysmoilov guysmoilov self-assigned this Feb 23, 2026
@guysmoilov guysmoilov added the bug Something isn't working label Feb 23, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request enhances the repository initialization functionality to support creating repositories under organizations when a repo_owner is specified that differs from the current user. Previously, repositories were always created under the current user's account.

Changes:

  • Added logic to fetch current user information and compare with repo_owner to determine creation context
  • Implemented conditional repository creation under organizations vs. current user
  • Added host parameter to create_repo() calls for consistency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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.

Caution

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

⚠️ Outside diff range comments (1)
dagshub/common/init.py (1)

110-110: ⚠️ Potential issue | 🟡 Minor

Missing host parameter in get_user_from_token call.

Line 91 correctly passes host to get_current_user(host=host), but line 110 omits it. For consistency and to ensure the correct host is used (especially with non-default hosts), pass host here as well.

🔧 Proposed fix
-        os.environ["MLFLOW_TRACKING_USERNAME"] = UserAPI.get_user_from_token(token).username
+        os.environ["MLFLOW_TRACKING_USERNAME"] = UserAPI.get_user_from_token(token, host=host).username
🧹 Nitpick comments (3)
dagshub/common/init.py (1)

90-102: The else branch (lines 100-102) appears unreachable.

By the time this code executes, repo_owner is always set:

  • If provided explicitly with repo_name, both are used (line 71-72)
  • If derived from URL, it's extracted from path parts (line 83)

The condition if repo_owner: at line 90 will always be true, making lines 100-102 dead code.

Additionally, lines 98-99 and 101-102 are duplicates—consider consolidating them.

♻️ Suggested simplification
     except RepoNotFoundError:
-        if repo_owner:
-            current_user = UserAPI.get_current_user(host=host)
-            if repo_owner != current_user.username:
-                log_message(
-                    f'Repository {repo_name} doesn\'t exist, creating it under organization "{repo_owner}".'
-                )
-                create_repo(repo_name, org_name=repo_owner, host=host)
-            else:
-                log_message(f"Repository {repo_name} doesn't exist, creating it under current user.")
-                create_repo(repo_name, host=host)
+        current_user = UserAPI.get_current_user(host=host)
+        if repo_owner != current_user.username:
+            log_message(
+                f'Repository {repo_name} doesn\'t exist, creating it under organization "{repo_owner}".'
+            )
+            create_repo(repo_name, org_name=repo_owner, host=host)
         else:
             log_message(f"Repository {repo_name} doesn't exist, creating it under current user.")
             create_repo(repo_name, host=host)
tests/common/test_init.py (2)

65-70: Test assertions appear incomplete.

This test verifies create_repo is called correctly when using a URL, but it's missing assertions that the other tests have:

  1. No mock_user_api.get_current_user.assert_called_once() assertion
  2. No mock_log_message.assert_any_call(...) assertion

Since the URL extracts repo_owner="testuser" which matches the mocked user, this should follow the "current user" path and those assertions would validate the behavior.

💡 Suggested additional assertions
 def test_init_creates_repo_under_current_user_from_url(
     mock_repo_api, mock_user_api, mock_create_repo, mock_get_token, mock_log_message
 ):
     dagshub.init(url="https://dagshub.com/testuser/my-repo", mlflow=False, dvc=False)
 
+    mock_user_api.get_current_user.assert_called_once()
     mock_create_repo.assert_called_once_with("my-repo", host="https://dagshub.com")
+    mock_log_message.assert_any_call(
+        "Repository my-repo doesn't exist, creating it under current user."
+    )

41-70: Consider adding a test for org creation via URL.

The tests cover owner/name args and URL with matching user, but there's no test for creating a repo under an org when using a URL (e.g., url="https://dagshub.com/my-org/my-repo" where my-org differs from current user). This would ensure the org creation path works correctly with URL input.


ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a25fa99 and c81d50d.

📒 Files selected for processing (3)
  • .gitignore
  • dagshub/common/init.py
  • tests/common/test_init.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: build (3.11)
  • GitHub Check: build (3.13)
  • GitHub Check: build (3.12)
  • GitHub Check: build (3.9)
  • GitHub Check: build (3.10)
🧰 Additional context used
🧬 Code graph analysis (2)
tests/common/test_init.py (3)
dagshub/common/api/repo.py (2)
  • RepoNotFoundError (43-44)
  • get_repo_info (96-109)
dagshub/common/api/user.py (3)
  • username (68-69)
  • get_current_user (64-65)
  • get_user_from_token (37-61)
dagshub/common/init.py (1)
  • init (23-151)
dagshub/common/init.py (2)
dagshub/common/api/user.py (3)
  • UserAPI (21-88)
  • get_current_user (64-65)
  • username (68-69)
dagshub/common/helpers.py (1)
  • log_message (100-107)
🪛 Ruff (0.15.1)
tests/common/test_init.py

[warning] 42-42: Unused function argument: mock_repo_api

(ARG001)


[warning] 42-42: Unused function argument: mock_get_token

(ARG001)


[warning] 54-54: Unused function argument: mock_repo_api

(ARG001)


[warning] 54-54: Unused function argument: mock_get_token

(ARG001)


[warning] 66-66: Unused function argument: mock_repo_api

(ARG001)


[warning] 66-66: Unused function argument: mock_user_api

(ARG001)


[warning] 66-66: Unused function argument: mock_get_token

(ARG001)


[warning] 66-66: Unused function argument: mock_log_message

(ARG001)

🔇 Additional comments (4)
.gitignore (1)

129-129: LGTM!

Adding *.iml to the IntelliJ section is appropriate—these are IDE-specific module files that should not be tracked.

tests/common/test_init.py (3)

9-38: LGTM on fixtures.

The fixtures correctly mock the dependencies needed for testing the init function. The unused argument warnings from static analysis are false positives—these fixtures are required to activate the patches even if not directly referenced in test bodies.


41-50: LGTM!

This test correctly verifies that when repo_owner differs from the current user, the repository is created under the organization with the appropriate parameters and log message.


53-62: LGTM!

This test correctly verifies that when repo_owner matches the current user, the repository is created under the user (without org_name) and logs the appropriate message.

@guysmoilov guysmoilov requested a review from kbolashev February 23, 2026 11:47
Copy link
Member

@kbolashev kbolashev left a comment

Choose a reason for hiding this comment

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

LGTM!

Actual bug report, from messages:

dagshub.init(owner_name='bla', repo_name='foo') always creates the repo as owned by the calling user, doesn't attempt to create it under the bla org or verify that it actually is an org and that the user can create repos under it, etc.

@guysmoilov guysmoilov merged commit 6608369 into main Feb 23, 2026
9 checks passed
@guysmoilov guysmoilov deleted the claude/fix-dagshub-org-creation-PCBI9 branch February 23, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants