github_message.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. #!/usr/bin/python3
  2. """
  3. Creates Github Releases Notes with content hashes
  4. """
  5. import argparse
  6. import logging
  7. import os
  8. import hashlib
  9. import glob
  10. from github import Github, GithubException, UnknownObjectException
  11. FORMAT = "%(levelname)s - %(asctime)s: %(message)s"
  12. logging.basicConfig(format=FORMAT)
  13. CLOUDFLARED_REPO = os.environ.get("GITHUB_REPO", "cloudflare/cloudflared")
  14. GITHUB_CONFLICT_CODE = "already_exists"
  15. def get_sha256(filename):
  16. """ get the sha256 of a file """
  17. sha256_hash = hashlib.sha256()
  18. with open(filename,"rb") as f:
  19. for byte_block in iter(lambda: f.read(4096),b""):
  20. sha256_hash.update(byte_block)
  21. return sha256_hash.hexdigest()
  22. def update_or_add_message(msg, name, sha):
  23. """
  24. updates or builds the github version message for each new asset's sha256.
  25. Searches the existing message string to update or create.
  26. """
  27. new_text = '{0}: {1}\n'.format(name, sha)
  28. start = msg.find(name)
  29. if (start != -1):
  30. end = msg.find("\n", start)
  31. if (end != -1):
  32. return msg.replace(msg[start:end+1], new_text)
  33. back = msg.rfind("```")
  34. if (back != -1):
  35. return '{0}{1}```'.format(msg[:back], new_text)
  36. return '{0} \n### SHA256 Checksums:\n```\n{1}```'.format(msg, new_text)
  37. def get_release(repo, version):
  38. """ Get a Github Release matching the version tag. """
  39. try:
  40. release = repo.get_release(version)
  41. logging.info("Release %s found", version)
  42. return release
  43. except UnknownObjectException:
  44. logging.info("Release %s not found", version)
  45. def parse_args():
  46. """ Parse and validate args """
  47. parser = argparse.ArgumentParser(
  48. description="Creates Github Releases and uploads assets."
  49. )
  50. parser.add_argument(
  51. "--api-key", default=os.environ.get("API_KEY"), help="Github API key"
  52. )
  53. parser.add_argument(
  54. "--release-version",
  55. metavar="version",
  56. default=os.environ.get("VERSION"),
  57. help="Release version",
  58. )
  59. parser.add_argument(
  60. "--dry-run", action="store_true", help="Do not modify the release message"
  61. )
  62. args = parser.parse_args()
  63. is_valid = True
  64. if not args.release_version:
  65. logging.error("Missing release version")
  66. is_valid = False
  67. if not args.api_key:
  68. logging.error("Missing API key")
  69. is_valid = False
  70. if is_valid:
  71. return args
  72. parser.print_usage()
  73. exit(1)
  74. def main():
  75. """ Attempts to update the Github Release message with the github asset's checksums """
  76. try:
  77. args = parse_args()
  78. client = Github(args.api_key)
  79. repo = client.get_repo(CLOUDFLARED_REPO)
  80. release = get_release(repo, args.release_version)
  81. msg = release.body
  82. for filepath in glob.glob("artifacts/*"):
  83. pkg_hash = get_sha256(filepath)
  84. # add the sha256 of the new artifact to the release message body
  85. name = os.path.basename(filepath)
  86. msg = update_or_add_message(msg, name, pkg_hash)
  87. if args.dry_run:
  88. logging.info("Skipping asset upload because of dry-run")
  89. return
  90. # update the release body text
  91. release.update_release(args.release_version, msg)
  92. except Exception as e:
  93. logging.exception(e)
  94. exit(1)
  95. main()