/ tools / scripts / memfault / memfault_elf_uploader.py
memfault_elf_uploader.py
  1  #!/usr/bin/env python3
  2  
  3  import os
  4  import sys
  5  import subprocess
  6  import glob
  7  import git
  8  import argparse
  9  
 10  from dotenv import load_dotenv, find_dotenv
 11  
 12  RELEASE_BRANCH = "main"
 13  
 14  
 15  def get_git_branch():
 16      git_repo = git.Repo(search_parent_directories=True)
 17      return git_repo.git.branch("--show-current")
 18  
 19  
 20  def get_project_root():
 21      git_repo = git.Repo(search_parent_directories=True)
 22      return git_repo.git.rev_parse("--show-toplevel")
 23  
 24  
 25  """
 26  Example readelf -n output:
 27  
 28  Displaying notes found in: .note.gnu.build-id
 29    Owner                Data size        Description
 30    GNU                  0x00000014       NT_GNU_BUILD_ID (unique build ID bitstring)
 31      Build ID: cebe50e6d5aa603cc53bb3d77f5177a287f42991
 32  """
 33  
 34  
 35  def get_build_id(elf_file):
 36      notes = subprocess.getoutput(f"arm-none-eabi-readelf -n {elf_file}")
 37  
 38      # Return build id from the last line of the output
 39      # TODO - actually search for "Build ID: xxxxxxxx" since this will break
 40      # if we ever add another note after the build id
 41      build_id = notes.split("\n")[-1].split(":")[-1].strip()
 42  
 43      print(f'Using build id: "{build_id}"')
 44  
 45      return build_id
 46  
 47  
 48  def get_git_version():
 49      return subprocess.getoutput("git describe --always --abbrev=8 --dirty")
 50  
 51  
 52  if __name__ == "__main__":
 53  
 54      parser = argparse.ArgumentParser()
 55      parser.add_argument("--software_type", default="unknown", help="Software type")
 56      parser.add_argument("--project", default="bristlemouth", help="Memfault project name")
 57      parser.add_argument("--org", default="sofar-ocean", help="Memfault org")
 58      parser.add_argument("--version", help="Version string")
 59      parser.add_argument("--username", help="Memfault username/email")
 60      parser.add_argument("--password", help="Memfault password/api key")
 61      parser.add_argument("--org-token", help="Memfault org token")
 62      parser.add_argument("--verbose", action="store_true")
 63      parser.add_argument("elf_file", help="Elf file to upload")
 64      args = parser.parse_args()
 65  
 66      load_dotenv(find_dotenv())
 67  
 68      elf_file = args.elf_file
 69  
 70      if args.version is None:
 71          version = get_git_version()
 72          if get_git_branch() != RELEASE_BRANCH:
 73              version = "ENG-" + version + "+" + get_build_id(elf_file)[:8]
 74      else:
 75          version = args.version
 76  
 77      # Put together memfault command
 78      memfault_cmd_args = [
 79          "memfault",
 80          "--org",
 81          args.org,
 82          "--project",
 83          args.project,
 84      ]
 85  
 86      # token or email/password need to precede the `upload-symbols` command
 87      if os.getenv("MEMFAULT_ORG_TOKEN"):
 88          memfault_cmd_args += [
 89              "--org-token",
 90              os.getenv("MEMFAULT_ORG_TOKEN")
 91              if args.org_token is None
 92              else args.org_token,
 93          ]
 94      elif os.getenv("MEMFAULT_USERNAME") and os.getenv("MEMFAULT_PASSWORD"):
 95          memfault_cmd_args += [
 96              "--email",
 97              os.getenv("MEMFAULT_USERNAME") if args.username is None else args.username,
 98              "--password",
 99              os.getenv("MEMFAULT_PASSWORD") if args.password is None else args.password,
100          ]
101      else:
102          raise EnvironmentError("Memfault org token or username/password required!")
103  
104      memfault_cmd_args += [
105          "upload-symbols",
106          elf_file,
107          "--software-type",
108          args.software_type,
109          "--software-version",
110          version,
111      ]
112  
113      if args.verbose:
114          print(" ".join(memfault_cmd_args))
115  
116      subprocess.run(memfault_cmd_args)