Refactor passing around git commit info

This commit is contained in:
Stéphane Bidoul 2021-11-21 17:57:11 +01:00
parent 386ccf63b3
commit 180ecc6f8d
No known key found for this signature in database
GPG key ID: BCAB2555446B5B92
12 changed files with 131 additions and 150 deletions

View file

@ -43,10 +43,7 @@ class Repo(BaseModel):
class Build(BaseModel): class Build(BaseModel):
name: str name: str
repo: str commit_info: github.CommitInfo
target_branch: str
pr: Optional[int]
git_commit: str
image: str image: str
deploy_link: str deploy_link: str
repo_target_branch_link: str repo_target_branch_link: str
@ -117,13 +114,8 @@ async def undeploy_builds(
) )
async def trigger_branch(repo: str, branch: str) -> None: async def trigger_branch(repo: str, branch: str) -> None:
"""Trigger build for a branch.""" """Trigger build for a branch."""
branch_info = await github.get_branch_info(repo, branch) commit_info = await github.get_branch_info(repo, branch)
await controller.deploy_or_start( await controller.deploy_or_start(commit_info)
repo=branch_info.repo,
target_branch=branch_info.name,
pr=None,
git_commit=branch_info.head_sha,
)
@router.post( @router.post(
@ -132,13 +124,8 @@ async def trigger_branch(repo: str, branch: str) -> None:
) )
async def trigger_pull(repo: str, pr: int) -> None: async def trigger_pull(repo: str, pr: int) -> None:
"""Trigger build for a pull request.""" """Trigger build for a pull request."""
pull_info = await github.get_pull_info(repo, pr) commit_info = await github.get_pull_info(repo, pr)
await controller.deploy_or_start( await controller.deploy_or_start(commit_info)
repo=pull_info.repo,
target_branch=pull_info.target_branch,
pr=pull_info.number,
git_commit=pull_info.head_sha,
)
async def _build_by_name(name: str) -> models.Build: async def _build_by_name(name: str) -> models.Build:
@ -222,13 +209,15 @@ class BuildEventSource:
return BuildEvent(event=event, build=Build.from_orm(build)).json() return BuildEvent(event=event, build=Build.from_orm(build)).json()
def on_build_event(self, event: models.BuildEvent, build: models.Build) -> None: def on_build_event(self, event: models.BuildEvent, build: models.Build) -> None:
if self.repo and build.repo != self.repo: if self.repo and build.commit_info.repo != self.repo:
return return
if self.target_branch and build.target_branch != self.target_branch: if self.target_branch and build.commit_info.target_branch != self.target_branch:
return return
if self.branch and (build.target_branch != self.branch or build.pr): if self.branch and (
build.commit_info.target_branch != self.branch or build.commit_info.pr
):
return return
if self.pr and build.pr != self.pr: if self.pr and build.commit_info.pr != self.pr:
return return
if self.build_name and build.name != self.build_name: if self.build_name and build.name != self.build_name:
return return

View file

@ -4,6 +4,7 @@ from typing import Any, Awaitable, Callable
from . import k8s from . import k8s
from .db import BuildsDb from .db import BuildsDb
from .github import CommitInfo
from .models import Build, BuildEvent, BuildInitStatus, BuildStatus from .models import Build, BuildEvent, BuildInitStatus, BuildStatus
from .settings import settings from .settings import settings
@ -78,24 +79,17 @@ class Controller:
def undeploying(self) -> int: def undeploying(self) -> int:
return self.db.count_by_status(BuildStatus.undeploying) return self.db.count_by_status(BuildStatus.undeploying)
async def deploy_or_start( async def deploy_or_start(self, commit_info: CommitInfo) -> None:
self, repo: str, target_branch: str, pr: int | None, git_commit: str
) -> None:
build = self.db.get_for_commit( build = self.db.get_for_commit(
repo=repo, repo=commit_info.repo,
target_branch=target_branch, target_branch=commit_info.target_branch,
pr=pr, pr=commit_info.pr,
git_commit=git_commit, git_commit=commit_info.git_commit,
) )
if build is not None: if build is not None:
await build.start() await build.start()
return return
await Build.deploy( await Build.deploy(commit_info)
repo=repo,
target_branch=target_branch,
pr=pr,
git_commit=git_commit,
)
def _wakeup(self) -> None: def _wakeup(self) -> None:
self._wakeup_initializer.set() self._wakeup_initializer.set()

View file

@ -4,6 +4,7 @@ from enum import Enum
from typing import Iterator, Protocol, cast from typing import Iterator, Protocol, cast
from weakref import WeakSet from weakref import WeakSet
from .github import CommitInfo
from .models import Build, BuildEvent, BuildInitStatus, BuildStatus, Repo from .models import Build, BuildEvent, BuildInitStatus, BuildStatus, Repo
_logger = logging.getLogger(__name__) _logger = logging.getLogger(__name__)
@ -40,7 +41,12 @@ class BuildsDb:
@classmethod @classmethod
def _build_from_row(cls, row: sqlite3.Row) -> Build: def _build_from_row(cls, row: sqlite3.Row) -> Build:
return Build(**{k: row[k] for k in row.keys()}) commit_info_fields = {"repo", "target_branch", "pr", "git_commit"}
commit_info = CommitInfo(**{k: row[k] for k in commit_info_fields})
return Build(
commit_info=commit_info,
**{k: row[k] for k in row.keys() if k not in commit_info_fields}
)
def reset(self) -> None: def reset(self) -> None:
self._con = sqlite3.connect(":memory:") self._con = sqlite3.connect(":memory:")
@ -123,10 +129,10 @@ class BuildsDb:
( (
build.name, build.name,
build.deployment_name, build.deployment_name,
build.repo, build.commit_info.repo,
build.target_branch, build.commit_info.target_branch,
build.pr, build.commit_info.pr,
build.git_commit, build.commit_info.git_commit,
build.image, build.image,
build.desired_replicas, build.desired_replicas,
build.status, build.status,

View file

@ -1,8 +1,8 @@
from dataclasses import dataclass
from enum import Enum from enum import Enum
from typing import Any from typing import Any, Optional
import httpx import httpx
from pydantic import BaseModel
from .exceptions import NotFoundOnGitHub from .exceptions import NotFoundOnGitHub
from .settings import settings from .settings import settings
@ -23,37 +23,30 @@ async def _github_request(method: str, url: str, json: Any = None) -> Any:
return response.json() return response.json()
@dataclass class CommitInfo(BaseModel):
class BranchInfo:
repo: str repo: str
name: str target_branch: str
head_sha: str pr: Optional[int]
git_commit: str
async def get_branch_info(repo: str, branch: str) -> BranchInfo: async def get_branch_info(repo: str, branch: str) -> CommitInfo:
branch_data = await _github_request("GET", f"/repos/{repo}/git/ref/heads/{branch}") branch_data = await _github_request("GET", f"/repos/{repo}/git/ref/heads/{branch}")
return BranchInfo( return CommitInfo(
repo=repo, repo=repo,
name=branch, target_branch=branch,
head_sha=branch_data["object"]["sha"], pr=None,
git_commit=branch_data["object"]["sha"],
) )
@dataclass async def get_pull_info(repo: str, pr: int) -> CommitInfo:
class PullInfo:
repo: str
number: int
head_sha: str
target_branch: str
async def get_pull_info(repo: str, pr: int) -> PullInfo:
pr_data = await _github_request("GET", f"/repos/{repo}/pulls/{pr}") pr_data = await _github_request("GET", f"/repos/{repo}/pulls/{pr}")
return PullInfo( return CommitInfo(
repo=repo, repo=repo,
number=pr,
head_sha=pr_data["head"]["sha"],
target_branch=pr_data["base"]["ref"], target_branch=pr_data["base"]["ref"],
pr=pr,
git_commit=pr_data["head"]["sha"],
) )

View file

@ -9,7 +9,7 @@ from contextlib import contextmanager
from enum import Enum from enum import Enum
from importlib import resources from importlib import resources
from pathlib import Path from pathlib import Path
from typing import Any, Callable, Generator, Optional, TypedDict, cast from typing import Any, Callable, Generator, TypedDict, cast
import urllib3 import urllib3
from jinja2 import Template from jinja2 import Template
@ -19,6 +19,7 @@ from kubernetes.client.models.v1_deployment import V1Deployment
from kubernetes.client.models.v1_job import V1Job from kubernetes.client.models.v1_job import V1Job
from pydantic import BaseModel from pydantic import BaseModel
from .github import CommitInfo
from .settings import settings from .settings import settings
from .utils import sync_to_async, sync_to_async_iterator from .utils import sync_to_async, sync_to_async_iterator
@ -146,10 +147,7 @@ class DeploymentVars(BaseModel):
build_name: str build_name: str
build_slug: str build_slug: str
build_domain: str build_domain: str
repo: str commit_info: CommitInfo
target_branch: str
pr: Optional[int]
git_commit: str
image_name: str image_name: str
image_tag: str image_tag: str
build_env: dict[str, str] build_env: dict[str, str]
@ -161,10 +159,7 @@ def make_deployment_vars(
mode: DeploymentMode, mode: DeploymentMode,
build_name: str, build_name: str,
slug: str, slug: str,
repo: str, commit_info: CommitInfo,
target_branch: str,
pr: int | None,
git_commit: str,
image: str, image: str,
) -> DeploymentVars: ) -> DeploymentVars:
image_name, image_tag = _split_image_name_tag(image) image_name, image_tag = _split_image_name_tag(image)
@ -174,10 +169,7 @@ def make_deployment_vars(
build_name=build_name, build_name=build_name,
build_slug=slug, build_slug=slug,
build_domain=settings.build_domain, build_domain=settings.build_domain,
repo=repo, commit_info=commit_info,
target_branch=target_branch,
pr=pr,
git_commit=git_commit,
image_name=image_name, image_name=image_name,
image_tag=image_tag, image_tag=image_tag,
build_env=settings.build_env or {}, build_env=settings.build_env or {},

View file

@ -19,10 +19,10 @@ commonLabels:
runboat/build: "{{ build_name }}" runboat/build: "{{ build_name }}"
commonAnnotations: commonAnnotations:
runboat/repo: "{{ repo }}" runboat/repo: "{{ commit_info.repo }}"
runboat/target-branch: "{{ target_branch }}" runboat/target-branch: "{{ commit_info.target_branch }}"
runboat/pr: "{{ pr if pr else '' }}" runboat/pr: "{{ commit_info.pr if commit_info.pr else '' }}"
runboat/git-commit: "{{ git_commit }}" runboat/git-commit: "{{ commit_info.git_commit }}"
images: images:
- name: odoo - name: odoo
@ -41,8 +41,8 @@ configMapGenerator:
literals: literals:
- PGDATABASE={{ build_name }} - PGDATABASE={{ build_name }}
- ADDONS_DIR=/mnt/data/odoo-addons-dir - ADDONS_DIR=/mnt/data/odoo-addons-dir
- RUNBOAT_GIT_REPO=https://github.com/{{ repo }} - RUNBOAT_GIT_REPO=https://github.com/{{ commit_info.repo }}
- RUNBOAT_GIT_REF={{ git_commit }} - RUNBOAT_GIT_REF={{ commit_info.git_commit }}
{%- for key, value in build_env.items() %} {%- for key, value in build_env.items() %}
- {{ key }}={{ value }} - {{ key }}={{ value }}
{%- endfor %} {%- endfor %}

View file

@ -8,7 +8,7 @@ from kubernetes.client.models.v1_deployment import V1Deployment
from pydantic import BaseModel from pydantic import BaseModel
from . import github, k8s from . import github, k8s
from .github import GitHubStatusState from .github import CommitInfo, GitHubStatusState
from .settings import get_build_settings, settings from .settings import get_build_settings, settings
from .utils import slugify from .utils import slugify
@ -40,10 +40,7 @@ class BuildInitStatus(str, Enum):
class Build(BaseModel): class Build(BaseModel):
name: str name: str
deployment_name: str deployment_name: str
repo: str commit_info: CommitInfo
target_branch: str
pr: Optional[int]
git_commit: str
image: str image: str
status: BuildStatus status: BuildStatus
init_status: BuildInitStatus init_status: BuildInitStatus
@ -83,10 +80,12 @@ class Build(BaseModel):
return Build( return Build(
name=deployment.metadata.labels["runboat/build"], name=deployment.metadata.labels["runboat/build"],
deployment_name=deployment.metadata.name, deployment_name=deployment.metadata.name,
repo=deployment.metadata.annotations["runboat/repo"], commit_info=CommitInfo(
target_branch=deployment.metadata.annotations["runboat/target-branch"], repo=deployment.metadata.annotations["runboat/repo"],
pr=deployment.metadata.annotations.get("runboat/pr") or None, target_branch=deployment.metadata.annotations["runboat/target-branch"],
git_commit=deployment.metadata.annotations["runboat/git-commit"], pr=deployment.metadata.annotations.get("runboat/pr") or None,
git_commit=deployment.metadata.annotations["runboat/git-commit"],
),
image=deployment.spec.template.spec.containers[0].image, image=deployment.spec.template.spec.containers[0].image,
init_status=deployment.metadata.annotations["runboat/init-status"], init_status=deployment.metadata.annotations["runboat/init-status"],
status=cls._status_from_deployment(deployment), status=cls._status_from_deployment(deployment),
@ -121,17 +120,18 @@ class Build(BaseModel):
@classmethod @classmethod
def make_slug( def make_slug(
cls, repo: str, target_branch: str, pr: int | None, git_commit: str cls,
commit_info: CommitInfo,
) -> str: ) -> str:
slug = f"{slugify(repo)}-{slugify(target_branch)}" slug = f"{slugify(commit_info.repo)}-{slugify(commit_info.target_branch)}"
if pr: if commit_info.pr:
slug = f"{slug}-pr{slugify(pr)}" slug = f"{slug}-pr{slugify(commit_info.pr)}"
slug = f"{slug}-{git_commit[:12]}" slug = f"{slug}-{commit_info.git_commit[:12]}"
return slug return slug
@property @property
def slug(self) -> str: def slug(self) -> str:
return self.make_slug(self.repo, self.target_branch, self.pr, self.git_commit) return self.make_slug(self.commit_info)
@property @property
def deploy_link(self) -> str: def deploy_link(self) -> str:
@ -139,21 +139,27 @@ class Build(BaseModel):
@property @property
def repo_target_branch_link(self) -> str: def repo_target_branch_link(self) -> str:
return f"https://github.com/{self.repo}/tree/{self.target_branch}" return (
f"https://github.com/{self.commit_info.repo}"
f"/tree/{self.commit_info.target_branch}"
)
@property @property
def repo_pr_link(self) -> str | None: def repo_pr_link(self) -> str | None:
if not self.pr: if not self.commit_info.pr:
return None return None
return f"https://github.com/{self.repo}/pull/{self.pr}" return f"https://github.com/{self.commit_info.repo}/pull/{self.commit_info.pr}"
@property @property
def repo_commit_link(self) -> str: def repo_commit_link(self) -> str:
link = f"https://github.com/{self.repo}" link = f"https://github.com/{self.commit_info.repo}"
if self.pr: if self.commit_info.pr:
return f"{link}/pull/{self.pr}/commits/{self.git_commit}" return (
f"{link}/pull/{self.commit_info.pr}"
f"/commits/{self.commit_info.git_commit}"
)
else: else:
return f"{link}/commit/{self.git_commit}" return f"{link}/commit/{self.commit_info.git_commit}"
@property @property
def webui_link(self) -> str: def webui_link(self) -> str:
@ -170,14 +176,12 @@ class Build(BaseModel):
return await k8s.log(self.name, job_kind=None) return await k8s.log(self.name, job_kind=None)
@classmethod @classmethod
async def deploy( async def deploy(cls, commit_info: CommitInfo) -> None:
cls, repo: str, target_branch: str, pr: int | None, git_commit: str
) -> None:
"""Deploy a build, without starting it.""" """Deploy a build, without starting it."""
name = f"b{uuid.uuid4()}" name = f"b{uuid.uuid4()}"
slug = cls.make_slug(repo, target_branch, pr, git_commit) slug = cls.make_slug(commit_info)
_logger.info(f"Deploying {slug} ({name}).") _logger.info(f"Deploying {slug} ({name}).")
build_settings = get_build_settings(repo, target_branch) build_settings = get_build_settings(commit_info.repo, commit_info.target_branch)
if len(build_settings) > 1: if len(build_settings) > 1:
raise NotImplementedError( raise NotImplementedError(
"Having more than one build per commit is not supported yet." "Having more than one build per commit is not supported yet."
@ -186,16 +190,13 @@ class Build(BaseModel):
k8s.DeploymentMode.deployment, k8s.DeploymentMode.deployment,
name, name,
slug, slug,
repo.lower(), commit_info,
target_branch,
pr,
git_commit,
build_settings[0].image, build_settings[0].image,
) )
await k8s.deploy(deployment_vars) await k8s.deploy(deployment_vars)
await github.notify_status( await github.notify_status(
repo, commit_info.repo,
git_commit, commit_info.git_commit,
GitHubStatusState.pending, GitHubStatusState.pending,
target_url=None, target_url=None,
) )
@ -220,8 +221,8 @@ class Build(BaseModel):
await k8s.delete_job(self.name, job_kind=k8s.DeploymentMode.initialize) await k8s.delete_job(self.name, job_kind=k8s.DeploymentMode.initialize)
if await self._patch(init_status=BuildInitStatus.todo, desired_replicas=0): if await self._patch(init_status=BuildInitStatus.todo, desired_replicas=0):
await github.notify_status( await github.notify_status(
self.repo, self.commit_info.repo,
self.git_commit, self.commit_info.git_commit,
GitHubStatusState.pending, GitHubStatusState.pending,
target_url=self.live_link, target_url=self.live_link,
) )
@ -253,10 +254,7 @@ class Build(BaseModel):
k8s.DeploymentMode.initialize, k8s.DeploymentMode.initialize,
self.name, self.name,
self.slug, self.slug,
self.repo, self.commit_info,
self.target_branch,
self.pr,
self.git_commit,
self.image, self.image,
) )
await k8s.deploy(deployment_vars) await k8s.deploy(deployment_vars)
@ -274,10 +272,7 @@ class Build(BaseModel):
k8s.DeploymentMode.cleanup, k8s.DeploymentMode.cleanup,
self.name, self.name,
self.slug, self.slug,
self.repo, self.commit_info,
self.target_branch,
self.pr,
self.git_commit,
self.image, self.image,
) )
await k8s.deploy(deployment_vars) await k8s.deploy(deployment_vars)
@ -288,8 +283,8 @@ class Build(BaseModel):
_logger.info(f"Initialization job started for {self}.") _logger.info(f"Initialization job started for {self}.")
if await self._patch(init_status=BuildInitStatus.started, desired_replicas=0): if await self._patch(init_status=BuildInitStatus.started, desired_replicas=0):
await github.notify_status( await github.notify_status(
self.repo, self.commit_info.repo,
self.git_commit, self.commit_info.git_commit,
GitHubStatusState.pending, GitHubStatusState.pending,
target_url=self.live_link, target_url=self.live_link,
) )
@ -302,8 +297,8 @@ class Build(BaseModel):
_logger.info(f"Initialization job succeded for {self}, ready to start.") _logger.info(f"Initialization job succeded for {self}, ready to start.")
if await self._patch(init_status=BuildInitStatus.succeeded): if await self._patch(init_status=BuildInitStatus.succeeded):
await github.notify_status( await github.notify_status(
self.repo, self.commit_info.repo,
self.git_commit, self.commit_info.git_commit,
GitHubStatusState.success, GitHubStatusState.success,
target_url=self.live_link, target_url=self.live_link,
) )
@ -316,8 +311,8 @@ class Build(BaseModel):
_logger.info(f"Initialization job failed for {self}.") _logger.info(f"Initialization job failed for {self}.")
if await self._patch(init_status=BuildInitStatus.failed, desired_replicas=0): if await self._patch(init_status=BuildInitStatus.failed, desired_replicas=0):
await github.notify_status( await github.notify_status(
self.repo, self.commit_info.repo,
self.git_commit, self.commit_info.git_commit,
GitHubStatusState.failure, GitHubStatusState.failure,
target_url=self.live_link, target_url=self.live_link,
) )

View file

@ -30,8 +30,8 @@
const build = oEvent.build; const build = oEvent.build;
buildElement.build = oEvent.event == "upd" ? build : {}; buildElement.build = oEvent.event == "upd" ? build : {};
const repolinkElement = document.getElementById("repolink"); const repolinkElement = document.getElementById("repolink");
repolinkElement.href = `./builds.html?repo=${build.repo}`; repolinkElement.href = `./builds.html?repo=${build.commit_info.repo}`;
repolinkElement.text = build.repo; repolinkElement.text = build.commit_info.repo;
} }
// TODO: evtSource error handling // TODO: evtSource error handling
</script> </script>

View file

@ -47,9 +47,9 @@
// update event element // update event element
buildElement.build = oEvent.build; buildElement.build = oEvent.build;
} else { } else {
var rowId = `branch-${oEvent.build.target_branch}`; var rowId = `branch-${oEvent.build.commit_info.target_branch}`;
if (oEvent.build.pr) { if (oEvent.build.commit_info.pr) {
rowId += `-pr-${oEvent.build.pr}` rowId += `-pr-${oEvent.build.commit_info.pr}`
} }
var rowElement = document.getElementById(rowId); var rowElement = document.getElementById(rowId);
if (!rowElement) { if (!rowElement) {

View file

@ -42,13 +42,13 @@ class RunboatBuildElement extends LitElement {
<div class="build-card build-status-${this.build.status}"> <div class="build-card build-status-${this.build.status}">
<p class="build-name">${this.build.name}</p> <p class="build-name">${this.build.name}</p>
<p> <p>
<a href="${this.build.repo_target_branch_link}">${this.build.repo} ${this.build.target_branch}</a> <a href="${this.build.repo_target_branch_link}">${this.build.commit_info.repo} ${this.build.commit_info.target_branch}</a>
${this.build.pr? ${this.build.commit_info.pr?
html`PR <a href="${this.build.repo_pr_link}">${this.build.pr}</a>`:"" html`PR <a href="${this.build.repo_pr_link}">${this.build.commit_info.pr}</a>`:""
} }
<br> <br>
${this.build.git_commit? ${this.build.commit_info.git_commit?
html`(<a href="${this.build.repo_commit_link}">${this.build.git_commit.substring(0, 8)}</a>)`:"" html`(<a href="${this.build.repo_commit_link}">${this.build.commit_info.git_commit.substring(0, 8)}</a>)`:""
} }
</p> </p>
<p> <p>

View file

@ -2,6 +2,7 @@ import datetime
from unittest.mock import MagicMock from unittest.mock import MagicMock
from runboat.db import BuildsDb, SortOrder from runboat.db import BuildsDb, SortOrder
from runboat.github import CommitInfo
from runboat.models import Build, BuildInitStatus, BuildStatus, Repo from runboat.models import Build, BuildInitStatus, BuildStatus, Repo
@ -18,10 +19,12 @@ def _make_build(
return Build( return Build(
name=name, name=name,
deployment_name=name + "-odoo", deployment_name=name + "-odoo",
repo=repo or "oca/mis-builder", commit_info=CommitInfo(
target_branch=target_branch or "15.0", repo=repo or "oca/mis-builder",
pr=pr or None, target_branch=target_branch or "15.0",
git_commit="0d35a10f161b410f2baa3d416a338d191b6dabc0", pr=pr or None,
git_commit="0d35a10f161b410f2baa3d416a338d191b6dabc0",
),
image="ghcr.io/oca/oca-ci:py3.8-odoo15.0", image="ghcr.io/oca/oca-ci:py3.8-odoo15.0",
status=status or BuildStatus.starting, status=status or BuildStatus.starting,
init_status=init_status or BuildInitStatus.todo, init_status=init_status or BuildInitStatus.todo,
@ -62,13 +65,19 @@ def test_get_for_commit() -> None:
db.add(build) db.add(build)
assert ( assert (
db.get_for_commit( db.get_for_commit(
build.repo, build.target_branch, build.pr, git_commit=build.git_commit build.commit_info.repo,
build.commit_info.target_branch,
build.commit_info.pr,
git_commit=build.commit_info.git_commit,
) )
== build == build
) )
assert ( assert (
db.get_for_commit( db.get_for_commit(
"not-a-build", build.target_branch, build.pr, git_commit=build.git_commit "not-a-repo",
build.commit_info.target_branch,
build.commit_info.pr,
git_commit=build.commit_info.git_commit,
) )
is None is None
) )

View file

@ -1,3 +1,4 @@
from runboat.github import CommitInfo
from runboat.k8s import DeploymentMode, _render_kubefiles, make_deployment_vars from runboat.k8s import DeploymentMode, _render_kubefiles, make_deployment_vars
EXPECTED = """\ EXPECTED = """\
@ -70,10 +71,12 @@ def test_render_kubefiles() -> None:
mode=DeploymentMode.deployment, mode=DeploymentMode.deployment,
build_name="build-name", build_name="build-name",
slug="build-slug", slug="build-slug",
repo="oca/mis-builder", commit_info=CommitInfo(
target_branch="15.0", repo="oca/mis-builder",
pr=None, target_branch="15.0",
git_commit="abcdef123456789", pr=None,
git_commit="abcdef123456789",
),
image="ghcr.io/oca/oca-ci:py3.8-odoo15.0", image="ghcr.io/oca/oca-ci:py3.8-odoo15.0",
) )
with _render_kubefiles(deployment_vars) as tmp_path: with _render_kubefiles(deployment_vars) as tmp_path: