Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add script+workflow to update IREE requirement pins. #827

Merged
merged 5 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did you have to set up keys / perms or anything like that to auto-create PRs in your own personal repo? or is it as simple as just setting the default branch to this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have these settings in my forks:
image

I see that we don't have the same settings in this repository though. May need to change that for this to work, or create a token with broader permissions and pass that around via secrets. I can run some tests on my fork with more limited settings to see what happens.

Copy link
Member Author

@ScottTodd ScottTodd Jan 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Needed to add

permissions:
  contents: write
  pull-requests: write

to work with the current default permissions. We do also need that "Allow GitHub Actions to create and approve pull requests" setting checked. I'll check if we can flip that here.

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 }}
Copy link
Contributor

@renxida renxida Jan 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nifty! New trick acquired.


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}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought through this a little longer and I think there is no reason this should not be in sync, even if patch releases for iree-base-compiler get published. The tag + the latest wheel version should always be in sync.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider the 3.2.0 release. There will be a window between when we publish 3.2.0 to PyPI and when we publish the first 3.3.0rcYYYYMMDD release during which the latest version fetched by this script will be 3.2.0. This will try to use the git tag iree-3.2.0 which will not exist if we stick to the new vX.Y.Z tag naming (e.g. https://github.com/iree-org/iree/releases/tag/v3.1.0). That would not have been an issue back when we used iree-X.Y.Z (e.g. https://github.com/iree-org/iree/releases/tag/iree-3.0.0)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One workaround would be to change the get_latest_version() function to scrape https://iree.dev/pip-release-links.html instead of calling pip index. The release links page only contains prereleases, while pip index searches that page and PyPI.

I'm not too concerned about this edge case though, since we'll be paying pretty close attention to the repositories and package versions around when we push a stable release. Where it will matter is if we decide to change the tag naming convention in the future, since the script expects the iree-PACKAGE_VERSION naming scheme.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can also push iree-X.Y.Z + vX.Y.Z for stable releases ;)


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()
Loading