aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/run_tests/python_utils/check_on_pr.py
blob: 3f335c8ea93e8953a67e7487329b735a9f1a292c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# Copyright 2018 The gRPC Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function
import os
import json
import time
import datetime

import requests
import jwt

_GITHUB_API_PREFIX = 'https://api.github.com'
_GITHUB_REPO = 'grpc/grpc'
_GITHUB_APP_ID = 22338
_INSTALLATION_ID = 519109

_ACCESS_TOKEN_CACHE = None


def _jwt_token():
    github_app_key = open(
        os.path.join(os.environ['KOKORO_KEYSTORE_DIR'],
                     '73836_grpc_checks_private_key'), 'rb').read()
    return jwt.encode(
        {
            'iat': int(time.time()),
            'exp': int(time.time() + 60 * 10),  # expire in 10 minutes
            'iss': _GITHUB_APP_ID,
        },
        github_app_key,
        algorithm='RS256')


def _access_token():
    global _ACCESS_TOKEN_CACHE
    if _ACCESS_TOKEN_CACHE == None or _ACCESS_TOKEN_CACHE['exp'] < time.time():
        resp = requests.post(
            url='https://api.github.com/app/installations/%s/access_tokens' %
            _INSTALLATION_ID,
            headers={
                'Authorization': 'Bearer %s' % _jwt_token().decode('ASCII'),
                'Accept': 'application/vnd.github.machine-man-preview+json',
            })
        _ACCESS_TOKEN_CACHE = {
            'token': resp.json()['token'],
            'exp': time.time() + 60
        }
    return _ACCESS_TOKEN_CACHE['token']


def _call(url, method='GET', json=None):
    if not url.startswith('https://'):
        url = _GITHUB_API_PREFIX + url
    headers = {
        'Authorization': 'Bearer %s' % _access_token(),
        'Accept': 'application/vnd.github.antiope-preview+json',
    }
    return requests.request(method=method, url=url, headers=headers, json=json)


def _latest_commit():
    resp = _call('/repos/%s/pulls/%s/commits' %
                 (_GITHUB_REPO,
                  os.environ['KOKORO_GITHUB_PULL_REQUEST_NUMBER']))
    return resp.json()[-1]


def check_on_pr(name, summary, success=True):
    """Create/Update a check on current pull request.

    The check runs are aggregated by their name, so newer check will update the
    older check with the same name.

    Requires environment variable 'KOKORO_GITHUB_PULL_REQUEST_NUMBER' to indicate which pull request
    should be updated.

    Args:
      name: The name of the check.
      summary: A str in Markdown to be used as the detail information of the check.
      success: A bool indicates whether the check is succeed or not.
    """
    if 'KOKORO_GIT_COMMIT' not in os.environ:
        print('Missing KOKORO_GIT_COMMIT env var: not checking')
        return
    if 'KOKORO_KEYSTORE_DIR' not in os.environ:
        print('Missing KOKORO_KEYSTORE_DIR env var: not checking')
        return
    if 'KOKORO_GITHUB_PULL_REQUEST_NUMBER' not in os.environ:
        print('Missing KOKORO_GITHUB_PULL_REQUEST_NUMBER env var: not checking')
        return
    completion_time = str(
        datetime.datetime.utcnow().replace(microsecond=0).isoformat()) + 'Z'
    resp = _call(
        '/repos/%s/check-runs' % _GITHUB_REPO,
        method='POST',
        json={
            'name': name,
            'head_sha': os.environ['KOKORO_GIT_COMMIT'],
            'status': 'completed',
            'completed_at': completion_time,
            'conclusion': 'success' if success else 'failure',
            'output': {
                'title': name,
                'summary': summary,
            }
        })
    print('Result of Creating/Updating Check on PR:',
          json.dumps(resp.json(), indent=2))