-
Notifications
You must be signed in to change notification settings - Fork 129
Add scripts to automate dependencies #2313
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| #!/usr/bin/python3 | ||
| # Copyright Kani Contributors | ||
| # SPDX-License-Identifier: Apache-2.0 OR MIT | ||
| import subprocess | ||
|
|
||
| def run_cargo_command(command, working_directory): | ||
|
|
||
| try: | ||
| process = subprocess.Popen( | ||
| command, | ||
| stdout=subprocess.PIPE, | ||
| stderr=subprocess.PIPE, | ||
| shell=True, | ||
| text=True, | ||
| cwd=working_directory) | ||
| stdout, stderr = process.communicate() | ||
|
|
||
| if process.returncode != 0: | ||
| print(f"Command '{command}' executed unsuccesfully, in '{working_directory}'.") | ||
| print(stderr) | ||
| else: | ||
| print(f"Command '{command}' executed succesfully, in '{working_directory}'.") | ||
| print(stdout) | ||
| except Exception as e: | ||
| print(f"Error: {str(e)}") | ||
|
|
||
|
|
||
| def main(): | ||
|
|
||
| target_directory = "kani" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be |
||
| run_cargo_command("cargo install cargo-outdated", working_directory) | ||
| run_cargo_command("cargo outdated --workspace", working_directory) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| #!/usr/bin/python3 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm going to propose that we don't duplicate this information, see this |
||
| # Copyright Kani Contributors | ||
| # SPDX-License-Identifier: Apache-2.0 OR MIT | ||
| dependencies_links = { | ||
| 'cbmc': { | ||
| 'dependency_name': 'cbmc', | ||
| 'dependency_string': 'CBMC_VERSION', | ||
| 'org_name': 'diffblue', | ||
| 'link': 'https://github.com/diffblue/cbmc' | ||
| }, | ||
| 'cbmc_viewer': { | ||
| 'dependency_name': 'cbmc-viewer', | ||
| 'dependency_string': 'CBMC_VIEWER_VERSION', | ||
| 'org_name': 'model-checking', | ||
| 'link': 'https://github.com/model-checking/cbmc-viewer' | ||
| }, | ||
| 'kissat': { | ||
| 'dependency_name': 'kissat', | ||
| 'dependency_string': 'KISSAT_VERSION', | ||
| 'org_name': 'arminbiere', | ||
| 'link': 'https://github.com/arminbiere/kissat' | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| #!/usr/bin/python3 | ||
| # Copyright Kani Contributors | ||
| # SPDX-License-Identifier: Apache-2.0 OR MIT | ||
| import re | ||
| import requests | ||
|
|
||
| class VersionUpdater: | ||
| def __init__(self, file, dependency): | ||
| self.file = file | ||
| self.dependency = dependency | ||
| self.dependencies = {} | ||
|
|
||
| def get_latest_version(self, org_name, crate_name): | ||
| url = f"https://github.com/{org_name}/{crate_name}/releases/latest" | ||
| response = requests.get(url) | ||
| if response.status_code == 404: | ||
| raise ValueError(f"Failed to find latest version for crate '{crate_name}' on GitHub.") | ||
| else: | ||
| return re.search(r"v?(\d+\.\d+(\.\d+)?(-\S+)?)", response.url).group(1) | ||
|
|
||
| def read_dependencies(self): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this method need to exist? It seems that its reading the current version numbers. But those never get used, they immediately get overwritten by the latest version number in |
||
|
|
||
| with open(self.file, 'r') as f: | ||
| contents = f.readlines() | ||
|
|
||
| for line in contents: | ||
| if "CBMC_VERSION" in line: | ||
| version_number = line.split("=")[1].replace("\n", "") | ||
| self.dependencies["CBMC_VERSION"] = version_number | ||
| elif "CBMC_VIEWER_VERSION" in line: | ||
| version_number = line.split("=")[1].replace("\n", "") | ||
| self.dependencies["CBMC_VIEWER_VERSION"] = version_number | ||
| elif "KISSAT_VERSION" in line: | ||
| version_number = line.split("=")[1].replace("\n", "") | ||
| self.dependencies["KISSAT_VERSION"] = version_number | ||
| else: | ||
| pass | ||
|
|
||
| def update_dependencies(self): | ||
| latest_version = self.get_latest_version(self.dependency["org_name"], self.dependency["dependency_name"]) | ||
| self.dependencies[self.dependency["dependency_string"]] = latest_version | ||
|
|
||
| def write_dependencies(self): | ||
| with open(self.file, 'r') as f: | ||
| lines = f.readlines() | ||
| with open(self.file, 'w') as f: | ||
| for line in lines: | ||
| match = re.search(r'(\w+)="\d+(\.\d+)+"', line.strip()) | ||
| if match and match.group(1).strip() == self.dependency["dependency_string"]: | ||
| f.write( | ||
| f'{self.dependency["dependency_string"]}="{self.dependencies[self.dependency["dependency_string"]]}"\n') | ||
| else: | ||
| f.write(line) | ||
|
|
||
| def run_process(self): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not clear to me that you need to walk through the file, updating the existing values. It seems much quicker to overwrite the entire file. If you have a dict like this: then I think it would be much clearer to do this: then you don't need the if-statement on line 27, which hard-codes the tool names and will thus need to be updated whenever we add a new dependency. so my suggestion is:
I think this would make the code a lot shorter and clearer, and avoid hardcoding the tool names here. |
||
| self.read_dependencies() | ||
| self.update_dependencies() | ||
| self.write_dependencies() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| #!/usr/bin/python3 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure that it makes sense to have three files for CBMC, Viewer, and Kissat, when the files are almost identical. I like that you've specified the dependencies in a data structure in for dep_name, info in dependency_links.items():
updater = VersionUpdater(kani_dependencies_path, dependencies_links[dep_name])
updater.run_process()This way, we can add more dependencies simply by adding to the dict, without adding any new code, because the logic is the same. ( |
||
| # Copyright Kani Contributors | ||
| # SPDX-License-Identifier: Apache-2.0 OR MIT | ||
| from job_runner import dependencies_links | ||
| from dependency_updater import VersionUpdater | ||
|
|
||
| # Set the name of the dependency you want to update | ||
| kani_dependencies_path = "/Users/jaisnan/kani/kani-dependencies" | ||
|
|
||
| if __name__ == "__main__": | ||
| updater = VersionUpdater(kani_dependencies_path, dependencies_links["cbmc_viewer"]) | ||
| updater.run_process() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| #!/usr/bin/python3 | ||
| # Copyright Kani Contributors | ||
| # SPDX-License-Identifier: Apache-2.0 OR MIT | ||
| from job_runner import dependencies_links | ||
| from dependency_updater import VersionUpdater | ||
|
|
||
| # Set the name of the dependency you want to update | ||
| kani_dependencies_path = "/Users/jaisnan/kani/kani-dependencies" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This shouldn't be using the full path, just |
||
|
|
||
| if __name__ == "__main__": | ||
| updater = VersionUpdater(kani_dependencies_path, dependencies_links["cbmc"]) | ||
| updater.run_process() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| #!/usr/bin/python3 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The correct shebang line for python (and most other interpreters) is |
||
| # Copyright Kani Contributors | ||
| # SPDX-License-Identifier: Apache-2.0 OR MIT | ||
| import toml | ||
| import sys | ||
|
|
||
| def update_version(file_path, new_version): | ||
|
|
||
| try: | ||
| # load the toml file | ||
| with open(file_path, 'r') as f: | ||
| data = toml.load(f) | ||
|
|
||
| # update the version number | ||
| data['package']['version'] = new_version | ||
|
|
||
| with open(file_path, 'w') as f: | ||
| toml.dump(data, f) | ||
|
|
||
| print(f"Version updated succesfully to '{version_number}' in '{file_path}'.") | ||
| except Exception as e: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see a need to catch |
||
| print(f"Error updating kani version to '{version_number}' in '{file_path}'.") | ||
|
|
||
|
|
||
| def main(): | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file doesn't appear to do anything because it doesn't actually call |
||
| if len(sys.argv) != 2: | ||
| print("Usage: python update_versions.py <new_version>") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggest that instead of asking the user to specify the new version, you should read the version from |
||
| sys.exit(1) | ||
|
|
||
| # The new version number specified by the user | ||
| new_version = sys.argv[1] | ||
|
|
||
| # The list of Cargo.toml files to update | ||
| cargo_toml_files = [ | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure that this should be hardcoded. How did you get this list? If new kani subpackages are later added this script will silently fail to update their version numbers. If this is a list of every TOML file whose for ct in pathlib.Path().rglob("Cargo.toml"):
with open(ct) as handle:
data = toml.load(handle)
if "package" not in data or "name" not in data["package"]:
continue
if not data["package"]["name"].startswith("kani"):
continue
data["package"]["version"] = new_version
with open(ct, "w") as handle:
toml.dump(data, handle) |
||
| "Cargo.toml", | ||
| "cprover_bindings/Cargo.toml", | ||
| "kani-compiler/Cargo.toml", | ||
| "kani-compiler/kani_queries/Cargo.toml", | ||
| "kani-driver/Cargo.toml", | ||
| "kani_metadata/Cargo.toml", | ||
| "library/kani/Cargo.toml", | ||
| "library/kani_macros/Cargo.toml", | ||
| "library/std/Cargo.toml", | ||
| "tools/build-kani/Cargo.toml", | ||
| ] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| #!/usr/bin/python3 | ||
| # Copyright Kani Contributors | ||
| # SPDX-License-Identifier: Apache-2.0 OR MIT | ||
| from job_runner import dependencies_links | ||
| from dependency_updater import VersionUpdater | ||
|
|
||
| # Set the name of the dependency you want to update | ||
| kani_dependencies_path = "/Users/jaisnan/kani/kani-dependencies" | ||
|
|
||
| if __name__ == "__main__": | ||
| updater = VersionUpdater(kani_dependencies_path, dependencies_links["kissat"]) | ||
| updater.run_process() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure that there's an need for try-except here. If
Popenraises, I think the program should crash out early.There's also no need to use
shell=Truehere, please pass the command as a list.More generally I'm not sure that there's any need to buffer the output and then immediately print it. I think this code could be a lot shorter: