@@ -0,0 +1,2062 @@
+#!/usr/bin/env python%0A%0Aimport argparse%0Aimport json%0Aimport sys%0Aimport os%0A%0Aimport requests%0A%0Afrom googleapiclient import discovery%0Afrom oauth2client.client import GoogleCredentials%0A%0A%0Aparser = argparse.ArgumentParser()%0Aparser.add_argument('repo', help='GitHub organization and repository')%0Aparser.add_argument('bucket', help='Cloud Storage bucket')%0Aparser.add_argument('--delete', action='store_true', help='Delete extraneous objects in storage bucket')%0Aargs = parser.parse_args(sys.argv%5B1:%5D or %5B'-h'%5D)%0A%0A%0Acredentials = GoogleCredentials.get_application_default()%0Astorage = discovery.build('storage', 'v1', credentials=credentials)%0A%0Astorage_objects = storage.objects().list(bucket=args.bucket).execute()%5B'items'%5D%0Astorage_objects = %7Bos.path.splitext(o%5B'name'%5D)%5B0%5D: o for o in storage_objects%7D%0A%0Agit_tree = requests.get('https://api.github.com/repos/%25s/git/trees/HEAD?recursive=true' %25 args.repo).json()%0Amanifests = %7Bos.path.basename(gto%5B'path'%5D).split('.')%5B0%5D: gto for gto in git_tree%5B'tree'%5D if%0A    gto%5B'type'%5D == 'blob' and%0A    gto%5B'path'%5D.startswith('manifests') and%0A    gto%5B'path'%5D.endswith('.json')%0A%7D%0A%0A%0Aif set(storage_objects) == set(manifests):%0A    print 'All manifests and storage objects accounted for'%0Aelse:%0A    ## Do we have a storage object for each manifest?%0A    for m in manifests:%0A        if m not in storage_objects:%0A            print 'Missing storage object for %25s' %25 m%0A%0A    ## Do we have a manifest for each storage object?%0A    extraneous_objects = %5B%5D%0A    for so_key, so in storage_objects.iteritems():%0A        if so_key not in manifests:%0A            print 'Missing manifest for %25s' %25 so_key%0A            extraneous_objects.append(so)%0A%0A    if args.delete and extraneous_objects:%0A        try:%0A            raw_input('%5CnPress Enter to delete %25d storage objects or Ctrl-C to abort...' %25 len(extraneous_objects))%0A        except KeyboardInterrupt:%0A            print%0A            sys.exit(1)%0A        for so in extraneous_objects:%0A            print 'Deleting %25s' %25 so%5B'name'%5D%0A            storage.objects().delete(bucket=args.bucket, object=so%5B'name'%5D).execute()%0A

Add storage/manifest validation script