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 functools
import os import os
import re import re
import subprocess
import tempfile import tempfile
import threading import threading
import tomllib import tomllib
@ -122,6 +123,10 @@ class BaseProject(abc.ABC, pydantic.BaseModel):
def apply_update(self, path: Path, version: str) -> None: def apply_update(self, path: Path, version: str) -> None:
raise NotImplementedError raise NotImplementedError
@abc.abstractmethod
def diff(self, path: Path) -> str:
raise NotImplementedError
class KustomizeProject(BaseProject): class KustomizeProject(BaseProject):
kind: Literal['kustomize'] kind: Literal['kustomize']
@ -153,6 +158,26 @@ class KustomizeProject(BaseProject):
with filepath.open('wb') as f: with filepath.open('wb') as f:
yaml.dump(kustomization, 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): class DirectoryProject(BaseProject):
kind: Literal['dir'] | Literal['directory'] kind: Literal['dir'] | Literal['directory']
@ -195,7 +220,11 @@ class RepoConfig(pydantic.BaseModel):
return data['clone_url'] return data['clone_url']
def create_pr( 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: ) -> None:
session = _get_session() session = _get_session()
r = session.post( r = session.post(
@ -207,6 +236,7 @@ class RepoConfig(pydantic.BaseModel):
'title': title, 'title': title,
'base': target_branch, 'base': target_branch,
'head': source_branch, 'head': source_branch,
'body': body,
}, },
) )
log.log(TRACE, '%r', r.content) log.log(TRACE, '%r', r.content)
@ -237,7 +267,7 @@ class Arguments:
def update_project( def update_project(
repo: git.Repo, name: str, project: Project repo: git.Repo, name: str, project: Project
) -> Optional[git.Commit]: ) -> tuple[Optional[git.Commit], Optional[str]]:
basedir = Path(repo.working_dir) basedir = Path(repo.working_dir)
log.debug('Checking for latest version of %s', name) log.debug('Checking for latest version of %s', name)
latest = project.source.get_latest_version() latest = project.source.get_latest_version()
@ -250,10 +280,12 @@ def update_project(
repo.index.add(str(path)) repo.index.add(str(path))
c = repo.index.commit(f'{name}: Update to {latest}') c = repo.index.commit(f'{name}: Update to {latest}')
log.info('Commited %s %s', str(c)[:7], c.summary) 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: else:
log.info('No changes to commit') log.info('No changes to commit')
return None return (None, None)
def parse_args() -> Arguments: def parse_args() -> Arguments:
@ -324,8 +356,11 @@ def main() -> None:
log.debug('Checking out new branch: %s', args.branch_name) log.debug('Checking out new branch: %s', args.branch_name)
repo.heads[0].checkout(force=True, B=args.branch_name) repo.heads[0].checkout(force=True, B=args.branch_name)
title = None title = None
pr_desc = ''
for project in projects: 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 commit and not title:
if not isinstance(commit.summary, str): if not isinstance(commit.summary, str):
title = bytes(commit.summary).decode( title = bytes(commit.summary).decode(
@ -333,17 +368,29 @@ def main() -> None:
) )
else: else:
title = commit.summary title = commit.summary
if diff:
pr_desc += diff
if not title: if not title:
log.info('No changes made') log.info('No changes made')
return return
repo.head.reference.set_tracking_branch(
git.RemoteReference(
repo, f'refs/remotes/origin/{args.branch_name}'
)
)
if not args.dry_run: if not args.dry_run:
repo.head.reference.set_tracking_branch(
git.RemoteReference(
repo, f'refs/remotes/origin/{args.branch_name}'
)
)
repo.remote().push(force=True) 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__': if __name__ == '__main__':