Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions cli/dstack/_internal/api/repos.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
from pathlib import Path
from typing import Optional

import git
Expand Down Expand Up @@ -50,15 +51,20 @@ def get_local_repo_credentials(
repo_data, RepoProtocol.SSH, identity_file=identity_file
)
except GitCommandError:
pass
url = repo_data.make_url(RepoProtocol.SSH)
raise InvalidRepoCredentialsError(
f"Can't access `{url}` using the `{identity_file}` private SSH key"
)

if oauth_token is not None:
try: # user provided oauth token
return test_remote_repo_credentials(
repo_data, RepoProtocol.HTTPS, oauth_token=oauth_token
)
except GitCommandError:
pass
url = repo_data.make_url(RepoProtocol.SSH, oauth_token)
masked = len(oauth_token[:-4]) * "*" + oauth_token[-4:]
raise InvalidRepoCredentialsError(f"Can't access `{url}` using the `{masked}` token")

identities = get_host_config(original_hostname or repo_data.repo_host_name).get("identityfile")
if identities: # must fail if key is invalid
Expand All @@ -67,7 +73,10 @@ def get_local_repo_credentials(
repo_data, RepoProtocol.SSH, identity_file=identities[0]
)
except GitCommandError:
pass
url = repo_data.make_url(RepoProtocol.SSH, oauth_token)
raise InvalidRepoCredentialsError(
f"Can't access `{url}` using the `{identities[0]}` SSH private key"
)

if os.path.exists(gh_config_path):
with open(gh_config_path, "r") as f:
Expand All @@ -89,6 +98,10 @@ def get_local_repo_credentials(
except GitCommandError:
pass

raise InvalidRepoCredentialsError(
"No valid default Git credentials found: ensure passing a valid `--token` or `--git-identity` to `dstack init`."
)


def test_remote_repo_credentials(
repo_data: RemoteRepoData,
Expand All @@ -102,9 +115,13 @@ def test_remote_repo_credentials(
git.cmd.Git().ls_remote(url, env=dict(GIT_TERMINAL_PROMPT="0"))
return RemoteRepoCredentials(protocol=protocol, oauth_token=oauth_token, private_key=None)
elif protocol == RepoProtocol.SSH:
if not Path(identity_file).exists():
raise InvalidRepoCredentialsError(f"The {identity_file} private SSH key doesn't exist")
if not os.access(identity_file, os.R_OK):
raise InvalidRepoCredentialsError(f"Can't access the {identity_file} private SSH key")
if not try_ssh_key_passphrase(identity_file):
raise InvalidRepoCredentialsError(
f"Repo SSH key must be passphrase-less: {identity_file}"
f"Can't access `{url}`: the {identity_file} private SSH key must passphrase-less"
)
with open(identity_file, "r") as f:
private_key = f.read()
Expand Down
3 changes: 2 additions & 1 deletion cli/dstack/_internal/cli/commands/init/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from argparse import Namespace
from pathlib import Path
from typing import Optional
Expand Down Expand Up @@ -56,7 +57,7 @@ def _command(self, args: Namespace):
try:
repo_credentials = get_local_repo_credentials(
repo_data=repo.repo_data,
identity_file=args.git_identity_file,
identity_file=os.path.expanduser(args.git_identity_file),
oauth_token=args.gh_token,
original_hostname=giturlparse.parse(repo.repo_url).resource,
)
Expand Down