Cred helper: load token, token support. RepoTool: timeout

Signed-off-by: Václav Valíček <valicek1994@gmail.com>
This commit is contained in:
Václav Valíček 2022-08-05 23:05:33 +02:00
parent de67130fd5
commit b3b9fbf0c8
Signed by: valicek
GPG Key ID: FF05BDCA0C73BB31
4 changed files with 147 additions and 2 deletions

View File

@ -1,5 +1,5 @@
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 .config_file_not_found_error import ConfigFileNotFoundError
from .default_cloner_config import DefaultClonerConfig

View File

@ -1,9 +1,40 @@
from git import Repo, GitConfigParser
import logging
import os
from typing import Optional, List
from pathlib import Path
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):
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")
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")
config_try_override(cfgw, "credential", "helper", f"store --file={cred_store}")
# ssh key
log.debug(f"Writing SSH cert path")
config_try_override(
cfgw,

View File

@ -194,7 +194,7 @@ class RepoTool:
self._last_fetch_data = remote.fetch(
["+refs/heads/*:refs/heads/*", "+refs/tags/*:refs/tags/*"],
progress = GitRemoteProgress(),
kill_after_timeout = 60,
kill_after_timeout = 600,
prune = True
)
log.debug("Fetch finished!")

View 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"