github.phpd.cn/thought-machine/please@v12.2.0+incompatible/tools/misc/gen_release.py (about)

     1  #!/usr/bin/env python3
     2  """Script to create Github releases & generate release notes."""
     3  
     4  import json
     5  import logging
     6  import os
     7  import subprocess
     8  import sys
     9  from third_party.python import requests
    10  
    11  
    12  class ReleaseGen:
    13  
    14      def __init__(self, version):
    15          if 'GITHUB_TOKEN' not in os.environ:
    16              logging.warning('Unless GITHUB_TOKEN is specified, your requests will likely fail')
    17          self.url = 'https://api.github.com'
    18          self.session = requests.Session()
    19          self.session.headers.update({
    20              'Accept': 'application/vnd.github.v3+json',
    21              'Authorization': 'token ' + os.environ.get('GITHUB_TOKEN', ''),
    22          })
    23          self.version = version or self.get_current_version()
    24          self.version_name = 'Version ' + self.version
    25  
    26      def get_current_version(self):
    27          """Loads the current version from the repo."""
    28          with open('VERSION') as f:
    29              return f.read().strip()
    30  
    31      def get_latest_release_version(self):
    32          """Gets the latest released version from Github."""
    33          response = self.session.get(self.url + '/repos/thought-machine/please/releases/latest')
    34          response.raise_for_status()
    35          return json.loads(response.text).get('tag_name').lstrip('v')
    36  
    37      def release(self):
    38          """Submits a new release to Github."""
    39          tag = self.tag_release(self.get_release_sha())
    40          data = {
    41              'tag_name': tag,
    42              'name': 'Please v' + self.version,
    43              'body': ''.join(self.get_release_notes()),
    44              'prerelease': 'a' in self.version or 'b' in self.version,
    45          }
    46          response = self.session.post(self.url + '/repos/thought-machine/please/releases', json=data)
    47          print(response.text)
    48          response.raise_for_status()
    49  
    50      def tag_release(self, commit_sha):
    51          """Tags the release at the given commit (& matching date)."""
    52          tag = 'v' + self.version
    53          # Have to tag at the correct time.
    54          commit_date = subprocess.check_output(['git', 'show', '-s', '--format=%ci', commit_sha]).decode('utf-8').strip()
    55          env = os.environ.copy()
    56          env['GIT_COMMITTER_DATE'] = commit_date
    57          subprocess.check_call(['git', 'tag', '-a', tag, commit_sha, '-m', 'Please ' + tag], env=env)
    58          subprocess.check_call(['git', 'push', 'origin', tag])
    59          return tag
    60  
    61      def get_release_sha(self):
    62          """Retrieves the Git commit corresponding to the given release."""
    63          for line in subprocess.check_output(['git', 'blame', 'ChangeLog']).decode('utf-8').split('\n'):
    64              if self.version_name in line:
    65                  # Convert short SHA to full one
    66                  return subprocess.check_output(['git', 'rev-parse', line.split(' ')[0]]).decode('utf-8').strip()
    67          raise Exception("Couldn't determine git sha for " + self.version_name)
    68  
    69      def get_release_notes(self):
    70          """Yields the changelog notes for a given version."""
    71          with open('ChangeLog') as f:
    72              found_version = False
    73              for line in f:
    74                  if line.startswith(self.version_name):
    75                      found_version = True
    76                      yield 'This is Please v%s' % self.version
    77                  elif line.startswith('------'):
    78                      continue
    79                  elif found_version:
    80                      if line.startswith('Version '):
    81                          return
    82                      elif line.startswith('   '):
    83                          # Markdown comes out nicer if we remove some of the spacing.
    84                          line = line[3:]
    85                      yield line
    86          raise Exception("Couldn't find release notes for " + self.version_name)
    87  
    88  
    89  if __name__ == '__main__':
    90      r = ReleaseGen(sys.argv[1] if len(sys.argv) >= 2 else None)
    91      r.release()