github: full GraphQL API support

there is currently not GraphQL API equivalent to the REST API's
`/repos/{owner}/{repo}/commits/{ref}` endpoint.
This commit is contained in:
Dusk Banks 2022-02-22 20:45:11 -08:00
parent 03a83d8278
commit 4d5c102f15
2 changed files with 108 additions and 48 deletions

View file

@ -409,6 +409,12 @@ use_max_tag
lightweight ones, and return the largest one sorted by the lightweight ones, and return the largest one sorted by the
``sort_version_key`` option. Will return the tag name instead of date. ``sort_version_key`` option. Will return the tag name instead of date.
This defaults ``list_count`` to 100.
list_count
When supporting :ref:`list options` through the v4 GraphQL API, this sets a
maximum count of items in the list. By default, ``list_count`` is set to 1.
token token
A personal authorization token used to call the API. A personal authorization token used to call the API.
@ -421,6 +427,8 @@ To set an authorization token, you can set:
- the token option - the token option
This source supports :ref:`list options` when ``use_max_tag`` is set. This source supports :ref:`list options` when ``use_max_tag`` is set.
Options of this source that support :ref:`list options` may be effected by
``list_count``.
Check Gitea Check Gitea
~~~~~~~~~~~ ~~~~~~~~~~~

View file

@ -1,10 +1,9 @@
# MIT licensed # MIT licensed
# Copyright (c) 2013-2020 lilydjwg <lilydjwg@gmail.com>, et al. # Copyright (c) 2013-2020 lilydjwg <lilydjwg@gmail.com>, et al.
import itertools
import time import time
from urllib.parse import urlencode from urllib.parse import urlencode
from typing import Any, Dict, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple
import structlog import structlog
@ -77,27 +76,76 @@ async def query_rest(
return await cache.get_json(url = url, headers = headers) return await cache.get_json(url = url, headers = headers)
QUERY_LATEST_TAG = ''' QUERY_LATEST_TAGS = '''
query latestTag( query latestTags(
$owner: String!, $name: String!, $owner: String!, $name: String!,
$query: String, $includeCommitName: Boolean = false, $query: String, $orderByCommitDate: Boolean!, $count: Int = 1,
$includeCommitName: Boolean = false,
) { ) {
repository(owner: $owner, name: $name) { repository(owner: $owner, name: $name) {
refs( ... @include(if: $orderByCommitDate) { latestRefs: refs(
refPrefix: "refs/tags/", query: $query, refPrefix: "refs/tags/", query: $query,
first: 1, orderBy: {field: TAG_COMMIT_DATE, direction: DESC}, first: $count, orderBy: {field: TAG_COMMIT_DATE, direction: DESC}
) { ) { ...tagData } }
edges { ... @skip(if: $orderByCommitDate) { maxRefs: refs(
node { refPrefix: "refs/tags/", query: $query,
name last: $count
... @include(if: $includeCommitName) { target { oid } } ) { ...tagData } }
} }
} }
fragment tagData on RefConnection {
edges {
node {
name
... @include(if: $includeCommitName) { target { ...commitOid } }
} }
} }
} }
fragment commitOid on GitObject {
... on Commit { commitOid: oid }
... on Tag { tagTarget: target {
... on Commit { commitOid: oid }
} }
}
''' '''
async def query_latest_tags(
*,
cache: AsyncCache,
token: Optional[str] = None,
owner: str,
name: str,
query: Optional[str],
order_by_commit_date: bool,
count: Optional[int] = None,
use_commit_name: bool,
) -> List[str]:
j = await query_graphql(
cache = cache,
token = token,
query = QUERY_LATEST_TAGS,
variables = {
'owner': owner,
'name': name,
'query': query,
'orderByCommitDate': order_by_commit_date,
'count': count,
'includeCommitName': use_commit_name,
},
)
refsAlias = 'latestRefs' if order_by_commit_date else 'maxRefs'
refs = j['data']['repository'][refsAlias]['edges']
if not order_by_commit_date:
refs = reversed(refs)
tags = [
add_commit_name(
ref['node']['name'],
ref['node']['target']['commitOid'] if use_commit_name else None,
)
for ref in refs
]
return tags
QUERY_LATEST_RELEASE = ''' QUERY_LATEST_RELEASE = '''
query latestRelease( query latestRelease(
$owner: String!, $name: String!, $owner: String!, $name: String!,
@ -128,28 +176,18 @@ async def get_version_real(
if conf.get('use_latest_tag', False): if conf.get('use_latest_tag', False):
owner, reponame = repo.split('/') owner, reponame = repo.split('/')
j = await query_graphql( tags = await query_latest_tags(
cache = cache, cache = cache,
token = token, token = token,
query = QUERY_LATEST_TAG, owner = owner,
variables = { name = reponame,
'owner': owner, query = conf.get('query'),
'name': reponame, order_by_commit_date = True,
'query': conf.get('query'), use_commit_name = use_commit_name,
'includeCommitName': use_commit_name,
},
) )
refs = j['data']['repository']['refs']['edges'] if not tags:
if not refs: raise GetVersionError('No tag found in upstream repository.')
raise GetVersionError('no tag found') return tags[0]
ref = next(
add_commit_name(
ref['node']['name'],
ref['node']['target']['oid'] if use_commit_name else None,
)
for ref in refs
)
return ref
elif conf.get('use_latest_release', False): elif conf.get('use_latest_release', False):
tag = None tag = None
if token: if token:
@ -182,18 +220,31 @@ async def get_version_real(
raise GetVersionError('No release found in upstream repository.') raise GetVersionError('No release found in upstream repository.')
return tag return tag
elif conf.get('use_max_tag', False): elif conf.get('use_max_tag', False):
data = await query_rest( if token:
cache = cache, owner, reponame = repo.split('/')
token = token, tags = await query_latest_tags(
url = GITHUB_MAX_TAG % repo, cache = cache,
) token = token,
tags = [ owner = owner,
add_commit_name( name = reponame,
ref['ref'].split('/', 2)[-1], query = conf.get('query'),
ref['object']['sha'] if use_commit_name else None, order_by_commit_date = False,
count = conf.get('list_count', 100),
use_commit_name = use_commit_name,
) )
for ref in data else:
] data = await query_rest(
cache = cache,
token = token,
url = GITHUB_MAX_TAG % repo,
)
tags = [
add_commit_name(
ref['ref'].split('/', 2)[-1],
ref['object']['sha'] if use_commit_name else None,
)
for ref in data
]
if not tags: if not tags:
raise GetVersionError('No tag found in upstream repository.') raise GetVersionError('No tag found in upstream repository.')
return tags return tags
@ -211,11 +262,12 @@ async def get_version_real(
url = GITHUB_URL % repo, url = GITHUB_URL % repo,
parameters = parameters, parameters = parameters,
) )
# YYYYMMDD.HHMMSS date = data[0]['commit']['committer']['date']
commit_name = data[0]['sha'] if use_commit_name else None
version = add_commit_name( version = add_commit_name(
data[0]['commit']['committer']['date'] \ # YYYYMMDD.HHMMSS
.rstrip('Z').replace('-', '').replace(':', '').replace('T', '.'), date.rstrip('Z').replace('-', '').replace(':', '').replace('T', '.'),
data[0]['sha'] if use_commit_name else None, commit_name,
) )
return version return version