mirror of
				https://github.com/docker/compose.git
				synced 2025-10-31 03:03:49 +01:00 
			
		
		
		
	Get candidates from moby/moby and docker/docker-ce repos Signed-off-by: Joffrey F <joffrey@docker.com>
		
			
				
	
	
		
			163 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env python
 | |
| """
 | |
| Query the github API for the git tags of a project, and return a list of
 | |
| version tags for recent releases, or the default release.
 | |
| 
 | |
| The default release is the most recent non-RC version.
 | |
| 
 | |
| Recent is a list of unique major.minor versions, where each is the most
 | |
| recent version in the series.
 | |
| 
 | |
| For example, if the list of versions is:
 | |
| 
 | |
|     1.8.0-rc2
 | |
|     1.8.0-rc1
 | |
|     1.7.1
 | |
|     1.7.0
 | |
|     1.7.0-rc1
 | |
|     1.6.2
 | |
|     1.6.1
 | |
| 
 | |
| `default` would return `1.7.1` and
 | |
| `recent -n 3` would return `1.8.0-rc2 1.7.1 1.6.2`
 | |
| """
 | |
| from __future__ import absolute_import
 | |
| from __future__ import print_function
 | |
| from __future__ import unicode_literals
 | |
| 
 | |
| import argparse
 | |
| import itertools
 | |
| import operator
 | |
| import sys
 | |
| from collections import namedtuple
 | |
| 
 | |
| import requests
 | |
| 
 | |
| 
 | |
| GITHUB_API = 'https://api.github.com/repos'
 | |
| 
 | |
| 
 | |
| class Version(namedtuple('_Version', 'major minor patch rc edition')):
 | |
| 
 | |
|     @classmethod
 | |
|     def parse(cls, version):
 | |
|         edition = None
 | |
|         version = version.lstrip('v')
 | |
|         version, _, rc = version.partition('-')
 | |
|         if rc:
 | |
|             if 'rc' not in rc:
 | |
|                 edition = rc
 | |
|                 rc = None
 | |
|             elif '-' in rc:
 | |
|                 edition, rc = rc.split('-')
 | |
| 
 | |
|         major, minor, patch = version.split('.', 3)
 | |
|         return cls(major, minor, patch, rc, edition)
 | |
| 
 | |
|     @property
 | |
|     def major_minor(self):
 | |
|         return self.major, self.minor
 | |
| 
 | |
|     @property
 | |
|     def order(self):
 | |
|         """Return a representation that allows this object to be sorted
 | |
|         correctly with the default comparator.
 | |
|         """
 | |
|         # rc releases should appear before official releases
 | |
|         rc = (0, self.rc) if self.rc else (1, )
 | |
|         return (int(self.major), int(self.minor), int(self.patch)) + rc
 | |
| 
 | |
|     def __str__(self):
 | |
|         rc = '-{}'.format(self.rc) if self.rc else ''
 | |
|         edition = '-{}'.format(self.edition) if self.edition else ''
 | |
|         return '.'.join(map(str, self[:3])) + edition + rc
 | |
| 
 | |
| 
 | |
| def group_versions(versions):
 | |
|     """Group versions by `major.minor` releases.
 | |
| 
 | |
|     Example:
 | |
| 
 | |
|         >>> group_versions([
 | |
|                 Version(1, 0, 0),
 | |
|                 Version(2, 0, 0, 'rc1'),
 | |
|                 Version(2, 0, 0),
 | |
|                 Version(2, 1, 0),
 | |
|             ])
 | |
| 
 | |
|         [
 | |
|             [Version(1, 0, 0)],
 | |
|             [Version(2, 0, 0), Version(2, 0, 0, 'rc1')],
 | |
|             [Version(2, 1, 0)],
 | |
|         ]
 | |
|     """
 | |
|     return list(
 | |
|         list(releases)
 | |
|         for _, releases
 | |
|         in itertools.groupby(versions, operator.attrgetter('major_minor'))
 | |
|     )
 | |
| 
 | |
| 
 | |
| def get_latest_versions(versions, num=1):
 | |
|     """Return a list of the most recent versions for each major.minor version
 | |
|     group.
 | |
|     """
 | |
|     versions = group_versions(versions)
 | |
|     num = min(len(versions), num)
 | |
|     return [versions[index][0] for index in range(num)]
 | |
| 
 | |
| 
 | |
| def get_default(versions):
 | |
|     """Return a :class:`Version` for the latest non-rc version."""
 | |
|     for version in versions:
 | |
|         if not version.rc:
 | |
|             return version
 | |
| 
 | |
| 
 | |
| def get_versions(tags):
 | |
|     for tag in tags:
 | |
|         try:
 | |
|             yield Version.parse(tag['name'])
 | |
|         except ValueError:
 | |
|             print("Skipping invalid tag: {name}".format(**tag), file=sys.stderr)
 | |
| 
 | |
| 
 | |
| def get_github_releases(projects):
 | |
|     """Query the Github API for a list of version tags and return them in
 | |
|     sorted order.
 | |
| 
 | |
|     See https://developer.github.com/v3/repos/#list-tags
 | |
|     """
 | |
|     versions = []
 | |
|     for project in projects:
 | |
|         url = '{}/{}/tags'.format(GITHUB_API, project)
 | |
|         response = requests.get(url)
 | |
|         response.raise_for_status()
 | |
|         versions.extend(get_versions(response.json()))
 | |
|     return sorted(versions, reverse=True, key=operator.attrgetter('order'))
 | |
| 
 | |
| 
 | |
| def parse_args(argv):
 | |
|     parser = argparse.ArgumentParser(description=__doc__)
 | |
|     parser.add_argument('project', help="Github project name (ex: docker/docker)")
 | |
|     parser.add_argument('command', choices=['recent', 'default'])
 | |
|     parser.add_argument('-n', '--num', type=int, default=2,
 | |
|                         help="Number of versions to return from `recent`")
 | |
|     return parser.parse_args(argv)
 | |
| 
 | |
| 
 | |
| def main(argv=None):
 | |
|     args = parse_args(argv)
 | |
|     versions = get_github_releases(args.project.split(','))
 | |
| 
 | |
|     if args.command == 'recent':
 | |
|         print(' '.join(map(str, get_latest_versions(versions, args.num))))
 | |
|     elif args.command == 'default':
 | |
|         print(get_default(versions))
 | |
|     else:
 | |
|         raise ValueError("Unknown command {}".format(args.command))
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     main()
 |