build-scripts/publish_to_maven_local_if_modified.py (68 lines of code) (raw):

#!/usr/bin/env python3 # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # Purpose: Publish android packages to local maven repo, but only if changed since last publish. # Dependencies: None # Usage: ./automation/publish_to_maven_local_if_modified.py import os import sys import time import hashlib import argparse from shared import run_cmd_checked, find_glean_root, fatal_err import re LAST_CONTENTS_HASH_FILE = ".lastAutoPublishContentsHash" GITIGNORED_FILES_THAT_AFFECT_THE_BUILD = ["local.properties"] parser = argparse.ArgumentParser(description="Publish android packages to local maven repo, but only if changed since last publish") parser.parse_args() root_dir = find_glean_root() if str(root_dir) != os.path.abspath(os.curdir): fatal_err(f"This only works if run from the repo root ({root_dir!r} != {os.path.abspath(os.curdir)!r})") # This doesn't work on "native" windows, so let's get that out of the way now. if sys.platform.startswith("win"): print("NOTE: The autoPublish workflows do not work on native Windows.") print("You must follow the instructions in") print("https://mozilla.github.io/glean/dev/android/setup-android-build-environment.html") print("then, manually ensure that the following command has completed successfully in WSL:") print(sys.argv) print(f"(from the '{root_dir}' directory)") print("Then restart the build") # We don't want to fail here - the intention is that building, eg, # android-components on native Windows still works, just that it prints the # warning above. sys.exit(0) # Calculate a hash reflecting the current state of the repo. contents_hash = hashlib.sha256() contents_hash.update( run_cmd_checked(["git", "rev-parse", "HEAD"], capture_output=True).stdout ) contents_hash.update(b"\x00") # Git can efficiently tell us about changes to tracked files, including # the diff of their contents, if you give it enough "-v"s. changes = run_cmd_checked(["git", "status", "-v", "-v"], capture_output=True).stdout contents_hash.update(changes) contents_hash.update(b"\x00") # But unfortunately it can only tell us the names of untracked # files, and it won't tell us anything about files that are in # .gitignore but can still affect the build. untracked_files = [] changes_lines = iter(ln.strip() for ln in changes.split(b"\n")) try: ln = next(changes_lines) # Skip the tracked files. while not ln.startswith(b"Untracked files:"): ln = next(changes_lines) # Skip instructional line about using `git add`. ln = next(changes_lines) # Now we're at the list of untracked files. ln = next(changes_lines) while ln: untracked_files.append(ln) ln = next(changes_lines) except StopIteration: pass untracked_files.extend(GITIGNORED_FILES_THAT_AFFECT_THE_BUILD) # So, we'll need to slurp the contents of such files for ourselves. for nm in untracked_files: try: with open(nm, "rb") as f: contents_hash.update(f.read()) except (FileNotFoundError, IsADirectoryError): pass contents_hash.update(b"\x00") contents_hash.update(b"\x00") contents_hash = contents_hash.hexdigest() # If the contents hash has changed since last publish, re-publish. last_contents_hash = "" try: with open(LAST_CONTENTS_HASH_FILE) as f: last_contents_hash = f.read().strip() except FileNotFoundError: pass if contents_hash == last_contents_hash: print("Contents have not changed, no need to publish") else: print(f"Contents have changed, publishing") run_cmd_checked(["./gradlew", "publishToMavenLocal", f"-Plocal={time.time_ns()}"]) with open(LAST_CONTENTS_HASH_FILE, "w") as f: f.write(contents_hash) f.write("\n")