Skip to content

Commit 0cb9218

Browse files
committed
Add LoongSuite Python probe release scripts and pipelines
- loongsuite-release.yml: release workflow (PyPI + GitHub Release) - loongsuite_{lint,test,misc}_0.yml: CI for distro and instrumentation - loongsuite-distro: bootstrap - instrumentation-loongsuite: agentscope, agno, dashscope, dify, langchain, mcp, mem0 - scripts: build, dry-run, bootstrap gen, readme gen - tox-loongsuite.ini: test matrix - docs/loongsuite-release.md Change-Id: Ia0469ec89406d76b3bfd0e4d6381125073b1d9d6 Co-developed-by: Cursor <noreply@cursor.com>
1 parent a26e3b5 commit 0cb9218

File tree

30 files changed

+4581
-27
lines changed

30 files changed

+4581
-27
lines changed
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
# LoongSuite Release Workflow
2+
#
3+
# This workflow handles the complete LoongSuite release process:
4+
#
5+
# 1. PyPI packages (loongsuite-util-genai, loongsuite-distro) - .whl only, NOT loongsuite-python-agent.tar.gz
6+
# 2. GitHub Release (instrumentation-genai/*, instrumentation-loongsuite/* as tar.gz)
7+
#
8+
# Trigger:
9+
# - workflow_dispatch: Manual trigger with version inputs
10+
# - push tags: Automatic trigger on v* tags
11+
#
12+
# PyPI / Test PyPI configuration:
13+
# - Production PyPI: Set PYPI_API_TOKEN secret, or configure OIDC trusted publishing on pypi.org
14+
# - Test PyPI: Set TEST_PYPI_TOKEN secret (pypi-xxx from https://test.pypi.org/manage/account/token/)
15+
# - Use publish_target: testpypi to publish to Test PyPI instead of production
16+
#
17+
# IMPORTANT: Only loongsuite_util_genai-*.whl and loongsuite_distro-*.whl are uploaded to PyPI.
18+
# loongsuite-python-agent-*.tar.gz is for GitHub Release only and must NOT be uploaded to PyPI.
19+
#
20+
name: LoongSuite Release
21+
22+
run-name: "LoongSuite Release ${{ github.event.inputs.loongsuite_version || github.ref_name }}"
23+
24+
on:
25+
workflow_dispatch:
26+
inputs:
27+
loongsuite_version:
28+
description: 'LoongSuite version (e.g., 0.1.0) - for loongsuite-* packages'
29+
required: true
30+
upstream_version:
31+
description: 'Upstream OTel version (e.g., 0.60b1) - for opentelemetry-* packages in bootstrap_gen.py'
32+
required: true
33+
release_notes:
34+
description: 'Release notes (optional, uses CHANGELOG-loongsuite.md Unreleased if empty)'
35+
required: false
36+
skip_pypi:
37+
description: 'Skip PyPI publish (for testing)'
38+
type: boolean
39+
default: false
40+
publish_target:
41+
description: 'Publish target: pypi or testpypi'
42+
type: choice
43+
options:
44+
- pypi
45+
- testpypi
46+
default: pypi
47+
push:
48+
tags:
49+
- 'v*'
50+
51+
permissions:
52+
contents: read
53+
54+
env:
55+
PYTHON_VERSION: '3.11'
56+
57+
jobs:
58+
# Build all packages
59+
build:
60+
runs-on: ubuntu-latest
61+
outputs:
62+
loongsuite_version: ${{ steps.version.outputs.loongsuite_version }}
63+
upstream_version: ${{ steps.version.outputs.upstream_version }}
64+
steps:
65+
- uses: actions/checkout@v4
66+
67+
- name: Set versions from tag or input
68+
id: version
69+
run: |
70+
if [[ "${{ github.event_name }}" == "push" && "${{ github.ref_type }}" == "tag" ]]; then
71+
# Tag-based release: extract version from tag (v0.1.0 -> 0.1.0)
72+
tag="${GITHUB_REF#refs/tags/}"
73+
loongsuite_version="${tag#v}"
74+
# For tag-based release, upstream_version must be set via environment or default
75+
upstream_version="${UPSTREAM_VERSION:-0.60b1}"
76+
else
77+
# Manual release: use inputs
78+
loongsuite_version="${{ github.event.inputs.loongsuite_version }}"
79+
upstream_version="${{ github.event.inputs.upstream_version }}"
80+
fi
81+
82+
if [[ -z "$loongsuite_version" ]]; then
83+
echo "ERROR: loongsuite_version is required"
84+
exit 1
85+
fi
86+
if [[ -z "$upstream_version" ]]; then
87+
echo "ERROR: upstream_version is required"
88+
exit 1
89+
fi
90+
91+
echo "loongsuite_version=$loongsuite_version" >> $GITHUB_OUTPUT
92+
echo "upstream_version=$upstream_version" >> $GITHUB_OUTPUT
93+
echo "LOONGSUITE_VERSION=$loongsuite_version" >> $GITHUB_ENV
94+
echo "UPSTREAM_VERSION=$upstream_version" >> $GITHUB_ENV
95+
96+
echo "LoongSuite version: $loongsuite_version"
97+
echo "Upstream version: $upstream_version"
98+
99+
- uses: actions/setup-python@v5
100+
with:
101+
python-version: ${{ env.PYTHON_VERSION }}
102+
103+
- name: Install build dependencies
104+
run: |
105+
python -m pip install --upgrade pip
106+
python -m pip install -r pkg-requirements.txt
107+
108+
- name: Generate bootstrap_gen.py with versions
109+
run: |
110+
python scripts/generate_loongsuite_bootstrap.py \
111+
--upstream-version ${{ steps.version.outputs.upstream_version }} \
112+
--loongsuite-version ${{ steps.version.outputs.loongsuite_version }}
113+
114+
echo "Generated bootstrap_gen.py:"
115+
head -30 loongsuite-distro/src/loongsuite/distro/bootstrap_gen.py
116+
117+
- name: Build PyPI packages
118+
run: |
119+
python scripts/build_loongsuite_package.py \
120+
--build-pypi \
121+
--version ${{ steps.version.outputs.loongsuite_version }}
122+
123+
echo "PyPI packages built:"
124+
ls -la dist/*.whl
125+
126+
- name: Build GitHub Release packages
127+
run: |
128+
python scripts/build_loongsuite_package.py \
129+
--build-github-release \
130+
--version ${{ steps.version.outputs.loongsuite_version }}
131+
132+
echo "GitHub Release tar:"
133+
ls -la dist/*.tar.gz
134+
135+
- name: Upload PyPI artifacts
136+
uses: actions/upload-artifact@v4
137+
with:
138+
name: pypi-packages
139+
path: |
140+
dist/loongsuite_util_genai-*.whl
141+
dist/loongsuite_distro-*.whl
142+
143+
- name: Upload GitHub Release artifact
144+
uses: actions/upload-artifact@v4
145+
with:
146+
name: github-release
147+
path: dist/loongsuite-python-agent-*.tar.gz
148+
149+
# Publish to production PyPI
150+
publish-pypi:
151+
needs: build
152+
runs-on: ubuntu-latest
153+
if: |
154+
(github.event_name != 'workflow_dispatch' || !inputs.skip_pypi) &&
155+
(github.event_name != 'workflow_dispatch' || github.event.inputs.publish_target != 'testpypi')
156+
environment:
157+
name: pypi
158+
url: https://pypi.org/project/loongsuite-distro/
159+
permissions:
160+
id-token: write # For OIDC; or use PYPI_API_TOKEN secret
161+
steps:
162+
- name: Download PyPI artifacts
163+
uses: actions/download-artifact@v4
164+
with:
165+
name: pypi-packages
166+
path: dist/
167+
168+
- name: Publish to PyPI
169+
uses: pypa/gh-action-pypi-publish@release/v1
170+
with:
171+
skip-existing: true
172+
173+
# Publish to Test PyPI (for testing before production)
174+
publish-testpypi:
175+
needs: build
176+
runs-on: ubuntu-latest
177+
if: ${{ github.event_name == 'workflow_dispatch' && !inputs.skip_pypi && inputs.publish_target == 'testpypi' }}
178+
steps:
179+
- name: Download PyPI artifacts
180+
uses: actions/download-artifact@v4
181+
with:
182+
name: pypi-packages
183+
path: dist/
184+
185+
- name: Publish to Test PyPI
186+
uses: pypa/gh-action-pypi-publish@release/v1
187+
with:
188+
repository-url: https://test.pypi.org/legacy/
189+
username: __token__
190+
password: ${{ secrets.TEST_PYPI_TOKEN }}
191+
skip-existing: true
192+
193+
# Create GitHub Release
194+
github-release:
195+
needs: build
196+
runs-on: ubuntu-latest
197+
permissions:
198+
contents: write # Required for creating releases
199+
steps:
200+
- uses: actions/checkout@v4
201+
202+
- name: Download GitHub Release artifact
203+
uses: actions/download-artifact@v4
204+
with:
205+
name: github-release
206+
path: dist/
207+
208+
- name: Generate release notes
209+
id: release_notes
210+
run: |
211+
LOONGSUITE_VERSION="${{ needs.build.outputs.loongsuite_version }}"
212+
UPSTREAM_VERSION="${{ needs.build.outputs.upstream_version }}"
213+
214+
if [[ -n "${{ github.event.inputs.release_notes }}" ]]; then
215+
echo "${{ github.event.inputs.release_notes }}" > /tmp/release-notes.txt
216+
else
217+
# Start with header
218+
cat > /tmp/release-notes.txt << EOF
219+
# LoongSuite Python Agent v${LOONGSUITE_VERSION}
220+
221+
## Installation
222+
223+
\`\`\`bash
224+
pip install loongsuite-distro==${LOONGSUITE_VERSION}
225+
loongsuite-bootstrap -a install --version ${LOONGSUITE_VERSION}
226+
\`\`\`
227+
228+
## Package Versions
229+
230+
- loongsuite-* packages: ${LOONGSUITE_VERSION}
231+
- opentelemetry-* packages: ${UPSTREAM_VERSION}
232+
233+
---
234+
235+
EOF
236+
237+
# Collect from root CHANGELOG-loongsuite.md
238+
if [[ -f CHANGELOG-loongsuite.md ]]; then
239+
echo "## loongsuite-distro" >> /tmp/release-notes.txt
240+
echo "" >> /tmp/release-notes.txt
241+
sed -n '/^## \[*Unreleased\]*$/,/^## /p' CHANGELOG-loongsuite.md | sed '/^## /d' >> /tmp/release-notes.txt
242+
echo "" >> /tmp/release-notes.txt
243+
fi
244+
245+
# Collect from instrumentation-loongsuite/*/CHANGELOG.md
246+
for changelog in instrumentation-loongsuite/*/CHANGELOG.md; do
247+
if [[ -f "$changelog" ]]; then
248+
pkg_dir=$(dirname "$changelog")
249+
pkg_name=$(basename "$pkg_dir")
250+
unreleased_content=$(sed -n '/^## \[*Unreleased\]*$/,/^## /p' "$changelog" | sed '/^## /d')
251+
if [[ -n "$unreleased_content" && "$unreleased_content" =~ [^[:space:]] ]]; then
252+
echo "## $pkg_name" >> /tmp/release-notes.txt
253+
echo "" >> /tmp/release-notes.txt
254+
echo "$unreleased_content" >> /tmp/release-notes.txt
255+
echo "" >> /tmp/release-notes.txt
256+
fi
257+
fi
258+
done
259+
fi
260+
261+
echo "Release notes:"
262+
cat /tmp/release-notes.txt
263+
264+
- name: Create GitHub release
265+
env:
266+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
267+
run: |
268+
VERSION="${{ needs.build.outputs.loongsuite_version }}"
269+
gh release create "v${VERSION}" \
270+
--title "LoongSuite Python Agent v${VERSION}" \
271+
--notes-file /tmp/release-notes.txt \
272+
dist/loongsuite-python-agent-${VERSION}.tar.gz
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Do not edit this file.
2+
# This file is generated automatically by executing tox -e generate-workflows
3+
4+
name: LoongSuite Misc 0
5+
6+
on:
7+
push:
8+
branches-ignore:
9+
- 'release/*'
10+
- 'otelbot/*'
11+
pull_request:
12+
13+
permissions:
14+
contents: read
15+
16+
concurrency:
17+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
18+
cancel-in-progress: true
19+
20+
env:
21+
# Set the SHA to the branch name if the PR has a label 'prepare-release' or 'backport' otherwise, set it to 'main'
22+
# For PRs you can change the inner fallback ('main')
23+
# For pushes you change the outer fallback ('main')
24+
# The logic below is used during releases and depends on having an equivalent branch name in the core repo.
25+
CORE_REPO_SHA: ${{ github.event_name == 'pull_request' && (
26+
contains(github.event.pull_request.labels.*.name, 'prepare-release') && github.event.pull_request.head.ref ||
27+
contains(github.event.pull_request.labels.*.name, 'backport') && github.event.pull_request.base.ref ||
28+
'main'
29+
) || 'main' }}
30+
CONTRIB_REPO_SHA: main
31+
PIP_EXISTS_ACTION: w
32+
33+
jobs:
34+
35+
generate-loongsuite:
36+
name: LoongSuite generate-loongsuite
37+
runs-on: ubuntu-latest
38+
timeout-minutes: 30
39+
steps:
40+
- name: Checkout repo @ SHA - ${{ github.sha }}
41+
uses: actions/checkout@v4
42+
43+
- name: Set up Python 3.11
44+
uses: actions/setup-python@v5
45+
with:
46+
python-version: "3.11"
47+
48+
- name: Install tox
49+
run: pip install tox-uv
50+
51+
- name: Run tests
52+
run: tox -c tox-loongsuite.ini -e generate-loongsuite
53+

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,5 +67,6 @@ pyrightconfig.json
6767

6868
# LoongSuite Extension
6969
.cursor/
70+
dist-*/
7071
upload/
71-
upload_*_test/
72+
upload_*_test/

0 commit comments

Comments
 (0)