diff --git a/docs/usage.rst b/docs/usage.rst index 3690e8c..e733049 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -390,6 +390,12 @@ use_latest_release Will return the release name instead of date. +include_prereleases + When ``use_latest_release`` is ``true``, set this to ``true`` to take prereleases into + account. + + This requires a token because it's using the v4 GraphQL API. + use_latest_tag Set this to ``true`` to check for the latest tag on GitHub. @@ -408,8 +414,8 @@ use_max_tag token A personal authorization token used to call the API. -An authorization token may be needed in order to use ``use_latest_tag`` or to -request more frequently than anonymously. +An authorization token may be needed in order to use ``use_latest_tag``, +``include_prereleases`` or to request more frequently than anonymously. To set an authorization token, you can set: diff --git a/nvchecker_source/github.py b/nvchecker_source/github.py index 0920d54..0d512c2 100644 --- a/nvchecker_source/github.py +++ b/nvchecker_source/github.py @@ -42,6 +42,20 @@ QUERY_LATEST_TAG = ''' }} ''' +QUERY_LATEST_RELEASE_WITH_PRERELEASES = ''' +{{ + repository(name: "{name}", owner: "{owner}") {{ + releases(first: 1, orderBy: {{field: CREATED_AT, direction: DESC}}) {{ + edges {{ + node {{ + name + }} + }} + }} + }} +}} +''' + async def get_latest_tag(key: Tuple[str, str, str]) -> str: repo, query, token = key owner, reponame = repo.split('/') @@ -68,6 +82,31 @@ async def get_latest_tag(key: Tuple[str, str, str]) -> str: return refs[0]['node']['name'] +async def get_latest_release_with_prereleases(key: Tuple[str, str]) -> str: + repo, token = key + owner, reponame = repo.split('/') + headers = { + 'Authorization': f'bearer {token}', + 'Content-Type': 'application/json', + } + q = QUERY_LATEST_RELEASE_WITH_PRERELEASES.format( + owner = owner, + name = reponame, + ) + + res = await session.post( + GITHUB_GRAPHQL_URL, + headers = headers, + json = {'query': q}, + ) + j = res.json() + + refs = j['data']['repository']['releases']['edges'] + if not refs: + raise GetVersionError('no release found') + + return refs[0]['node']['name'] + async def get_version_real( name: str, conf: Entry, *, cache: AsyncCache, keymanager: KeyManager, @@ -89,9 +128,16 @@ async def get_version_real( query = conf.get('query', '') return await cache.get((repo, query, token), get_latest_tag) # type: ignore + use_latest_release = conf.get('use_latest_release', False) + include_prereleases = conf.get('include_prereleases', False) + if use_latest_release and include_prereleases: + if not token: + raise GetVersionError('token not given but it is required') + + return await cache.get((repo, token), get_latest_release_with_prereleases) # type: ignore + br = conf.get('branch') path = conf.get('path') - use_latest_release = conf.get('use_latest_release', False) use_max_tag = conf.get('use_max_tag', False) if use_latest_release: url = GITHUB_LATEST_RELEASE % repo diff --git a/tests/test_github.py b/tests/test_github.py index c505c83..23cef9a 100644 --- a/tests/test_github.py +++ b/tests/test_github.py @@ -24,9 +24,17 @@ async def test_github_default_not_master(get_version): async def test_github_latest_release(get_version): assert await get_version("example", { "source": "github", - "github": "harry-sanabria/ReleaseTestRepo", + "github": "dpeukert/ReleaseTestRepo", "use_latest_release": True, - }) == "release3" + }) == "v0.0.0" + +async def test_github_latest_release_include_prereleases(get_version): + assert await get_version("example", { + "source": "github", + "github": "dpeukert/ReleaseTestRepo", + "use_latest_release": True, + "include_prereleases": True, + }) == "v0.0.1-pre" async def test_github_max_tag(get_version): assert await get_version("example", {