diff --git a/docs/usage.rst b/docs/usage.rst
index c5ea879..60f3cc4 100644
--- a/docs/usage.rst
+++ b/docs/usage.rst
@@ -365,8 +365,8 @@ Check GitHub
source = "github"
Check `GitHub `_ for updates. The version returned is in
-date format ``%Y%m%d.%H%M%S``, e.g. ``20130701.012212``, unless ``use_latest_release``
-or ``use_max_tag`` is used. See below.
+date format ``%Y%m%d.%H%M%S``, e.g. ``20130701.012212``, unless ``use_latest_release``,
+``use_max_tag``, or ``use_commit_name`` is used. See below.
github
The github repository, with author, e.g. ``lilydjwg/nvchecker``.
@@ -393,6 +393,10 @@ use_latest_tag
This requires a token because it's using the v4 GraphQL API.
+use_commit_name
+ Set this to ``true`` to append a plus and the commit name to the version, e.g.
+ ``20130701.012212+e1457aadd30f53f4d50d6c4828d517355c09b8ae``.
+
query
When ``use_latest_tag`` is ``true``, this sets a query for the tag. The exact
matching method is not documented by GitHub.
diff --git a/nvchecker_source/github.py b/nvchecker_source/github.py
index 0920d54..84eedde 100644
--- a/nvchecker_source/github.py
+++ b/nvchecker_source/github.py
@@ -1,9 +1,10 @@
# MIT licensed
# Copyright (c) 2013-2020 lilydjwg , et al.
+import itertools
import time
from urllib.parse import urlencode
-from typing import Tuple
+from typing import Optional, Tuple
import structlog
@@ -14,6 +15,9 @@ from nvchecker.api import (
logger = structlog.get_logger(logger_name=__name__)
+def add_commit_name(version: str, commit_name: Optional[str]) -> str:
+ return version if commit_name is None else version + '+' + commit_name
+
GITHUB_URL = 'https://api.github.com/repos/%s/commits'
GITHUB_LATEST_RELEASE = 'https://api.github.com/repos/%s/releases/latest'
# https://developer.github.com/v3/git/refs/#get-all-references
@@ -27,38 +31,45 @@ async def get_version(name, conf, **kwargs):
check_ratelimit(e, name)
QUERY_LATEST_TAG = '''
-{{
- repository(name: "{name}", owner: "{owner}") {{
- refs(refPrefix: "refs/tags/", first: 1,
- query: "{query}",
- orderBy: {{field: TAG_COMMIT_DATE, direction: DESC}}) {{
- edges {{
- node {{
+query latestTag(
+ $owner: String!, $name: String!,
+ $query: String, $includeCommitName: Boolean = false,
+) {
+ repository(owner: $owner, name: $name) {
+ refs(
+ refPrefix: "refs/tags/", query: $query,
+ first: 1, orderBy: {field: TAG_COMMIT_DATE, direction: DESC},
+ ) {
+ edges {
+ node {
name
- }}
- }}
- }}
- }}
-}}
+ ... @include(if: $includeCommitName) { target { oid } }
+ }
+ }
+ }
+ }
+}
'''
-async def get_latest_tag(key: Tuple[str, str, str]) -> str:
- repo, query, token = key
+async def get_latest_tag(key: Tuple[str, Optional[str], str, bool]) -> str:
+ repo, query, token, use_commit_name = key
owner, reponame = repo.split('/')
headers = {
'Authorization': f'bearer {token}',
'Content-Type': 'application/json',
}
- q = QUERY_LATEST_TAG.format(
- owner = owner,
- name = reponame,
- query = query,
- )
+ variables = {
+ 'owner': owner,
+ 'name': reponame,
+ 'includeCommitName': use_commit_name,
+ }
+ if query is not None:
+ variables['query'] = query
res = await session.post(
GITHUB_GRAPHQL_URL,
headers = headers,
- json = {'query': q},
+ json = {'query': QUERY_LATEST_TAG, 'variables': variables},
)
j = res.json()
@@ -66,7 +77,10 @@ async def get_latest_tag(key: Tuple[str, str, str]) -> str:
if not refs:
raise GetVersionError('no tag found')
- return refs[0]['node']['name']
+ return next(add_commit_name(
+ ref['node']['name'],
+ ref['node']['target']['oid'] if use_commit_name else None,
+ ) for ref in refs)
async def get_version_real(
name: str, conf: Entry, *,
@@ -82,12 +96,13 @@ async def get_version_real(
token = keymanager.get_key('github')
use_latest_tag = conf.get('use_latest_tag', False)
+ use_commit_name = conf.get('use_commit_name', False)
if use_latest_tag:
if not token:
raise GetVersionError('token not given but it is required')
- query = conf.get('query', '')
- return await cache.get((repo, query, token), get_latest_tag) # type: ignore
+ query = conf.get('query')
+ return await cache.get((repo, query, token, use_commit_name), get_latest_tag) # type: ignore
br = conf.get('branch')
path = conf.get('path')
@@ -114,7 +129,10 @@ async def get_version_real(
data = await cache.get_json(url, headers = headers)
if use_max_tag:
- tags = [ref['ref'].split('/', 2)[-1] for ref in data]
+ 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:
raise GetVersionError('No tag found in upstream repository.')
return tags
@@ -126,8 +144,11 @@ async def get_version_real(
else:
# YYYYMMDD.HHMMSS
- version = data[0]['commit']['committer']['date'] \
- .rstrip('Z').replace('-', '').replace(':', '').replace('T', '.')
+ version = add_commit_name(
+ data[0]['commit']['committer']['date'] \
+ .rstrip('Z').replace('-', '').replace(':', '').replace('T', '.'),
+ data[0]['sha'] if use_commit_name else None,
+ )
return version
diff --git a/tests/test_github.py b/tests/test_github.py
index c505c83..2c9b3e6 100644
--- a/tests/test_github.py
+++ b/tests/test_github.py
@@ -15,6 +15,13 @@ async def test_github(get_version):
"github": "harry-sanabria/ReleaseTestRepo",
}) == "20140122.012101"
+async def test_github_commit_name(get_version):
+ assert await get_version("example", {
+ "source": "github",
+ "github": "harry-sanabria/ReleaseTestRepo",
+ "use_commit_name": True,
+ }) == "20140122.012101+2b3cdf6134b07ae6ac77f11b586dc1ae6d1521db"
+
async def test_github_default_not_master(get_version):
assert await get_version("example", {
"source": "github",
@@ -35,6 +42,14 @@ async def test_github_max_tag(get_version):
"use_max_tag": True,
}) == "second_release"
+async def test_github_max_tag_commit_name(get_version):
+ assert await get_version("example", {
+ "source": "github",
+ "github": "harry-sanabria/ReleaseTestRepo",
+ "use_max_tag": True,
+ "use_commit_name": True,
+ }) == "second_release+0f01b10ee72809e7ec0d903db95bcb6eef18c925"
+
async def test_github_max_tag_with_ignored(get_version):
assert await get_version("example", {
"source": "github",
@@ -74,3 +89,11 @@ async def test_github_latest_tag(get_version):
"use_latest_tag": True,
}) == "release3"
+async def test_github_latest_tag_commit_name(get_version):
+ assert await get_version("example", {
+ "source": "github",
+ "github": "harry-sanabria/ReleaseTestRepo",
+ "use_latest_tag": True,
+ "use_commit_name": True,
+ }) == "release3+2b3cdf6134b07ae6ac77f11b586dc1ae6d1521db"
+