Skip to content

Commit 2f68efd

Browse files
committed
Add post-release task to modify changelogs
Change-Id: I49a24a2b973a4b11f5df72babf1588bad5f8eca7 Co-developed-by: Cursor <noreply@cursor.com>
1 parent ea27fcd commit 2f68efd

File tree

4 files changed

+204
-8
lines changed

4 files changed

+204
-8
lines changed

.github/workflows/loongsuite-release.yml

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
# 4. Commit & push release branch
99
# 5. Create GitHub Release
1010
# 6. Publish to PyPI / Test PyPI
11+
# 7. Create post-release PR to main (archive changelogs + bump dev versions)
1112
#
1213
# The core logic lives in scripts/loongsuite/loongsuite_release.sh, which can also be
1314
# run locally for the same workflow.
@@ -111,7 +112,8 @@ jobs:
111112
--loongsuite-version ${{ steps.version.outputs.loongsuite_version }} \
112113
--upstream-version ${{ steps.version.outputs.upstream_version }} \
113114
--skip-install \
114-
--skip-github-release
115+
--skip-github-release \
116+
--skip-post-release-pr
115117
116118
- name: Upload PyPI artifacts
117119
uses: actions/upload-artifact@v4
@@ -195,3 +197,63 @@ jobs:
195197
--title "LoongSuite Python Agent v${VERSION}" \
196198
--notes-file dist/release-notes.md \
197199
dist/loongsuite-python-agent-${VERSION}.tar.gz
200+
201+
# Create post-release PR to main (archive changelogs + bump dev versions)
202+
post-release-pr:
203+
needs: build
204+
runs-on: ubuntu-latest
205+
permissions:
206+
contents: write
207+
pull-requests: write
208+
steps:
209+
- uses: actions/checkout@v4
210+
with:
211+
ref: main
212+
fetch-depth: 0
213+
214+
- uses: actions/setup-python@v5
215+
with:
216+
python-version: ${{ env.PYTHON_VERSION }}
217+
218+
- name: Configure git for CI
219+
run: |
220+
git config user.name "github-actions[bot]"
221+
git config user.email "github-actions[bot]@users.noreply.github.com"
222+
223+
- name: Create post-release branch and PR
224+
env:
225+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
226+
run: |
227+
VERSION="${{ needs.build.outputs.loongsuite_version }}"
228+
BRANCH="post-release/v${VERSION}"
229+
TODAY=$(date -u +%Y-%m-%d)
230+
231+
git checkout -b "$BRANCH"
232+
233+
python scripts/loongsuite/collect_loongsuite_changelog.py \
234+
--archive \
235+
--version "$VERSION" \
236+
--date "$TODAY"
237+
238+
python scripts/loongsuite/collect_loongsuite_changelog.py \
239+
--bump-dev \
240+
--version "$VERSION"
241+
242+
git add -A
243+
git commit -m "chore: post-release v${VERSION} - archive changelogs & bump dev versions
244+
245+
- Archive Unreleased changelogs as Version ${VERSION}
246+
- Bump instrumentation-loongsuite module versions to next dev"
247+
248+
git push origin "$BRANCH"
249+
250+
gh pr create \
251+
--base main \
252+
--head "$BRANCH" \
253+
--title "chore: post-release v${VERSION}" \
254+
--body "## Post-release updates for v${VERSION}
255+
256+
- Archive \`Unreleased\` changelog sections as \`Version ${VERSION} (${TODAY})\`
257+
- Bump \`instrumentation-loongsuite\` module versions to next \`.dev\`
258+
259+
This PR was auto-generated by the release workflow."

docs/loongsuite-release.md

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ LoongSuite 采用**双轨发布策略**:
125125
| 脚本 | 作用 |
126126
|------|------|
127127
| `scripts/loongsuite/loongsuite_release.sh` | **统一发布脚本**,支持 `--dry-run` 验证和正式发布两种模式 |
128-
| `scripts/loongsuite/collect_loongsuite_changelog.py` | 收集 Unreleased changelog 生成 release notes,以及归档 changelog |
128+
| `scripts/loongsuite/collect_loongsuite_changelog.py` | changelog 收集、归档、模块版本升级(`--collect` / `--archive` / `--bump-dev` |
129129
| `scripts/loongsuite/generate_loongsuite_bootstrap.py` | 生成 `bootstrap_gen.py`,定义包名映射和版本 |
130130
| `scripts/loongsuite/build_loongsuite_package.py` | 构建 wheel 包,处理包名重命名和依赖替换 |
131131
| `.github/workflows/loongsuite-release.yml` | GitHub Actions 发布工作流(调用统一脚本) |
@@ -428,6 +428,7 @@ Dry Run 模式**不会**创建分支、归档 changelog、提交代码或创建
428428
5. 归档 changelog(将 `Unreleased` 替换为 `Version X.Y.Z (YYYY-MM-DD)`
429429
6. 提交并推送 release 分支
430430
7. 创建 GitHub Release
431+
8. 创建 post-release PR 到 main(归档 changelog + 升级模块版本为下一个 `.dev`
431432

432433
#### 方式 1: 本地执行(推荐)
433434

@@ -451,7 +452,7 @@ Dry Run 模式**不会**创建分支、归档 changelog、提交代码或创建
451452
- `skip_pypi`: 测试时可勾选
452453
4. 执行
453454

454-
CI 工作流会调用同一个脚本完成构建和分支管理,然后在独立 job 中发布 PyPI 和创建 GitHub Release。
455+
CI 工作流会调用同一个脚本完成构建和分支管理,然后在独立 job 中发布 PyPI、创建 GitHub Release,并自动创建 post-release PR 到 main
455456

456457
#### 方式 3: Tag 触发
457458

@@ -470,6 +471,7 @@ git push origin v0.1.0
470471
| Commit + Push | 脚本内 `git commit` + `git push` | 同上 |
471472
| GitHub Release | 脚本内 `gh release create`(可 skip) | 独立 job |
472473
| PyPI publish | 不执行(本地不做) | 独立 job 通过 OIDC/Token |
474+
| Post-release PR | 脚本内创建 PR(需 `gh` CLI) | 独立 job,自动创建 |
473475

474476
#### PyPI / Test PyPI 发布配置
475477

@@ -495,13 +497,37 @@ git push origin v0.1.0
495497
- 只有 `loongsuite_util_genai-*.whl``loongsuite_distro-*.whl` 会上传到 PyPI
496498
- `loongsuite-python-agent-*.tar.gz` 仅用于 GitHub Release,**禁止**上传到 PyPI
497499

500+
### 5.4 Post-Release PR
501+
502+
发布完成后,脚本会自动创建一个 PR 到 `main` 分支,完成两件事:
503+
504+
1. **归档 Changelog**:将各 changelog 文件中的 `Unreleased` 部分标记为已发布的版本号和日期
505+
2. **升级模块版本**:将 `instrumentation-loongsuite/` 下所有模块的 `version.py` 升级为下一个开发版本
506+
507+
**版本升级规则:** 发布 `0.1.0` → 模块版本改为 `0.2.0.dev`(minor 版本 +1,后缀 `.dev`
508+
509+
**受影响的文件:**
510+
- `CHANGELOG-loongsuite.md``util/opentelemetry-util-genai/CHANGELOG-loongsuite.md``instrumentation-loongsuite/*/CHANGELOG.md`
511+
- `instrumentation-loongsuite/*/src/**/version.py`
512+
513+
**本地执行时**,脚本通过 `gh pr create` 自动创建 PR(需要 `gh` CLI)。
514+
**CI 执行时**`post-release-pr` job 独立完成 PR 创建。
515+
516+
如果需要跳过此步骤:
517+
518+
```bash
519+
./scripts/loongsuite/loongsuite_release.sh \
520+
-l 0.1.0 -u 0.60b1 --skip-post-release-pr
521+
```
522+
498523
#### 发布检查清单
499524

500525
- [ ] 本地 dry run 通过 (`--dry-run`)
501526
- [ ] `CHANGELOG-loongsuite.md` 等 changelog 已更新
502527
- [ ] 版本号格式正确(不带 `v` 前缀)
503528
- [ ] `upstream_version` 与当前上游稳定版本匹配
504529
- [ ] PyPI 权限已配置(CI 发布时需要)
530+
- [ ] 发布完成后检查 post-release PR 已创建并合入 main
505531

506532
---
507533

@@ -645,7 +671,7 @@ pip install loongsuite-util-genai
645671
| 文件 | 说明 |
646672
|------|------|
647673
| `scripts/loongsuite/loongsuite_release.sh` | **统一发布脚本**(本地 + CI 共用,支持 `--dry-run`|
648-
| `scripts/loongsuite/collect_loongsuite_changelog.py` | changelog 收集(`--collect`与归档`--archive`|
674+
| `scripts/loongsuite/collect_loongsuite_changelog.py` | changelog 收集(`--collect`、归档`--archive`)、版本升级(`--bump-dev`|
649675
| `scripts/loongsuite/build_loongsuite_package.py` | 构建脚本,处理包名重命名和依赖替换 |
650676
| `scripts/loongsuite/generate_loongsuite_bootstrap.py` | 生成 bootstrap_gen.py |
651677
| `.github/workflows/loongsuite-release.yml` | GitHub Actions 发布工作流(调用统一脚本) |

scripts/loongsuite/collect_loongsuite_changelog.py

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
#!/usr/bin/env python3
22
"""
3-
Collect and archive LoongSuite changelogs.
3+
Collect, archive, and bump LoongSuite changelogs / versions.
44
5-
Two modes:
6-
--collect Gather all Unreleased sections and emit a release-notes markdown file.
7-
--archive Replace Unreleased headers with a versioned header in-place.
5+
Modes:
6+
--collect Gather all Unreleased sections and emit a release-notes markdown file.
7+
--archive Replace Unreleased headers with a versioned header in-place.
8+
--bump-dev Bump instrumentation-loongsuite module versions to the next dev version.
89
910
Changelog sources (in order):
1011
1. CHANGELOG-loongsuite.md (root, label: loongsuite)
@@ -17,6 +18,9 @@
1718
1819
python scripts/loongsuite/collect_loongsuite_changelog.py --archive \\
1920
--version 0.1.0
21+
22+
python scripts/loongsuite/collect_loongsuite_changelog.py --bump-dev \\
23+
--version 0.1.0
2024
"""
2125

2226
import argparse
@@ -159,17 +163,59 @@ def archive(version: str, repo: Path, date_str: Optional[str] = None) -> None:
159163
print(f"No Unreleased section in {label}: {path} (skipped)")
160164

161165

166+
VERSION_RE = re.compile(r'^(__version__\s*=\s*["\']).*(["\'])', re.MULTILINE)
167+
168+
169+
def _next_dev_version(released_version: str) -> str:
170+
"""Compute the next development version by bumping the minor segment.
171+
172+
Examples: "0.1.0" -> "0.2.0.dev", "1.3.2" -> "1.4.0.dev"
173+
"""
174+
parts = released_version.split(".")
175+
if len(parts) < 2:
176+
raise ValueError(f"Cannot compute next dev version from '{released_version}'")
177+
major = int(parts[0])
178+
minor = int(parts[1])
179+
return f"{major}.{minor + 1}.0.dev"
180+
181+
182+
def bump_dev(released_version: str, repo: Path, next_version: Optional[str] = None) -> None:
183+
"""Bump all instrumentation-loongsuite module versions to the next dev version."""
184+
next_ver = next_version or _next_dev_version(released_version)
185+
inst_dir = repo / "instrumentation-loongsuite"
186+
if not inst_dir.is_dir():
187+
print(f"WARNING: {inst_dir} not found, skipping version bump")
188+
return
189+
190+
version_files = sorted(inst_dir.rglob("version.py"))
191+
if not version_files:
192+
print(f"WARNING: no version.py files found in {inst_dir}")
193+
return
194+
195+
for vf in version_files:
196+
text = vf.read_text(encoding="utf-8")
197+
m = VERSION_RE.search(text)
198+
if m:
199+
new_text = VERSION_RE.sub(rf'\g<1>{next_ver}\2', text)
200+
vf.write_text(new_text, encoding="utf-8")
201+
print(f"Bumped {vf.relative_to(repo)}: {m.group(0).strip()} -> __version__ = \"{next_ver}\"")
202+
else:
203+
print(f"WARNING: no __version__ found in {vf.relative_to(repo)}")
204+
205+
162206
def main() -> None:
163207
parser = argparse.ArgumentParser(description="Collect/archive LoongSuite changelogs")
164208
group = parser.add_mutually_exclusive_group(required=True)
165209
group.add_argument("--collect", action="store_true", help="Collect Unreleased into release notes")
166210
group.add_argument("--archive", action="store_true", help="Archive Unreleased to versioned header")
211+
group.add_argument("--bump-dev", action="store_true", help="Bump module versions to next dev")
167212

168213
parser.add_argument("--version", required=True, help="LoongSuite version (e.g. 0.1.0)")
169214
parser.add_argument("--upstream-version", default="", help="Upstream OTel version (for --collect header)")
170215
parser.add_argument("--output", default="dist/release-notes.md", help="Output file for --collect")
171216
parser.add_argument("--repo-root", default=str(REPO_ROOT), help="Repository root")
172217
parser.add_argument("--date", default=None, help="Release date (YYYY-MM-DD), default: today")
218+
parser.add_argument("--next-dev-version", default=None, help="Override next dev version (default: auto-computed)")
173219

174220
args = parser.parse_args()
175221
repo = Path(args.repo_root)
@@ -180,6 +226,8 @@ def main() -> None:
180226
collect(args.version, args.upstream_version, Path(args.output), repo)
181227
elif args.archive:
182228
archive(args.version, repo, args.date)
229+
elif args.bump_dev:
230+
bump_dev(args.version, repo, args.next_dev_version)
183231

184232

185233
if __name__ == "__main__":

scripts/loongsuite/loongsuite_release.sh

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
# 7. Commit & push release branch
1616
# 8. (Optional) Installation verification
1717
# 9. (Optional) Create GitHub Release via gh CLI
18+
# 10. Create post-release PR to main (archive changelogs + bump dev versions)
1819
#
1920
# --dry-run:
2021
# Runs steps 2-5, 8 only (no branch creation, no changelog archive, no commit, no release).
@@ -37,6 +38,7 @@ DRY_RUN=false
3738
SKIP_INSTALL=false
3839
SKIP_PYPI=false
3940
SKIP_GITHUB_RELEASE=false
41+
SKIP_POST_RELEASE_PR=false
4042
GIT_REMOTE="origin"
4143

4244
while [[ $# -gt 0 ]]; do
@@ -65,6 +67,10 @@ while [[ $# -gt 0 ]]; do
6567
SKIP_GITHUB_RELEASE=true
6668
shift
6769
;;
70+
--skip-post-release-pr)
71+
SKIP_POST_RELEASE_PR=true
72+
shift
73+
;;
6874
--remote)
6975
GIT_REMOTE="$2"
7076
shift 2
@@ -81,6 +87,7 @@ while [[ $# -gt 0 ]]; do
8187
echo " --skip-install Skip installation verification"
8288
echo " --skip-pypi Skip PyPI package build"
8389
echo " --skip-github-release Skip creating GitHub Release (for CI)"
90+
echo " --skip-post-release-pr Skip creating post-release PR to main"
8491
echo " --remote <name> Git remote name (default: origin)"
8592
echo " -h, --help Show this help message"
8693
exit 0
@@ -361,6 +368,59 @@ else
361368
echo ""
362369
fi
363370

371+
# ── Step 12: Create post-release PR to main ────────────────────────────
372+
if [[ "$DRY_RUN" == "true" || "$SKIP_POST_RELEASE_PR" == "true" ]]; then
373+
echo ">>> Step 12: Skipped (dry-run or --skip-post-release-pr)"
374+
echo ""
375+
else
376+
echo ">>> Step 12: Creating post-release PR to main..."
377+
POST_RELEASE_BRANCH="post-release/v${LOONGSUITE_VERSION}"
378+
379+
git checkout main
380+
git checkout -b "$POST_RELEASE_BRANCH"
381+
382+
echo " Archiving changelogs on main..."
383+
python scripts/loongsuite/collect_loongsuite_changelog.py \
384+
--archive \
385+
--version "$LOONGSUITE_VERSION" \
386+
--date "$TODAY"
387+
388+
echo " Bumping instrumentation-loongsuite versions to next dev..."
389+
python scripts/loongsuite/collect_loongsuite_changelog.py \
390+
--bump-dev \
391+
--version "$LOONGSUITE_VERSION"
392+
393+
git add -A
394+
git commit -m "chore: post-release v${LOONGSUITE_VERSION} - archive changelogs & bump dev versions
395+
396+
- Archive Unreleased changelogs as Version ${LOONGSUITE_VERSION}
397+
- Bump instrumentation-loongsuite module versions to next dev"
398+
399+
echo " Pushing ${POST_RELEASE_BRANCH}..."
400+
git push "$GIT_REMOTE" "$POST_RELEASE_BRANCH"
401+
402+
if command -v gh &>/dev/null; then
403+
gh pr create \
404+
--base main \
405+
--head "$POST_RELEASE_BRANCH" \
406+
--title "chore: post-release v${LOONGSUITE_VERSION}" \
407+
--body "## Post-release updates for v${LOONGSUITE_VERSION}
408+
409+
- Archive \`Unreleased\` changelog sections as \`Version ${LOONGSUITE_VERSION} (${TODAY})\`
410+
- Bump \`instrumentation-loongsuite\` module versions to next \`.dev\`
411+
412+
This PR was auto-generated by the release script."
413+
echo " OK: Post-release PR created"
414+
else
415+
echo " WARN: gh CLI not found, skipping PR creation."
416+
echo " Push completed. Create PR manually from ${POST_RELEASE_BRANCH} → main"
417+
fi
418+
419+
# Switch back to the release branch
420+
git checkout "$RELEASE_BRANCH"
421+
echo ""
422+
fi
423+
364424
# ── Summary ───────────────────────────────────────────────────────────────
365425
echo "=========================================="
366426
echo "Complete ($MODE)"

0 commit comments

Comments
 (0)