Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support using SSH to fetch repositories on Gitea #362

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 46 additions & 22 deletions buildbot_nix/buildbot_nix/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,7 @@ async def run_vc(
pr_head = build_props.getProperty("github.head.sha") or build_props.getProperty(
"head_sha"
)
auth_workdir = self._get_auth_data_workdir()

# Not a PR, fallback to default behavior
if merge_base is None or pr_head is None:
Expand All @@ -1005,33 +1006,42 @@ async def run_vc(
self.build.path_module.join(self.workdir, ".git")
)

if not has_git:
await self._dovccmd(["clone", "--recurse-submodules", self.repourl, "."])
try:
await self._git_auth.download_auth_files_if_needed(auth_workdir)

patched = await self.sourcedirIsPatched()
if not has_git:
await self._dovccmd(
["clone", "--recurse-submodules", self.repourl, "."]
)

if patched:
await self._dovccmd(["clean", "-f", "-f", "-d", "-x"])
patched = await self.sourcedirIsPatched()

await self._dovccmd(["fetch", "-f", "-t", self.repourl, merge_base, pr_head])
if patched:
await self._dovccmd(["clean", "-f", "-f", "-d", "-x"])

await self._dovccmd(["checkout", "--detach", "-f", pr_head])
await self._dovccmd(
["fetch", "-f", "-t", self.repourl, merge_base, pr_head]
)

await self._dovccmd(
[
"-c",
"[email protected]",
"-c",
"user.name=buildbot",
"merge",
"--no-ff",
"-m",
f"Merge {merge_base} into {pr_head}",
merge_base,
]
)
self.updateSourceProperty("got_revision", pr_head)
return await self.parseCommitDescription()
await self._dovccmd(["checkout", "--detach", "-f", pr_head])

await self._dovccmd(
[
"-c",
"[email protected]",
"-c",
"user.name=buildbot",
"merge",
"--no-ff",
"-m",
f"Merge {merge_base} into {pr_head}",
merge_base,
]
)
self.updateSourceProperty("got_revision", pr_head)
return await self.parseCommitDescription()
finally:
await self._git_auth.remove_auth_files_if_needed(auth_workdir)


def nix_eval_config(
Expand All @@ -1058,6 +1068,12 @@ def nix_eval_config(
submodules=True,
haltOnFailure=True,
logEnviron=False,
sshPrivateKey=project.private_key_path.read_text()
if project.private_key_path
else None,
sshKnownHosts=project.known_hosts_path.read_text()
if project.known_hosts_path
else None,
),
)
drv_gcroots_dir = util.Interpolate(
Expand Down Expand Up @@ -1365,6 +1381,8 @@ def nix_skipped_build_config(
collapseRequests=False,
env={},
factory=factory,
do_build_if=lambda build: do_register_gcroot_if(build, branch_config_dict)
and outputs_path is not None,
)


Expand Down Expand Up @@ -1414,6 +1432,12 @@ def buildbot_effects_config(
method="clean",
submodules=True,
haltOnFailure=True,
sshPrivateKey=project.private_key_path.read_text()
if project.private_key_path
else None,
sshKnownHosts=project.known_hosts_path.read_text()
if project.known_hosts_path
else None,
),
)
secrets_list = []
Expand Down
10 changes: 10 additions & 0 deletions buildbot_nix/buildbot_nix/gitea_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ def __init__(

def get_project_url(self) -> str:
url = urlparse(self.config.instance_url)
if self.config.ssh_private_key_file:
return self.data.ssh_url
return f"{url.scheme}://git:%(secret:{self.config.token_file})s@{url.hostname}/{self.name}"

def create_change_source(self) -> ChangeSource | None:
Expand Down Expand Up @@ -113,6 +115,14 @@ def belongs_to_org(self) -> bool:
# TODO Gitea doesn't include this information
return False # self.data["owner"]["type"] == "Organization"

@property
def private_key_path(self) -> Path | None:
return self.config.ssh_private_key_file

@property
def known_hosts_path(self) -> Path | None:
return self.config.ssh_known_hosts_file


class GiteaBackend(GitBackend):
config: GiteaConfig
Expand Down
8 changes: 8 additions & 0 deletions buildbot_nix/buildbot_nix/github_projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,14 @@ def topics(self) -> list[str]:
def belongs_to_org(self) -> bool:
return self.data.owner.ttype == "Organization"

@property
def private_key_path(self) -> Path | None:
return None

@property
def known_hosts_path(self) -> Path | None:
return None


def refresh_projects(
github_token: str,
Expand Down
3 changes: 3 additions & 0 deletions buildbot_nix/buildbot_nix/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ class GiteaConfig(BaseModel):
oauth_id: str | None
oauth_secret_file: Path | None

ssh_private_key_file: Path | None
ssh_known_hosts_file: Path | None

@property
def token(self) -> str:
return read_secret_file(self.token_file)
Expand Down
11 changes: 11 additions & 0 deletions buildbot_nix/buildbot_nix/projects.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from abc import ABC, abstractmethod
from pathlib import Path
from typing import Any

from buildbot.changes.base import ChangeSource
Expand Down Expand Up @@ -125,3 +126,13 @@ def topics(self) -> list[str]:
@abstractmethod
def belongs_to_org(self) -> bool:
pass

@property
@abstractmethod
def private_key_path(self) -> Path | None:
pass

@property
@abstractmethod
def known_hosts_path(self) -> Path | None:
pass
9 changes: 9 additions & 0 deletions buildbot_nix/buildbot_nix/pull_based/project.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from pathlib import Path
from typing import Any
from urllib.parse import ParseResult, urlparse

Expand Down Expand Up @@ -99,3 +100,11 @@ def topics(self) -> list[str]:
@property
def belongs_to_org(self) -> bool:
return False

@property
def private_key_path(self) -> Path | None:
return None

@property
def known_hosts_path(self) -> Path | None:
return None
19 changes: 19 additions & 0 deletions nix/master.nix
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,23 @@ in
If null, all projects that the buildbot Gitea user has access to, are built.
'';
};

sshPrivateKeyFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
If non-null the specified SSH key will be used to fetch all configured repositories.
'';
};

sshKnownHostsFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
If non-null the specified known hosts file will be matched against when connecting to
repositories over SSH.
'';
};
};
github = {
enable = lib.mkEnableOption "Enable GitHub integration" // {
Expand Down Expand Up @@ -801,6 +818,8 @@ in
instance_url = cfg.gitea.instanceUrl;
oauth_id = cfg.gitea.oauthId;
topic = cfg.gitea.topic;
ssh_private_key_file = cfg.gitea.sshPrivateKeyFile;
ssh_known_hosts_file = cfg.gitea.sshKnownHostsFile;
};
github =
if !cfg.github.enable then
Expand Down