wip: Include manifest diff in PR description

Dustin 2024-08-27 21:14:13 -05:00
parent 8126e5de21
commit a2f33f1be2
1 changed files with 58 additions and 11 deletions

View File

@ -5,6 +5,7 @@ import logging
import functools
import os
import re
import subprocess
import tempfile
import threading
import tomllib
@ -122,6 +123,10 @@ class BaseProject(abc.ABC, pydantic.BaseModel):
def apply_update(self, path: Path, version: str) -> None:
raise NotImplementedError
@abc.abstractmethod
def diff(self, path: Path) -> str:
raise NotImplementedError
class KustomizeProject(BaseProject):
kind: Literal['kustomize']
@ -153,6 +158,26 @@ class KustomizeProject(BaseProject):
with filepath.open('wb') as f:
yaml.dump(kustomization, f)
def diff(self, path: Path) -> str:
try:
p = subprocess.run(
['kubectl', 'diff', '-k', '.'],
cwd=path,
check=False,
capture_output=True,
stdin=subprocess.DEVNULL,
encoding='utf-8',
)
except FileNotFoundError as e:
log.warning('Cannot compute manifest diff: %s', e)
return ''
if not p.stdout and p.returncode != 0:
log.error('Error computing manifest diff: %s', p.stderr)
return ''
else:
assert p.stdout is not None
return p.stdout
class DirectoryProject(BaseProject):
kind: Literal['dir'] | Literal['directory']
@ -195,7 +220,11 @@ class RepoConfig(pydantic.BaseModel):
return data['clone_url']
def create_pr(
self, title: str, source_branch: str, target_branch: str
self,
title: str,
source_branch: str,
target_branch: str,
body: Optional[str] = None,
) -> None:
session = _get_session()
r = session.post(
@ -207,6 +236,7 @@ class RepoConfig(pydantic.BaseModel):
'title': title,
'base': target_branch,
'head': source_branch,
'body': body,
},
)
log.log(TRACE, '%r', r.content)
@ -237,7 +267,7 @@ class Arguments:
def update_project(
repo: git.Repo, name: str, project: Project
) -> Optional[git.Commit]:
) -> tuple[Optional[git.Commit], Optional[str]]:
basedir = Path(repo.working_dir)
log.debug('Checking for latest version of %s', name)
latest = project.source.get_latest_version()
@ -250,10 +280,12 @@ def update_project(
repo.index.add(str(path))
c = repo.index.commit(f'{name}: Update to {latest}')
log.info('Commited %s %s', str(c)[:7], c.summary)
return c
log.debug('Computing manifest diff')
diff = project.diff(path)
return (c, diff)
else:
log.info('No changes to commit')
return None
return (None, None)
def parse_args() -> Arguments:
@ -324,8 +356,11 @@ def main() -> None:
log.debug('Checking out new branch: %s', args.branch_name)
repo.heads[0].checkout(force=True, B=args.branch_name)
title = None
pr_desc = ''
for project in projects:
commit = update_project(repo, project, config.projects[project])
commit, diff = update_project(
repo, project, config.projects[project]
)
if commit and not title:
if not isinstance(commit.summary, str):
title = bytes(commit.summary).decode(
@ -333,17 +368,29 @@ def main() -> None:
)
else:
title = commit.summary
if diff:
pr_desc += diff
if not title:
log.info('No changes made')
return
if not args.dry_run:
repo.head.reference.set_tracking_branch(
git.RemoteReference(
repo, f'refs/remotes/origin/{args.branch_name}'
)
)
if not args.dry_run:
repo.remote().push(force=True)
config.repo.create_pr(title, args.branch_name, config.repo.branch)
if pr_desc:
pr_desc = (
'<details>\n<summary>Manifest diff</summary>\n\n'
f'```diff\n{pr_desc}```\n'
'</details>'
)
config.repo.create_pr(
title, args.branch_name, config.repo.branch, pr_desc
)
elif pr_desc:
print(pr_desc)
if __name__ == '__main__':