]> git.ipfire.org Git - thirdparty/mkosi.git/commitdiff
mkosi: Override misconfigured gitconfig HTTP/HTTPS proxy with ProxyUrl
authorRyan Wilson <ryantimwilson@meta.com>
Mon, 21 Apr 2025 17:00:53 +0000 (10:00 -0700)
committerJörg Behrmann <behrmann@physik.fu-berlin.de>
Tue, 22 Apr 2025 07:12:40 +0000 (09:12 +0200)
When running mkosi on a server with an outgoing HTTP/HTTPS proxy,
Build.ProxyUrl must be set. However, some repositories (e.g. systemd)
call git in their mkosi scripts (e.g. cloning package repositories for
distros) and .gitconfig can also contain different http.proxy and https.proxy
settings. Thus, if .gitconfig is misconfigured with the wrong proxy,
the user will get confusing errors related to git fetching repositories.

To ensure we use a consistent proxy across git and mkosi, we override
git http proxy configuration via GIT_CONFIG_COUNT, GIT_CONFIG_KEY_{n},
GIT_CONFIG_VALUE{n} environment variables. Most of the code complexity
is dealing with the case when these variables are set by the user via
Environment / EnvironmentFiles.

mkosi/config.py
tests/test_config.py

index be72f9b10b1e709f53eaecc9e3636171a8dc5f29..433f10208f9b69ea289de0b320a268651a1a3f1a 100644 (file)
@@ -2131,6 +2131,7 @@ class Config:
             for line in f.read_text().strip().splitlines()
         )
         env |= self.environment
+        env |= finalize_git_config(self.proxy_url, env)
 
         return env
 
@@ -5244,6 +5245,27 @@ def finalize_term() -> str:
     return term if sys.stderr.isatty() else "dumb"
 
 
+def finalize_git_config(proxy_url: Optional[str], env: dict[str, str]) -> dict[str, str]:
+    if proxy_url is None:
+        return {}
+
+    try:
+        cnt = int(env.get("GIT_CONFIG_COUNT", "0"))
+    except ValueError:
+        raise ValueError("GIT_CONFIG_COUNT environment variable must be set to a valid integer")
+
+    # Override HTTP/HTTPS proxy in case its set in .gitconfig to a different value than proxy_url.
+    # No need to override http.proxy / https.proxy if set in a previous GIT_CONFIG_* variable since
+    # the last setting always wins.
+    return {
+        "GIT_CONFIG_COUNT": str(cnt + 2),
+        f"GIT_CONFIG_KEY_{cnt}": "http.proxy",
+        f"GIT_CONFIG_VALUE_{cnt}": proxy_url,
+        f"GIT_CONFIG_KEY_{cnt + 1}": "https.proxy",
+        f"GIT_CONFIG_VALUE_{cnt + 1}": proxy_url,
+    }
+
+
 def yes_no(b: bool) -> str:
     return "yes" if b else "no"
 
index ce4a313922ba145b8ed6019bfdb96e1ff436948f..bc52cd1c7e69c85e265713efeef53417150fd221 100644 (file)
@@ -1321,6 +1321,58 @@ def test_environment(tmp_path: Path) -> None:
         assert "TestValue2" not in sub.environment
 
 
+def test_proxy(tmp_path: Path) -> None:
+    d = tmp_path
+
+    # Verify environment variables are set correctly when GIT_CONFIG_COUNT is not set
+    (d / "mkosi.conf").write_text(
+        """\
+        [Build]
+        ProxyUrl=http://proxy:8080
+        """
+    )
+
+    with chdir(d):
+        _, _, [config] = parse_config()
+
+        expected = {
+            "GIT_CONFIG_COUNT": "2",
+            "GIT_CONFIG_KEY_0": "http.proxy",
+            "GIT_CONFIG_VALUE_0": "http://proxy:8080",
+            "GIT_CONFIG_KEY_1": "https.proxy",
+            "GIT_CONFIG_VALUE_1": "http://proxy:8080",
+        }
+
+        # Only check values for keys from expected, as config.environment contains other items as well
+        assert {k: config.finalize_environment()[k] for k in expected.keys()} == expected
+
+    (d / "mkosi.conf").write_text(
+        """\
+        [Build]
+        ProxyUrl=http://proxy:8080
+        Environment=GIT_CONFIG_COUNT=1
+                    GIT_CONFIG_KEY_0=user.name
+                    GIT_CONFIG_VALUE_0=bob
+        """
+    )
+
+    with chdir(d):
+        _, _, [config] = parse_config()
+
+        expected = {
+            "GIT_CONFIG_COUNT": "3",
+            "GIT_CONFIG_KEY_0": "user.name",
+            "GIT_CONFIG_VALUE_0": "bob",
+            "GIT_CONFIG_KEY_1": "http.proxy",
+            "GIT_CONFIG_VALUE_1": "http://proxy:8080",
+            "GIT_CONFIG_KEY_2": "https.proxy",
+            "GIT_CONFIG_VALUE_2": "http://proxy:8080",
+        }
+
+        # Only check values for keys from expected, as config.environment contains other items as well
+        assert {k: config.finalize_environment()[k] for k in expected.keys()} == expected
+
+
 def test_mkosi_version_executable(tmp_path: Path) -> None:
     d = tmp_path