diff --git a/.github/RELEASES/README.md b/.github/RELEASES/README.md new file mode 100644 index 0000000..31a8a1a --- /dev/null +++ b/.github/RELEASES/README.md @@ -0,0 +1,49 @@ +# πŸ“ llm-d Release Note Generator + +This tool generates well-formatted release notes for the `llm-d` project using a `release.yaml` descriptor and data pulled from GitHub. It is intended to assist release managers in crafting consistent, accurate, and informative release notes across multiple components. + +--- + +## πŸš€ How It Works + +You write a `release.yaml` file that defines: + +- The overall project version +- The Helm chart version +- A list of components with: + - `name` + - `repo` (GitHub repo) + - `version` (image tag/Git tag) + - `old_version` (optional β€” used for diffs) + +The script will: + +1. Generate a component summary table. +2. For each component: + - If an `old_version` is provided and differs from `version`, it generates a GitHub **changelog diff link** + - It retrieves the Git **commit SHA** for the version tag + - It finds the **pull request** that introduced the commit + - It fetches the **GitHub Actions check runs** on that PR's last commit and includes them in the notes + +The final output is written to a Markdown file named based on the release version (e.g. `release-llm-d-1.1.0.md`). + +--- + +## ✍️ Creating the Release YAML File + +Here’s an example structure for your `release.yaml`: + +```yaml +project_version: llm-d-1.1.0 +chart_version: 1.1.0 +release_date: 2025-07-17 +components: + - name: epp + version: v0.1.0 + old_version: v0.0.9 + repo: llm-d/llm-d-inference-scheduler + - name: modelservice + version: v0.0.15 + repo: llm-d/llm-d-model-service + ... +``` diff --git a/.github/RELEASES/python-release-automation.py b/.github/RELEASES/python-release-automation.py new file mode 100644 index 0000000..8443d4d --- /dev/null +++ b/.github/RELEASES/python-release-automation.py @@ -0,0 +1,114 @@ +import yaml +from jinja2 import Template + +import requests +import os + +GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN") +HEADERS = { + "Authorization": f"Bearer {GITHUB_TOKEN}", + "Accept": "application/vnd.github+json" +} + +def get_commit_sha_from_tag(repo, tag): + tag_url = f"https://api.github.com/repos/{repo}/git/ref/tags/{tag}" + tag_data = requests.get(tag_url, headers=HEADERS).json() + if tag_data.get("object", {}).get("type") == "tag": + tag_obj_url = tag_data["object"]["url"] + tag_obj = requests.get(tag_obj_url, headers=HEADERS).json() + return tag_obj["object"]["sha"] + else: + return tag_data["object"]["sha"] + +def get_pr_for_commit(repo, sha): + pr_url = f"https://api.github.com/repos/{repo}/commits/{sha}/pulls" + pr_data = requests.get(pr_url, headers={ + **HEADERS, + "Accept": "application/vnd.github.groot-preview+json" + }).json() + return pr_data[0] if pr_data else None + +def get_ci_checks_for_commit(repo, sha): + checks_url = f"https://api.github.com/repos/{repo}/commits/{sha}/check-runs" + check_data = requests.get(checks_url, headers=HEADERS).json() + return [ + { + "name": c["name"], + "url": c["html_url"], + "status": c["conclusion"] + } + for c in check_data.get("check_runs", []) + ] + +with open("release-llm-d-1.1.0.yaml") as f: + data = yaml.safe_load(f) + +for c in data["components"]: + if c.get("old_version") == c.get("version"): + c["has_changes"] = False + continue + + c["has_changes"] = True + c["ci_url"] = f"https://github.com/{c['repo']}/actions?query=event:push+tag:{c['version']}" + if c.get("old_version"): + c["changelog_url"] = f"https://github.com/{c['repo']}/compare/{c['old_version']}...{c['version']}" + + try: + sha = get_commit_sha_from_tag(c["repo"], c["version"]) + pr = get_pr_for_commit(c["repo"], sha) + c["commit_sha"] = sha + c["pr_number"] = pr["number"] if pr else None + c["ci_checks"] = get_ci_checks_for_commit(c["repo"], sha) + except Exception as e: + print(f"⚠️ Failed to get CI info for {c['name']}: {e}") + c["ci_checks"] = [] + + +template = Template(""" +# πŸ“¦ llm-d {{ project_version }} Release Notes + +**Release Date:** {{ release_date }} +**Chart Version:** {{ chart_version }} + +--- + +## 🧩 Component Summary + +| Component | Version | Previous Version | +|-----------|---------|------------------| +{% for c in components -%} +| {{ c.name }} | `{{ c.version }}` | `{{ c.old_version or "-" }}` | +{% endfor %} + +--- + +{%- for c in components %} +## πŸ”Ή {{ c.name }} + +{%- if c.has_changes %} +- **Changelog**: [{{ c.old_version }} β†’ {{ c.version }}]({{ c.changelog_url }}) +{%- else %} +_No version change in this release._ +{%- endif %} + +- **CI Checks:** +{%- if c.ci_checks %} +{%- for check in c.ci_checks %} + - [{{ check.name }}]({{ check.url }}) [`{{ check.status }}`] +{%- endfor %} +{%- else %} + - _No CI checks found_ +{%- endif %} + +--- +{%- endfor %} +""") + +output = template.render(**data) + +filename = f"release-{data['project_version']}.md" + +with open(filename, "w") as f: + f.write(output) + +print(f"βœ… Release notes written to {filename}") diff --git a/.github/RELEASES/release-llm-d-1.1.0.md b/.github/RELEASES/release-llm-d-1.1.0.md new file mode 100644 index 0000000..a9b6b6a --- /dev/null +++ b/.github/RELEASES/release-llm-d-1.1.0.md @@ -0,0 +1,64 @@ + +# πŸ“¦ llm-d llm-d-1.1.0 Release Notes + +**Release Date:** 2025-07-17 +**Chart Version:** 1.1.0 + +--- + +## 🧩 Component Summary + +| Component | Version | Previous Version | +|-----------|---------|------------------| +| epp | `v0.1.0` | `0.0.3` | +| modelservice | `v0.0.15` | `0.0.10` | +| vllm | `0.0.8` | `0.0.8` | +| routingProxy | `0.0.7` | `0.0.6` | +| inferenceSimulator | `v0.1.2` | `0.0.4` | + +--- + +## πŸ”Ή epp + +- **Changelog**: [0.0.3 β†’ v0.1.0](https://github.com/llm-d/llm-d-inference-scheduler/compare/0.0.3...v0.1.0) +- **CI Checks:** + - [docker-build-and-push](https://github.com/llm-d/llm-d-inference-scheduler/actions/runs/15136999662/job/42551051127) [`success`] + - [docker-build-and-push](https://github.com/llm-d/llm-d-inference-scheduler/actions/runs/15136999680/job/42551051066) [`success`] + +--- + +## πŸ”Ή modelservice + +- **Changelog**: [0.0.10 β†’ v0.0.15](https://github.com/llm-d/llm-d-model-service/compare/0.0.10...v0.0.15) +- **CI Checks:** + - [docker-build-and-push](https://github.com/llm-d/llm-d-model-service/actions/runs/15305745133/job/43057885324) [`success`] + - [docker-build-and-push](https://github.com/llm-d/llm-d-model-service/actions/runs/15305745152/job/43057885296) [`success`] + +--- + +## πŸ”Ή vllm + +_No version change in this release._ + +- **CI Checks:** + - _No CI checks found_ + +--- + +## πŸ”Ή routingProxy + +- **Changelog**: [0.0.6 β†’ 0.0.7](https://github.com/llm-d/llm-d-routing-sidecar/compare/0.0.6...0.0.7) + +- **CI Checks:** + - [Pipelines as Code CI / llm-d-routing-sidecar](https://github.com/llm-d/llm-d-routing-sidecar/runs/42500129270) [`None`] + +--- + +## πŸ”Ή inferenceSimulator + +- **Changelog**: [0.0.4 β†’ v0.1.2](https://github.com/llm-d/llm-d-inference-sim/compare/0.0.4...v0.1.2) + +- **CI Checks:** + - [docker-build-and-push](https://github.com/llm-d/llm-d-inference-sim/actions/runs/15584716286/job/43887980202) [`success`] + +--- diff --git a/.github/RELEASES/release-llm-d-1.1.0.yaml b/.github/RELEASES/release-llm-d-1.1.0.yaml new file mode 100644 index 0000000..45c11bc --- /dev/null +++ b/.github/RELEASES/release-llm-d-1.1.0.yaml @@ -0,0 +1,29 @@ +project_version: llm-d-1.1.0 +chart_version: 1.1.0 +release_date: 2025-07-17 +components: + - name: epp + version: v0.1.0 + old_version: 0.0.3 + repo: llm-d/llm-d-inference-scheduler + url: https://github.com/llm-d/llm-d-inference-scheduler + - name: modelservice + version: v0.0.15 + old_version: 0.0.10 + repo: llm-d/llm-d-model-service + url: https://github.com/llm-d/llm-d-model-service + - name: vllm + version: 0.0.8 + old_version: 0.0.8 + repo: llm-d/llm-d + url: https://github.com/llm-d/llm-d + - name: routingProxy + version: 0.0.7 + old_version: 0.0.6 + repo: llm-d/llm-d-routing-sidecar + url: https://github.com/llm-d/llm-d-routing-sidecar + - name: inferenceSimulator + version: v0.1.2 + old_version: 0.0.4 + repo: llm-d/llm-d-inference-sim + url: https://github.com/llm-d/llm-d-inference-sim diff --git a/.github/RELEASES/requirements.txt b/.github/RELEASES/requirements.txt new file mode 100644 index 0000000..7b5b5a1 --- /dev/null +++ b/.github/RELEASES/requirements.txt @@ -0,0 +1,2 @@ +Jinja2 +pyyaml