-
-
Notifications
You must be signed in to change notification settings - Fork 134
Automate Ubuntu dependency baseline generation #824
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
base: master
Are you sure you want to change the base?
Changes from all commits
af45b7b
5542513
c2ad8b8
ea4e00e
f4188ac
f8ba860
6efc1ed
8b522db
7e3cc5b
995ed6f
0ee3dec
81d1815
f3ca2f5
34a61e5
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,33 @@ | ||||||||||
| name: Generate Ubuntu Baseline | ||||||||||
|
|
||||||||||
| on: | ||||||||||
| workflow_dispatch: | ||||||||||
|
|
||||||||||
| jobs: | ||||||||||
| generate: | ||||||||||
| if: github.actor != 'github-actions[bot]' | ||||||||||
| runs-on: ubuntu-latest | ||||||||||
|
|
||||||||||
| steps: | ||||||||||
| - uses: actions/checkout@v4 | ||||||||||
|
Member
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. There is already a v6:
Suggested change
|
||||||||||
|
|
||||||||||
| - name: Install Python deps | ||||||||||
| run: pip install PyYAML | ||||||||||
|
|
||||||||||
| - name: Generate baseline | ||||||||||
| run: | | ||||||||||
| python3 scripts/generate_ubuntu_baseline.py \ | ||||||||||
| --lts 22.04 24.04 | ||||||||||
|
Comment on lines
+19
to
+20
Member
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. Since precice/precice#2564, the baseline has shifted to 24.04, and we have added 26.04. For the current version (3.4.x), we still need to keep 22.04 listed. Let's make this:
Suggested change
|
||||||||||
|
|
||||||||||
| - name: Commit if changed | ||||||||||
| run: | | ||||||||||
| git config user.name github-actions | ||||||||||
| git config user.email github-actions@github.com | ||||||||||
|
Comment on lines
+24
to
+25
Member
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. In other workflows (
Suggested change
|
||||||||||
| git add _data/ubuntu-baseline.yml | ||||||||||
|
|
||||||||||
| if git diff --cached --quiet; then | ||||||||||
| echo "No changes" | ||||||||||
| else | ||||||||||
| git commit -m "Update Ubuntu baseline" | ||||||||||
| git push | ||||||||||
| fi | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| generated_at: '2026-02-28T11:28:15.149816+00:00' | ||
| ubuntu: | ||
| '22.04': | ||
| optional: | ||
| libopenmpi-dev: 4.1.2 | ||
| petsc-dev: 3.15.5+dfsg1 | ||
| python3-dev: 3.10.6 | ||
| python3-numpy: 1.21.5 | ||
| required: | ||
| build-essential: 12.9ubuntu3 | ||
| cmake: 3.22.1 | ||
| libboost-all-dev: 1.74.0.3ubuntu7 | ||
| libeigen3-dev: 3.4.0 | ||
| libxml2-dev: 2.9.13+dfsg | ||
| '24.04': | ||
| optional: | ||
| libopenmpi-dev: 4.1.6 | ||
| petsc-dev: 3.19.6+dfsg1 | ||
| python3-dev: 3.12.3 | ||
| python3-numpy: 1.26.4+ds | ||
| required: | ||
| build-essential: 12.10ubuntu1 | ||
| cmake: 3.28.3 | ||
| libboost-all-dev: 1.83.0.1ubuntu2 | ||
| libeigen3-dev: 3.4.0 | ||
| libxml2-dev: 2.9.14+dfsg |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| packages: | ||
| required: | ||
| - build-essential | ||
| - cmake | ||
| - libeigen3-dev | ||
| - libxml2-dev | ||
| - libboost-all-dev | ||
|
|
||
| optional: | ||
| - libopenmpi-dev | ||
| - petsc-dev | ||
| - python3-dev | ||
| - python3-numpy |
|
Member
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. Ideally, I would put this script (everything you currently have into |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| #!/usr/bin/env python3 | ||
|
|
||
| import subprocess | ||
| import yaml | ||
| import argparse | ||
| from pathlib import Path | ||
| from datetime import datetime, UTC | ||
|
Comment on lines
+3
to
+7
Member
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 Python script would still need a |
||
|
|
||
| ROOT = Path(__file__).resolve().parent.parent | ||
| DEPENDENCIES_FILE = ROOT / "scripts" / "dependencies.yml" | ||
| OUTPUT_FILE = ROOT / "_data" / "ubuntu-baseline.yml" | ||
|
|
||
|
|
||
| def load_dependencies(): | ||
| with open(DEPENDENCIES_FILE, "r") as f: | ||
| data = yaml.safe_load(f) | ||
|
|
||
| packages = data.get("packages", {}) | ||
|
|
||
| return { | ||
| "required": sorted(packages.get("required", [])), | ||
| "optional": sorted(packages.get("optional", [])), | ||
| } | ||
|
|
||
|
|
||
| def run_command(cmd): | ||
| result = subprocess.run( | ||
| cmd, | ||
| stdout=subprocess.PIPE, | ||
| stderr=subprocess.PIPE, | ||
| text=True, | ||
| ) | ||
| if result.returncode != 0: | ||
| print(result.stderr) | ||
| return None | ||
| return result.stdout.strip() | ||
|
|
||
|
|
||
| def get_version_docker(ubuntu_version, package): | ||
| cmd = [ | ||
| "docker", | ||
| "run", | ||
| "--rm", | ||
| f"ubuntu:{ubuntu_version}", | ||
| "bash", | ||
| "-c", | ||
| f"apt-get update -qq && apt-cache policy {package} | grep Candidate | awk '{{print $2}}'", | ||
|
Member
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. While this will give the package name, which includes the respective upstream version, it also includes other elements, such as the Debian package revision. For example, I am not sure if these would be useful for the user on the website, or rather confusing. In principle, the first three digits should work (all these packages use semantic versioning). |
||
| ] | ||
| raw = run_command(cmd) | ||
|
Member
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. Before running this command, I would expect some output with the command to run, especially since this might take a while. This would also be useful for debugging and for understanding what this script does. |
||
|
|
||
| if not raw or raw == "(none)": | ||
| return None | ||
|
|
||
| # Remove epoch (e.g. "1:") | ||
| if ":" in raw: | ||
| raw = raw.split(":", 1)[1] | ||
|
|
||
| # Remove Debian revision (e.g. "-1ubuntu1") | ||
| raw = raw.split("-", 1)[0] | ||
|
|
||
| return raw | ||
|
|
||
|
|
||
| def get_version_mock(package): | ||
| return "0.0.0-mock" | ||
|
Comment on lines
+64
to
+65
Member
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. What is the use case for this one? It just assigns |
||
|
|
||
|
|
||
| def generate_data(lts_versions, mock=False): | ||
| package_groups = load_dependencies() | ||
|
|
||
| result = { | ||
| "generated_at": datetime.now(UTC).isoformat(), | ||
| "ubuntu": {}, | ||
| } | ||
|
|
||
| for version in lts_versions: | ||
| result["ubuntu"][version] = { | ||
| "required": {}, | ||
| "optional": {}, | ||
| } | ||
|
|
||
| for group in ["required", "optional"]: | ||
| for pkg in package_groups[group]: | ||
| if mock: | ||
| ver = get_version_mock(pkg) | ||
| else: | ||
| ver = get_version_docker(version, pkg) | ||
|
|
||
| result["ubuntu"][version][group][pkg] = ver or "not-found" | ||
|
|
||
| return result | ||
|
|
||
|
|
||
| def write_yaml(data): | ||
| OUTPUT_FILE.parent.mkdir(parents=True, exist_ok=True) | ||
| with open(OUTPUT_FILE, "w") as f: | ||
| yaml.dump(data, f, sort_keys=True) | ||
|
|
||
|
|
||
| def main(): | ||
| parser = argparse.ArgumentParser( | ||
| description="Generate Ubuntu baseline package versions using Docker." | ||
| ) | ||
| parser.add_argument( | ||
| "--mock", | ||
| action="store_true", | ||
| help="Use mock versions instead of querying Docker (useful for testing the pipeline).", | ||
| ) | ||
| parser.add_argument( | ||
| "--lts", | ||
| nargs="+", | ||
| required=True, | ||
| help="Ubuntu LTS versions to query (e.g. 22.04 24.04)", | ||
| ) | ||
|
Comment on lines
+109
to
+114
Member
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. Why restrict that to LTS releases? I would rather name the option |
||
| args = parser.parse_args() | ||
|
|
||
| data = generate_data(args.lts, mock=args.mock) | ||
| write_yaml(data) | ||
|
|
||
| print(f"Generated {OUTPUT_FILE}") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() | ||
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.
Why this line?