mirror of
https://github.com/openSUSE/osc.git
synced 2025-08-01 21:23:39 +02:00
Allow git in git-obs to be switched from SSH to http(s)
This commit is contained in:
@@ -25,3 +25,37 @@ Scenario: Clone a git repo
|
||||
|
||||
Total cloned repos: 1
|
||||
"""
|
||||
|
||||
|
||||
@destructive
|
||||
Scenario: Clone a git repo via http
|
||||
Given I execute git-obs with args "api -X PATCH /repos/pool/test-GitPkgA/ --data '{{"private": true}}'"
|
||||
And stdout contains ""private": true"
|
||||
And I execute git-obs with args "login update admin --new-git-uses-http=1 --new-ssh-key="
|
||||
When I set env "GIT_TERMINAL_PROMPT" to "0"
|
||||
And I execute git-obs with args "repo clone pool/test-GitPkgA --no-ssh-strict-host-key-checking"
|
||||
Then the exit code is 1
|
||||
Given I create file "{context.osc.temp}/gitconfig" with perms "0644"
|
||||
"""
|
||||
[credential "http://localhost:{context.podman.container.ports[gitea_http]}"]
|
||||
helper = "{context.git_obs.cmd} -G admin login gitcredentials-helper"
|
||||
"""
|
||||
And I set env "GIT_CONFIG_GLOBAL" to "{context.osc.temp}/gitconfig"
|
||||
When I execute git-obs with args "repo clone pool/test-GitPkgA --no-ssh-strict-host-key-checking"
|
||||
Then the exit code is 0
|
||||
And stdout is
|
||||
"""
|
||||
"""
|
||||
And stderr is
|
||||
"""
|
||||
Using the following Gitea settings:
|
||||
* Config path: {context.git_obs.config}
|
||||
* Login (name of the entry in the config file): admin
|
||||
* URL: http://localhost:{context.podman.container.ports[gitea_http]}
|
||||
* User: Admin
|
||||
|
||||
Cloning git repo pool/test-GitPkgA ...
|
||||
Cloning into 'test-GitPkgA'...
|
||||
|
||||
Total cloned repos: 1
|
||||
"""
|
||||
|
@@ -65,6 +65,22 @@ Use one of the following commands to upload your public SSH key to the Gitea ser
|
||||
git-obs ssh-key add --key-path PUBLIC_KEY_PATH
|
||||
|
||||
|
||||
Using git with token auth instead of SSH keys
|
||||
=============================================
|
||||
|
||||
It is possible to use Gitea token for both communicating with the Gitea API
|
||||
and also for authenticating the git command.
|
||||
|
||||
|
||||
To use token auth for git operations, switch git from using SSH to http(s)::
|
||||
|
||||
git-obs login update <login> --new-git-uses-http=1
|
||||
|
||||
and add the following entry to ~/.config/git/config or ~/.gitconfig::
|
||||
|
||||
[credential "https://src.example.com"]
|
||||
helper = "git-obs -G <login> login gitcredentials-helper"
|
||||
|
||||
|
||||
Workflow: Making changes to packages
|
||||
====================================
|
||||
|
@@ -21,6 +21,7 @@ class LoginAddCommand(osc.commandline_git.GitObsCommand):
|
||||
self.parser.add_argument("--user", help="Gitea username", required=True)
|
||||
self.parser.add_argument("--token", help="Gitea access token; omit or set to '-' to invoke a secure interactive prompt")
|
||||
self.parser.add_argument("--ssh-key", metavar="PATH", help="Path to a private SSH key").completer = complete_ssh_key_path
|
||||
self.parser.add_argument("--git-uses-http", action="store_true", help="Git uses http(s) instead of SSH", default=None)
|
||||
self.parser.add_argument("--set-as-default", help="Set the new login entry as default", action="store_true", default=None)
|
||||
|
||||
def run(self, args):
|
||||
@@ -44,6 +45,7 @@ class LoginAddCommand(osc.commandline_git.GitObsCommand):
|
||||
user=args.user,
|
||||
token=args.token,
|
||||
ssh_key=args.ssh_key,
|
||||
git_uses_http=args.git_uses_http,
|
||||
default=args.set_as_default,
|
||||
)
|
||||
self.gitea_conf.add_login(login_obj)
|
||||
|
32
osc/commands_git/login_gitcredentials_helper.py
Normal file
32
osc/commands_git/login_gitcredentials_helper.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import osc.commandline_git
|
||||
|
||||
|
||||
class LoginGitcredentialsHelperCommand(osc.commandline_git.GitObsCommand):
|
||||
"""
|
||||
A gitcredentials helper
|
||||
|
||||
To use token auth for git operations, switch git from using SSH to http(s):
|
||||
git-obs login update <login> --new-git-uses-http=1
|
||||
|
||||
and add the following entry to .gitconfig:
|
||||
[credential "https://src.example.com"]
|
||||
helper = "git-obs -G <login> login gitcredentials-helper"
|
||||
"""
|
||||
|
||||
name = "gitcredentials-helper"
|
||||
parent = "LoginCommand"
|
||||
hidden = True
|
||||
|
||||
def init_arguments(self):
|
||||
self.parser.add_argument(
|
||||
"operation",
|
||||
# see gitcredentials(7) for more details
|
||||
choices=["get", "store", "erase"],
|
||||
)
|
||||
|
||||
def run(self, args):
|
||||
import shlex
|
||||
|
||||
if args.operation == "get":
|
||||
print(f"username={shlex.quote(self.gitea_login.user)}")
|
||||
print(f"password={shlex.quote(self.gitea_login.token)}")
|
@@ -22,6 +22,7 @@ class LoginUpdateCommand(osc.commandline_git.GitObsCommand):
|
||||
self.parser.add_argument("--new-user", metavar="USER", help="Gitea username")
|
||||
self.parser.add_argument("--new-token", metavar="TOKEN", help="Gitea access token; set to '-' to invoke a secure interactive prompt")
|
||||
self.parser.add_argument("--new-ssh-key", metavar="PATH", help="Path to a private SSH key").completer = complete_ssh_key_path
|
||||
self.parser.add_argument("--new-git-uses-http", help="Git uses http(s) instead of SSH", choices=["0", "1", "yes", "no"], default=None)
|
||||
self.parser.add_argument("--set-as-default", action="store_true", help="Set the login entry as default")
|
||||
|
||||
def run(self, args):
|
||||
@@ -43,6 +44,13 @@ class LoginUpdateCommand(osc.commandline_git.GitObsCommand):
|
||||
if args.new_token and not re.match(r"^[0-9a-f]{40}$", args.new_token):
|
||||
self.parser.error("Invalid token format, 40 hexadecimal characters expected")
|
||||
|
||||
if args.new_git_uses_http in ("0", "no"):
|
||||
new_git_uses_http = False
|
||||
elif args.new_git_uses_http in ("1", "yes"):
|
||||
new_git_uses_http = True
|
||||
else:
|
||||
new_git_uses_http = None
|
||||
|
||||
updated_login_obj = self.gitea_conf.update_login(
|
||||
args.name,
|
||||
new_name=args.new_name,
|
||||
@@ -50,6 +58,7 @@ class LoginUpdateCommand(osc.commandline_git.GitObsCommand):
|
||||
new_user=args.new_user,
|
||||
new_token=args.new_token,
|
||||
new_ssh_key=args.new_ssh_key,
|
||||
new_git_uses_http=new_git_uses_http,
|
||||
set_as_default=args.set_as_default,
|
||||
)
|
||||
print("")
|
||||
|
@@ -64,7 +64,7 @@ class RepoCloneCommand(osc.commandline_git.GitObsCommand):
|
||||
owner,
|
||||
repo,
|
||||
directory=args.directory,
|
||||
use_http=args.anonymous,
|
||||
use_http=args.anonymous or self.gitea_login.git_uses_http,
|
||||
add_remotes=True,
|
||||
ssh_private_key_path=args.ssh_key or self.gitea_login.ssh_key,
|
||||
ssh_strict_host_key_checking=not(args.no_ssh_strict_host_key_checking),
|
||||
|
@@ -21,6 +21,7 @@ class Login(BaseModel):
|
||||
user: str = Field() # type: ignore[assignment]
|
||||
token: str = Field() # type: ignore[assignment]
|
||||
ssh_key: Optional[str] = Field() # type: ignore[assignment]
|
||||
git_uses_http: Optional[bool] = Field() # type: ignore[assignment]
|
||||
default: Optional[bool] = Field() # type: ignore[assignment]
|
||||
|
||||
class AlreadyExists(oscerr.OscBaseError):
|
||||
@@ -67,6 +68,8 @@ class Login(BaseModel):
|
||||
table.add("User", self.user)
|
||||
if self.ssh_key:
|
||||
table.add("Private SSH key path", self.ssh_key)
|
||||
if self.git_uses_http:
|
||||
table.add("Git uses http(s)", "yes" if self.git_uses_http else "no")
|
||||
if show_token:
|
||||
# tokens are stored in the plain text, there's not reason to protect them too much
|
||||
# let's only hide them from the output by default
|
||||
@@ -217,6 +220,7 @@ class Config:
|
||||
new_user: Optional[str] = None,
|
||||
new_token: Optional[str] = None,
|
||||
new_ssh_key: Optional[str] = None,
|
||||
new_git_uses_http: Optional[bool] = None,
|
||||
set_as_default: Optional[bool] = None,
|
||||
) -> Login:
|
||||
login = self.get_login(name)
|
||||
@@ -231,6 +235,16 @@ class Config:
|
||||
login.token = new_token
|
||||
if new_ssh_key is not None:
|
||||
login.ssh_key = new_ssh_key
|
||||
|
||||
if new_git_uses_http is None:
|
||||
# keep the original value
|
||||
pass
|
||||
elif new_git_uses_http:
|
||||
login.git_uses_http = True
|
||||
else:
|
||||
# remove from the config instead of setting to False
|
||||
login.git_uses_http = None
|
||||
|
||||
if set_as_default:
|
||||
login.default = True
|
||||
|
||||
@@ -241,6 +255,11 @@ class Config:
|
||||
for entry in data["logins"]:
|
||||
if entry.get("name", None) == name:
|
||||
entry.update(login.dict())
|
||||
|
||||
# remove keys with no value
|
||||
for key, value in entry.copy().items():
|
||||
if value is None:
|
||||
del entry[key]
|
||||
else:
|
||||
if set_as_default:
|
||||
entry.pop("default", None)
|
||||
|
Reference in New Issue
Block a user