Skip to content

Commit

Permalink
refactor: split and overhaul github.util
Browse files Browse the repository at this point in the history
Introduce dedicated module for managing limits of GitHub-API. Also,
create new module for GitHub-Release-specific code.
  • Loading branch information
ccwienk committed Jan 28, 2025
1 parent 44b25dc commit 629d76b
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 40 deletions.
15 changes: 12 additions & 3 deletions .github/actions/draft-release/update_draft_release.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
print(f'note: added {repo_root} to python-path (sys.path)')
import github.util

import github.release
import version as version_mod


Expand Down Expand Up @@ -76,16 +77,24 @@ def main():
name=repo,
github_api=github_api,
)
repository = github_helper.repository

with open(parsed.release_notes) as f:
release_notes_md = f.read()

draft_release_name = f'{version}{parsed.draftname_suffix}'
if not (draft_release := github_helper.draft_release_with_name(draft_release_name)):
release_notes_md = github.release.body_or_replacement(
release_notes_md,
)
if not (draft_release := github.release.find_draft_release(
repository=repository,
name=draft_release_name,
)):
print(f'Creating {draft_release_name=}')
github_helper.create_draft_release(
name=draft_release_name,
repository.create_release(
tag_name=draft_release_name,
body=release_notes_md,
draft=True,
)
else:
if not draft_release.body == release_notes_md:
Expand Down
24 changes: 17 additions & 7 deletions concourse/steps/draft_release.mako
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import ci.log
import ci.util
import cnudie.retrieve
import cnudie.util
import github.release
import github.util
import gitutil
import ocm
Expand Down Expand Up @@ -122,18 +123,27 @@ except ValueError as e:
# repository is already published - usually by steps that erroneously publish them before they should.
release_notes_md = 'no release notes available'
repository = github_helper.repository
draft_name = f'{processed_version}-draft'
draft_release = github_helper.draft_release_with_name(draft_name)
draft_release = github.release.find_draft_release(
repository=repository,
name=draft_name,
)
body = github.body_or_replacement(
body=release_notes_md,
)
if not draft_release:
logger.info(f"Creating draft-release '{draft_name}'")
github_helper.create_draft_release(
name=draft_name,
body=release_notes_md,
logger.info(f"Creating {draft_name=}")
repository.create_release(
tag_name=draft_name,
body=body,
draft=True,
prerelease=False,
)
else:
if not draft_release.body == release_notes_md:
if not draft_release.body == body:
logger.info(f"Updating draft-release '{draft_name}'")
draft_release.edit(body=release_notes_md)
draft_release.edit(body=body)
else:
logger.info('draft release notes are already up to date')
Expand Down
6 changes: 5 additions & 1 deletion concourse/steps/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import concourse.steps.version
import concourse.model.traits.version as version_trait
import dockerutil
import github.release
import release_notes.fetch
import release_notes.markdown
import slackclient.util
Expand Down Expand Up @@ -400,7 +401,10 @@ def github_release(
# github-api expects unqualified tagname
release_tag = release_tag.removeprefix('refs/tags/')

if release := github_helper.draft_release_with_name(f'{release_version}-draft'):
if release := github.release.find_draft_release(
repository=github_helper.repository,
name=f'{release_version}-draft',
):
github_helper.promote_draft_release(
draft_release=release,
release_tag=release_tag,
Expand Down
20 changes: 20 additions & 0 deletions github/limits.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'''
limits for github-api
stolen from: https://github.com/dead-claudia/github-limits
limits refer to amount of codepoints (tested empirically for some samples).
'''

issue_body = 65536
issue_title = 256
pullrequest_body = 262144
release_body = 125000


def fits(
value: str | bytes,
/,
limit: int,
) -> bool:
return len(value) <= limit
55 changes: 55 additions & 0 deletions github/release.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'''
utils wrapping github3.py's relase-API
'''

import github3.repos
import github3.repos.release

import github.limits


def body_or_replacement(
body: str,
replacement: str='body was too large (limit: {limit} / actual: {actual})',
limit: int=github.limits.release_body,
) -> tuple[str, bool]:
'''
convenience function that will check whether given body is short enough to be accepted
by GitHub's API. If so, passed body will be returned as first element of returned tuple, else
replacement value.
The second value of returned tuple will indicate whether original body was returned. Callers
may use this hint to perform a mitigation.
limit may be overwritten (but this is not recommended; see github.limits for more details).
'''
if github.limits.fits(
body,
limit=limit,
):
return body, True

return replacement.format(
limit=limit,
actual=len(body),
), False


def find_draft_release(
repository: github3.repos.Repository,
name: str,
) -> github3.repos.release.Release | None:
'''
finds the given draft-release. For draft-releases, lookup has to be done that way, as
there is no way of directly retrieving a draft-release (as those do not yet have a tag)
'''
# at some point in time, github.com would return http-500 if there were more than 1020
# releases; as draft-releases are typically not too old (and such great numbers of releases
# are uncommon), this should be okay to hardcode. Todo: check whether this limit is still
# valid.
max_releases = 1020
for release in repository.releases(number=max_releases):
if not release.draft:
continue
if release.name == name:
return release
31 changes: 2 additions & 29 deletions github/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


import collections
import datetime
import enum
import logging
import re
Expand All @@ -21,8 +20,8 @@
from github3.pulls import PullRequest
from github3.repos.release import Release

import ocm
import ci.util
import ocm
import version

logger = logging.getLogger(__name__)
Expand All @@ -32,6 +31,7 @@
This limit is not documented explicitly in the GitHub docs. To see it, the error returned by
GitHub when creating a release with more then the allowed number of characters must be
looked at.
as (inofficial) alternative, see: https://github.com/dead-claudia/github-limits
'''
MAXIMUM_GITHUB_RELEASE_BODY_LENGTH = 25000

Expand Down Expand Up @@ -390,18 +390,6 @@ def create_release(
)
return release

def create_draft_release(
self,
name: str,
body: str,
):
return self.create_release(
tag_name='',
name=name,
body=body,
draft=True,
)

def promote_draft_release(
self,
draft_release,
Expand Down Expand Up @@ -468,21 +456,6 @@ def update_release_notes(

return release

def draft_release_with_name(
self,
name: str
) -> Release:
# if there are more than 1021 releases, github(.com) will return http-500 one requesting
# additional releases. As this limit is typically not reached, hardcode limit for now
# in _most_ cases, most recent releases are returned first, so this should hardly ever
# be an actual issue
max_releases = 1020
for release in self.repository.releases(number=max_releases):
if not release.draft:
continue
if release.name == name:
return release

def tag_exists(
self,
tag_name: str,
Expand Down

0 comments on commit 629d76b

Please sign in to comment.