From 08cbb97ec9bfd7b5dec872b3cb25bc7c2b9684ca Mon Sep 17 00:00:00 2001 From: mechanarchy <1166756+mechanarchy@users.noreply.github.com> Date: Wed, 1 Dec 2021 15:10:25 +1100 Subject: [PATCH] Allow Git credentials to be loaded from secrets (#2825) --- .../components/external_components/__init__.py | 6 ++++++ esphome/components/packages/__init__.py | 6 ++++++ esphome/git.py | 15 ++++++++++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/esphome/components/external_components/__init__.py b/esphome/components/external_components/__init__.py index e0548e8981..d0153f6104 100644 --- a/esphome/components/external_components/__init__.py +++ b/esphome/components/external_components/__init__.py @@ -12,6 +12,8 @@ from esphome.const import ( CONF_TYPE, CONF_EXTERNAL_COMPONENTS, CONF_PATH, + CONF_USERNAME, + CONF_PASSWORD, ) from esphome.core import CORE from esphome import git, loader @@ -27,6 +29,8 @@ TYPE_LOCAL = "local" GIT_SCHEMA = { cv.Required(CONF_URL): cv.url, cv.Optional(CONF_REF): cv.git_ref, + cv.Optional(CONF_USERNAME): cv.string, + cv.Optional(CONF_PASSWORD): cv.string, } LOCAL_SCHEMA = { cv.Required(CONF_PATH): cv.directory, @@ -99,6 +103,8 @@ def _process_git_config(config: dict, refresh) -> str: ref=config.get(CONF_REF), refresh=refresh, domain=DOMAIN, + username=config.get(CONF_USERNAME), + password=config.get(CONF_PASSWORD), ) if (repo_dir / "esphome" / "components").is_dir(): diff --git a/esphome/components/packages/__init__.py b/esphome/components/packages/__init__.py index df0f0de13d..7483d65b9d 100644 --- a/esphome/components/packages/__init__.py +++ b/esphome/components/packages/__init__.py @@ -10,6 +10,8 @@ from esphome.const import ( CONF_REF, CONF_REFRESH, CONF_URL, + CONF_USERNAME, + CONF_PASSWORD, ) import esphome.config_validation as cv @@ -93,6 +95,8 @@ BASE_SCHEMA = cv.All( cv.Schema( { cv.Required(CONF_URL): cv.url, + cv.Optional(CONF_USERNAME): cv.string, + cv.Optional(CONF_PASSWORD): cv.string, cv.Exclusive(CONF_FILE, "files"): validate_yaml_filename, cv.Exclusive(CONF_FILES, "files"): cv.All( cv.ensure_list(validate_yaml_filename), @@ -124,6 +128,8 @@ def _process_base_package(config: dict) -> dict: ref=config.get(CONF_REF), refresh=config[CONF_REFRESH], domain=DOMAIN, + username=config.get(CONF_USERNAME), + password=config.get(CONF_PASSWORD), ) files: str = config[CONF_FILES] diff --git a/esphome/git.py b/esphome/git.py index 25d893b2f5..64c8d6a6b7 100644 --- a/esphome/git.py +++ b/esphome/git.py @@ -2,6 +2,7 @@ from pathlib import Path import subprocess import hashlib import logging +import urllib.parse from datetime import datetime @@ -36,9 +37,21 @@ def _compute_destination_path(key: str, domain: str) -> Path: def clone_or_update( - *, url: str, ref: str = None, refresh: TimePeriodSeconds, domain: str + *, + url: str, + ref: str = None, + refresh: TimePeriodSeconds, + domain: str, + username: str = None, + password: str = None, ) -> Path: key = f"{url}@{ref}" + + if username is not None and password is not None: + url = url.replace( + "://", f"://{urllib.parse.quote(username)}:{urllib.parse.quote(password)}@" + ) + repo_dir = _compute_destination_path(key, domain) fetch_pr_branch = ref is not None and ref.startswith("pull/") if not repo_dir.is_dir():