diff --git a/.github/workflows/watcher-py-wheels.yml b/.github/workflows/watcher-py-wheels.yml index b01a0570..438ce773 100644 --- a/.github/workflows/watcher-py-wheels.yml +++ b/.github/workflows/watcher-py-wheels.yml @@ -6,30 +6,49 @@ on: pull_request: branches: [ release, next ] - +# macos-13 is an intel runner, which cibw wants for x86 builds... But intel mac is busted. +# https://github.com/e-dant/watcher/actions/runs/9929111640/job/27426247416#step:3:293 +# We don't support Windows (but we want to) because meson-python doesn't allow us +# to install shared libraries in wheels for Windows. More info and whatnot here: +# https://github.com/mesonbuild/meson-python/discussions/629 +# Other refs, for the action file: +# - https://cibuildwheel.pypa.io/en/stable/setup +# - https://github.com/scikit-image/scikit-image/blob/main/.github/workflows/wheels_recipe.yml jobs: - watcher_py_wheels: - # Ref: https://cibuildwheel.pypa.io/en/stable/setup - strategy: - matrix: - # macos-13 is an intel runner, macos-14 is apple silicon... But intel mac is busted. - # https://github.com/e-dant/watcher/actions/runs/9929111640/job/27426247416#step:3:293 - # We don't support Windows (but we want to) because meson-python doesn't allow us - # to install shared libraries in wheels for Windows. More info and whatnot here: - # https://github.com/mesonbuild/meson-python/discussions/629 - os: [ ubuntu-latest, macos-14 ] - name: Build wheels on ${{matrix.os}} - runs-on: ${{matrix.os}} + watcher-py-wheels-linux: + name: (x86_64|aarch64)-unknown-linux-(gnu|musl) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: docker/setup-qemu-action@v3 + with: + platforms: arm64 + - uses: pypa/cibuildwheel@v2.19.2 + with: + package-dir: . + output-dir: wheelhouse + config-file: pyproject.toml + - run: python3 tool/shasum.py wheelhouse show + - run: python3 tool/shasum.py wheelhouse mk + - uses: actions/upload-artifact@v4 + with: + name: watcher-py-wheels-linux + path: wheelhouse/* + watcher-py-wheels-apple: + name: aarch64-apple-darwin + runs-on: macos-latest steps: - uses: actions/checkout@v4 - uses: pypa/cibuildwheel@v2.19.2 env: - MACOSX_DEPLOYMENT_TARGET: "11" + MACOSX_DEPLOYMENT_TARGET: 11 with: package-dir: . output-dir: wheelhouse config-file: pyproject.toml + - run: python3 tool/shasum.py wheelhouse show + - run: python3 tool/shasum.py wheelhouse mk - uses: actions/upload-artifact@v4 with: - name: watcher-py-wheels.built-on-${{matrix.os}} - path: wheelhouse/*.whl + name: watcher-py-wheels-apple + path: wheelhouse/* diff --git a/tool/shasum.py b/tool/shasum.py new file mode 100644 index 00000000..f436c3f0 --- /dev/null +++ b/tool/shasum.py @@ -0,0 +1,76 @@ +""" +Tool for writing and computing sha256sums on files. +Particularly useful for verifying the integrity of build artifacts. +""" + +import glob +import hashlib +import os +import sys + + +def sha256sum(file_path) -> str: + """ + The sha256sum of a file + """ + with open(file_path, "rb") as f: + return hashlib.file_digest(f, "sha256").hexdigest() + + +def sha256sum_tree(path) -> dict: + """ + Similar to mk_dot_sha256sums, but returns a mapping of + file paths to their shasums, not file path.sha256sum to shasums. + """ + if os.path.isfile(path): + return {path: sha256sum(path)} + tree = {} + for root, dirs, files in os.walk(path): + for p in dirs + files: + tree.update(sha256sum_tree(os.path.join(root, p))) + return tree + + +def mk_dot_sha256sums(path) -> None: + """ + Adds the shasums of all the files in a directory to new files of + the same name, but with a .sha256sum file extension. + If the path given is a file, just writes that file's shasum to a + file of the same name, but with a .sha256sum file extension. + You get the drift. + """ + for file, shasum in sha256sum_tree(path).items(): + with open(f"{file}.sha256sum", "w", encoding="utf-8") as f: + f.write(shasum) + + +def rm_dot_sha256sums(dir_path) -> None: + """ + Convenience function to remove all .sha256sum files in a directory, + because if we don't we'll make a bunch of .sha256sum.sha256sum... files. + """ + for file in glob.glob(f"{dir_path}/**/*.sha256sum", recursive=True): + os.remove(file) + + +def _main() -> None: + if len(sys.argv) < 2: + print("Usage: python shasum.py [mk | rm | show]") + sys.exit(1) + path = sys.argv[1] + op = sys.argv[2] if len(sys.argv) > 2 else "show" + match op: + case "mk": + mk_dot_sha256sums(path) + case "rm": + rm_dot_sha256sums(path) + case "show": + for file, shasum in sha256sum_tree(path).items(): + print(f"{file}: {shasum}") + case _: + print("Invalid operation. Use mk, rm, or show.") + sys.exit(1) + + +if __name__ == "__main__": + _main()