Cred helper: load token, token support. RepoTool: timeout
Signed-off-by: Václav Valíček <valicek1994@gmail.com>
This commit is contained in:
parent
de67130fd5
commit
b3b9fbf0c8
|
@ -1,5 +1,5 @@
|
||||||
from .checksum import gen_repo_hashed_name
|
from .checksum import gen_repo_hashed_name
|
||||||
from .cred_helper import prepare_git_auth
|
from .cred_helper import prepare_git_auth, init_gh_token
|
||||||
from .cloner_config import ClonerConfig, ClonerConfigParser
|
from .cloner_config import ClonerConfig, ClonerConfigParser
|
||||||
from .config_file_not_found_error import ConfigFileNotFoundError
|
from .config_file_not_found_error import ConfigFileNotFoundError
|
||||||
from .default_cloner_config import DefaultClonerConfig
|
from .default_cloner_config import DefaultClonerConfig
|
||||||
|
|
|
@ -1,9 +1,40 @@
|
||||||
from git import Repo, GitConfigParser
|
from git import Repo, GitConfigParser
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
from typing import Optional, List
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
log = logging.getLogger("rc.cfghelper")
|
log = logging.getLogger("rc.cfghelper")
|
||||||
|
|
||||||
|
token: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
def gen_gh_token_candidates() -> List[Path]:
|
||||||
|
return [
|
||||||
|
Path(os.getcwd()).joinpath(".gh-token"),
|
||||||
|
Path(os.getenv("HOME")).joinpath(".config", "gh-token"),
|
||||||
|
Path("/etc").joinpath("cloner-gh-token"),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def init_gh_token():
|
||||||
|
for candidate in gen_gh_token_candidates():
|
||||||
|
log.debug(f"Loading gh-candidate candidate {candidate.as_posix()}")
|
||||||
|
load_gh_token(candidate)
|
||||||
|
if token:
|
||||||
|
log.info(f"Token succesfully loaded")
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
|
def load_gh_token(path: Path):
|
||||||
|
global token
|
||||||
|
log.info(f"Loading secret github token")
|
||||||
|
if not path.is_file():
|
||||||
|
log.warning(f"Token load did not pass - file not found")
|
||||||
|
return
|
||||||
|
# load token
|
||||||
|
token = path.read_text().strip()
|
||||||
|
|
||||||
|
|
||||||
def config_try_override(config_writer: GitConfigParser, section: str, option: str, value: str):
|
def config_try_override(config_writer: GitConfigParser, section: str, option: str, value: str):
|
||||||
if section not in config_writer.sections():
|
if section not in config_writer.sections():
|
||||||
|
@ -32,8 +63,20 @@ def prepare_git_auth(repo: str, config_dir):
|
||||||
ssh_identity: str = os.path.join(config_dir, "ssh", "identity")
|
ssh_identity: str = os.path.join(config_dir, "ssh", "identity")
|
||||||
|
|
||||||
with repo.config_writer("user") as cfgw:
|
with repo.config_writer("user") as cfgw:
|
||||||
|
# github personal token
|
||||||
|
# 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
|
||||||
|
if token:
|
||||||
|
config_try_override(
|
||||||
|
cfgw,
|
||||||
|
f"url \"https://{token}:x-oauth-basic@github.com/\"",
|
||||||
|
"insteadOf",
|
||||||
|
"https://github.com/"
|
||||||
|
)
|
||||||
|
|
||||||
|
# https credential store
|
||||||
log.debug(f"Writing credential store setting")
|
log.debug(f"Writing credential store setting")
|
||||||
config_try_override(cfgw, "credential", "helper", f"store --file={cred_store}")
|
config_try_override(cfgw, "credential", "helper", f"store --file={cred_store}")
|
||||||
|
# ssh key
|
||||||
log.debug(f"Writing SSH cert path")
|
log.debug(f"Writing SSH cert path")
|
||||||
config_try_override(
|
config_try_override(
|
||||||
cfgw,
|
cfgw,
|
||||||
|
|
|
@ -194,7 +194,7 @@ class RepoTool:
|
||||||
self._last_fetch_data = remote.fetch(
|
self._last_fetch_data = remote.fetch(
|
||||||
["+refs/heads/*:refs/heads/*", "+refs/tags/*:refs/tags/*"],
|
["+refs/heads/*:refs/heads/*", "+refs/tags/*:refs/tags/*"],
|
||||||
progress = GitRemoteProgress(),
|
progress = GitRemoteProgress(),
|
||||||
kill_after_timeout = 60,
|
kill_after_timeout = 600,
|
||||||
prune = True
|
prune = True
|
||||||
)
|
)
|
||||||
log.debug("Fetch finished!")
|
log.debug("Fetch finished!")
|
||||||
|
|
102
tests/lib/test_cred_helper.py
Normal file
102
tests/lib/test_cred_helper.py
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
import pytest
|
||||||
|
from repo_cloner.lib.cred_helper import *
|
||||||
|
from repo_cloner.lib import cred_helper
|
||||||
|
import os
|
||||||
|
from unittest.mock import MagicMock, patch
|
||||||
|
from cloner_test_fixtures import path_repo_base, support_data_path
|
||||||
|
from git import Repo
|
||||||
|
|
||||||
|
|
||||||
|
def test_gen_gh_token_candidates(monkeypatch):
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setenv("HOME", "/mocked/home")
|
||||||
|
candidates = gen_gh_token_candidates()
|
||||||
|
assert candidates[0].as_posix() == os.path.join(os.getcwd(), ".gh-token")
|
||||||
|
assert candidates[1].as_posix() == "/mocked/home/.config/gh-token"
|
||||||
|
assert candidates[2].as_posix() == "/etc/cloner-gh-token"
|
||||||
|
assert len(candidates) == 3
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_gh_token(tmp_path):
|
||||||
|
# no token
|
||||||
|
token_file = tmp_path.joinpath("gh-token")
|
||||||
|
load_gh_token(token_file)
|
||||||
|
assert cred_helper.token is None
|
||||||
|
|
||||||
|
token_file.write_text("test-token\n")
|
||||||
|
load_gh_token(token_file)
|
||||||
|
assert cred_helper.token == "test-token"
|
||||||
|
|
||||||
|
|
||||||
|
def test_init_gh_token(tmp_path, monkeypatch, caplog):
|
||||||
|
with patch("repo_cloner.lib.cred_helper.load_gh_token", autospec = True) as p:
|
||||||
|
cred_helper.token = None
|
||||||
|
init_gh_token()
|
||||||
|
assert p.call_count == 3
|
||||||
|
|
||||||
|
# "loaded" token
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setattr(os, "getcwd", lambda: tmp_path.as_posix())
|
||||||
|
tmp_path.joinpath(".gh-token").write_text("testtoken")
|
||||||
|
caplog.set_level(0)
|
||||||
|
init_gh_token()
|
||||||
|
assert "Token succesfully loaded" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_config_try_override(tmp_path, path_repo_base, monkeypatch):
|
||||||
|
tmp_path.joinpath("git").mkdir()
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setenv("XDG_CONFIG_HOME", tmp_path.as_posix())
|
||||||
|
r = Repo(path_repo_base)
|
||||||
|
cfgw = r.config_writer("user")
|
||||||
|
|
||||||
|
config_try_override(cfgw, "user", "name", "Mocker")
|
||||||
|
assert cfgw.get("user", "name") == "Mocker"
|
||||||
|
|
||||||
|
config_try_override(cfgw, "user", "name", "Loser")
|
||||||
|
assert cfgw.get("user", "name") == "Loser"
|
||||||
|
|
||||||
|
x = tmp_path.joinpath("git", "config")
|
||||||
|
assert x.is_file()
|
||||||
|
x = x.read_text()
|
||||||
|
assert x == "[user]\n name = Loser\n"
|
||||||
|
|
||||||
|
|
||||||
|
def test_prepare_git_auth(tmp_path, path_repo_base, monkeypatch):
|
||||||
|
tmp_path.joinpath("git").mkdir()
|
||||||
|
cred_helper.token = None
|
||||||
|
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setenv("XDG_CONFIG_HOME", tmp_path.as_posix())
|
||||||
|
|
||||||
|
prepare_git_auth(path_repo_base.as_posix(), tmp_path.as_posix())
|
||||||
|
|
||||||
|
x = tmp_path.joinpath("git", "config")
|
||||||
|
assert x.exists()
|
||||||
|
config = x.read_text()
|
||||||
|
assert config == \
|
||||||
|
f"[credential]\n" \
|
||||||
|
f" helper = store --file={tmp_path.as_posix()}/git/git-credentials\n" \
|
||||||
|
"[core]\n" \
|
||||||
|
f" sshcommand = ssh -i {tmp_path.as_posix()}/ssh/identity -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes -q\n"
|
||||||
|
|
||||||
|
|
||||||
|
def test_prepare_git_auth_token(tmp_path, path_repo_base, monkeypatch):
|
||||||
|
# tmp_path.joinpath("git").mkdir()
|
||||||
|
|
||||||
|
with monkeypatch.context() as mp:
|
||||||
|
mp.setenv("XDG_CONFIG_HOME", tmp_path.as_posix())
|
||||||
|
cred_helper.token = "token123"
|
||||||
|
|
||||||
|
prepare_git_auth(path_repo_base.as_posix(), tmp_path.as_posix())
|
||||||
|
|
||||||
|
x = tmp_path.joinpath("git", "config")
|
||||||
|
assert x.exists()
|
||||||
|
config = x.read_text()
|
||||||
|
assert config == \
|
||||||
|
"[url \"https://token123:x-oauth-basic@github.com/\"]\n" \
|
||||||
|
" insteadOf = https://github.com/\n" \
|
||||||
|
f"[credential]\n" \
|
||||||
|
f" helper = store --file={tmp_path.as_posix()}/git/git-credentials\n" \
|
||||||
|
"[core]\n" \
|
||||||
|
f" sshcommand = ssh -i {tmp_path.as_posix()}/ssh/identity -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes -q\n"
|
Loading…
Reference in New Issue
Block a user