Skip to content

Commit

Permalink
Add script+workflow to update IREE requirement pins. (#827)
Browse files Browse the repository at this point in the history
Progress on #760, built off of
the work in iree-org/iree-turbine#388.

This adds a new workflow that runs once a day to update all pinned IREE
versions. I also looked into using Dependabot but found that it
struggles with `--find-links`, `--index-url`, and with there being
multiple `requirements.txt` files in a repository. While I would love to
not need to reinvent this wheel, I do like keeping full control over the
process.

This PR includes:

* A new `build_tools/update_iree_requirement_pins.py` script handles
updating the pins in `requirements-iree-pinned.txt` and
`shortfin/CMakeLists.txt`. The script also sets some variables in
`GITHUB_ENV`.
* A new `.github/workflows/update_iree_requirement_pins.yml` workflow
runs that script then calls
https://github.com/peter-evans/create-pull-request to create or update a
pull request if there are local changes after running that script. The
commit message and pull request body are constructed using the variables
set by the script.

Test action run:
https://github.com/ScottTodd/shark-ai/actions/runs/12777789320
Test pull request: ScottTodd#1
  • Loading branch information
ScottTodd authored Jan 16, 2025
1 parent 13781bb commit 6f69d8e
Show file tree
Hide file tree
Showing 2 changed files with 248 additions and 0 deletions.
53 changes: 53 additions & 0 deletions .github/workflows/update_iree_requirement_pins.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# Copyright 2025 Advanced Micro Devices, Inc.
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

name: Update IREE requirement pins

on:
workflow_dispatch:
schedule:
# Weekdays at 11:00 AM UTC = 03:00 AM PST / 04:00 AM PDT
- cron: "0 11 * * 1-5"

permissions:
contents: write
pull-requests: write

jobs:
update-iree:
if: ${{ github.repository_owner == 'nod-ai' || github.event_name != 'schedule' }}
runs-on: ubuntu-24.04

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: "Setting up Python"
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
with:
python-version: 3.11

# This sets a few environment variables used below.
- name: Update IREE requirement pins
run: build_tools/update_iree_requirement_pins.py

- name: Create or update pull request
if: |
${{ env.CURRENT_IREE_BASE_COMPILER_VERSION }} != ${{ env.LATEST_IREE_BASE_COMPILER_VERSION }} || \
${{ env.CURRENT_IREE_BASE_RUNTIME_VERSION }} != ${{ env.LATEST_IREE_BASE_RUNTIME_VERSION }} || \
${{ env.CURRENT_IREE_TURBINE_VERSION }} != ${{ env.LATEST_IREE_TURBINE_VERSION }}
${{ env.CURRENT_SHORTFIN_IREE_GIT_TAG }} != ${{ env.LATEST_SHORTFIN_IREE_GIT_TAG }}
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6
with:
base: main
branch: integrates/iree
delete-branch: true
signoff: true
title: "Bump IREE requirement pins to their latest versions."
body: |
Diff: https://github.com/iree-org/iree/compare/iree-${{ env.CURRENT_IREE_BASE_COMPILER_VERSION }}...iree-${{ env.LATEST_IREE_BASE_COMPILER_VERSION }}
Auto-generated by GitHub Actions using [`.github/workflows/update_iree_requirement_pins.yml`](https://github.com/${{ github.repository }}/blob/main/.github/workflows/update_iree_requirement_pins.yml).
commit-message: "Bump IREE to ${{ env.LATEST_IREE_BASE_COMPILER_VERSION }}."
195 changes: 195 additions & 0 deletions build_tools/update_iree_requirement_pins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
#!/usr/bin/env python

# Copyright 2025 Advanced Micro Devices, Inc.
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

"""Updates the pinned IREE versions in this repository.
Usage:
update_iree_requirement_pins.py
Environment variable outputs (via GITHUB_ENV) for GitHub Actions:
CURRENT_IREE_BASE_COMPILER_VERSION
CURRENT_IREE_BASE_RUNTIME_VERSION
CURRENT_IREE_TURBINE_VERSION
LATEST_IREE_BASE_COMPILER_VERSION
LATEST_IREE_BASE_RUNTIME_VERSION
LATEST_IREE_TURBINE_VERSION
"""

from pathlib import Path
import os
import re
import subprocess
import sys
import textwrap

REPO_ROOT = Path(__file__).parent.parent
REQUIREMENTS_IREE_PINNED_PATH = REPO_ROOT / "requirements-iree-pinned.txt"
SHORTFIN_CMAKELISTS_PATH = REPO_ROOT / "shortfin" / "CMakeLists.txt"


def get_current_version(package_name):
with open(REQUIREMENTS_IREE_PINNED_PATH, "r") as f:
text = f.read()
return re.findall(f"{package_name}==(.*)", text)[0]


def get_latest_version(package_name, extra_pip_args=[]):
print("\n-------------------------------------------------------------------------")
print(f"Finding latest available package version for package '{package_name}'\n")

# This queries the pip index to get the latest version.
#
# This doesn't require downloading or installing, so it should be more
# portable across operating systems than other approaches.
#
# Note: the `index` subcommand is experimental. We could instead:
# * Install (into a venv) then check what was installed with `--report`,
# `pip freeze`, or regex parsing (as in `get_current_version()` above)
# * Download then check what was downloaded
# * Scrape the package index and/or release page (https://iree.dev/pip-release-links.html)
subprocess_args = [
sys.executable,
"-m",
"pip",
"index",
"versions",
package_name,
"--disable-pip-version-check",
]
subprocess_args.extend(extra_pip_args)

print(f"Running command:\n {subprocess.list2cmdline(subprocess_args)}\n")
result = subprocess.run(subprocess_args, stdout=subprocess.PIPE)
output = result.stdout.decode("utf-8")
print(f"Command output:\n{textwrap.indent(output, ' ')}")

# Search for text like `iree-base-compiler (3.2.0rc20250109)` within the
# multiple lines of output from the command.
# WARNING: The output from `pip index` is UNSTABLE and UNSTRUCTURED, but
# this seems to work using Python 3.11.2 and pip 22.3.1.
version_search_regex = re.compile(f"{package_name}\s\((.*)\)")
matches = version_search_regex.match(output)
if not matches:
raise RuntimeError("Failed to find a package version using regex")
version = matches.groups()[0]
print(
f"Found package version for '{package_name}' in output using regex: '{version}'"
)
return version


def get_current_git_tag():
with open(SHORTFIN_CMAKELISTS_PATH, "r") as f:
text = f.read()
return re.findall('SHORTFIN_IREE_GIT_TAG "(.*)"', text)[0]


def main():
print("Updating IREE version pins!")

current_compiler_version = get_current_version("iree-base-compiler")
current_runtime_version = get_current_version("iree-base-runtime")
current_turbine_version = get_current_version("iree-turbine")
current_git_tag = get_current_git_tag()

nightly_pip_args = [
"--pre",
"--find-links",
"https://iree.dev/pip-release-links.html",
]
latest_compiler_version = get_latest_version("iree-base-compiler", nightly_pip_args)
latest_runtime_version = get_latest_version("iree-base-runtime", nightly_pip_args)
latest_turbine_version = get_latest_version("iree-turbine", nightly_pip_args)
# TODO(scotttodd): Get this from git? It should generally be in sync with
# the python packages and follow a naming convention. If that isn't
# true, such as right after a stable release, then this may break.
latest_git_tag = f"iree-{latest_runtime_version}"

print("\n-------------------------------------------------------------------------")
print("Current versions:")
print(f" iree-base-compiler=={current_compiler_version}")
print(f" iree-base-runtime=={current_runtime_version}")
print(f" iree-turbine=={current_turbine_version}")
print(f' SHORTFIN_IREE_GIT_TAG "{current_git_tag}"')
print("Latest versions:")
print(f" iree-base-compiler=={latest_compiler_version}")
print(f" iree-base-runtime=={latest_runtime_version}")
print(f" iree-turbine=={latest_turbine_version}")
print(f' SHORTFIN_IREE_GIT_TAG "{latest_git_tag}"')

# Write to GitHub Actions environment variables for future steps to use if they want.
github_env = os.getenv("GITHUB_ENV")
if github_env:
with open(github_env, "a") as fh:
print(
f"CURRENT_IREE_BASE_COMPILER_VERSION={current_compiler_version}",
file=fh,
)
print(
f"CURRENT_IREE_BASE_RUNTIME_VERSION={current_runtime_version}", file=fh
)
print(f"CURRENT_IREE_TURBINE_VERSION={current_turbine_version}", file=fh)
print(f"CURRENT_SHORTFIN_IREE_GIT_TAG={current_git_tag}", file=fh)
print(
f"LATEST_IREE_BASE_COMPILER_VERSION={latest_compiler_version}", file=fh
)
print(f"LATEST_IREE_BASE_RUNTIME_VERSION={latest_runtime_version}", file=fh)
print(f"LATEST_IREE_TURBINE_VERSION={latest_turbine_version}", file=fh)
print(f"LATEST_SHORTFIN_IREE_GIT_TAG={latest_git_tag}", file=fh)

if (
current_compiler_version == latest_compiler_version
and current_runtime_version == latest_runtime_version
and current_turbine_version == latest_turbine_version
and current_git_tag == latest_git_tag
):
print("Already using the latest versions, exiting")
return

print("\n-------------------------------------------------------------------------")
print(f"Editing version pins in '{REQUIREMENTS_IREE_PINNED_PATH}'")
with open(REQUIREMENTS_IREE_PINNED_PATH, "r") as f:
text = f.read()
print(f"Original text:\n{textwrap.indent(text, ' ')}\n")

text = re.sub(
"iree-base-compiler==.*",
f"iree-base-compiler=={latest_compiler_version}",
text,
)
text = re.sub(
"iree-base-runtime==.*",
f"iree-base-runtime=={latest_runtime_version}",
text,
)
text = re.sub(
"iree-turbine==.*",
f"iree-turbine=={latest_turbine_version}",
text,
)
print(f"New text:\n{textwrap.indent(text, ' ')}\n")
with open(REQUIREMENTS_IREE_PINNED_PATH, "w") as f:
f.write(text)

print(f"Editing git tag in '{SHORTFIN_CMAKELISTS_PATH}'")
with open(SHORTFIN_CMAKELISTS_PATH, "r") as f:
text = f.read()
text = re.sub(
'SHORTFIN_IREE_GIT_TAG ".*"',
f'SHORTFIN_IREE_GIT_TAG "{latest_git_tag}"',
text,
)
with open(SHORTFIN_CMAKELISTS_PATH, "w") as f:
f.write(text)

print("-------------------------------------------------------------------------")
print("Edits complete")


if __name__ == "__main__":
main()

0 comments on commit 6f69d8e

Please sign in to comment.