Release Skill — G-Core/gcore-python
Constraints
- Repository:
G-Core/gcore-python (hardcoded, do not use for other repos)
- Allowed tools:
gh CLI (scoped to G-Core/gcore-python + read-only
G-Core/gcore-go releases) and Read
- Never: modify source code, force-push, delete branches, or merge without
explicit user confirmation
- Release PRs are created by
stainless-app[bot] with title release: {version}
Workflow
Execute steps 1-6 in order. Present findings at each step before proceeding.
Step 1 — Discover the Release PR
gh pr list --repo G-Core/gcore-python --state open --app stainless-app \
--json number,title,author,url,createdAt
Find the PR whose title starts with release: .
- If no open release PR exists, inform the user and stop.
- If found, display: PR number, title (contains version), URL, creation date.
Step 2 — Analyze the Release
Fetch all three in parallel:
PR body containing the auto-generated changelog (Part 2). Parse it to extract:
- Version number and date
- Breaking changes, Features, Bug Fixes, Refactors, Chores, Documentation
gh pr view {N} --repo G-Core/gcore-python --json body,title,number,url
The actual code diff. Analyze for Python API-level changes:
- New/removed/renamed types, fields, methods
- Changed field types (e.g.,
str -> Optional[str], int -> Literal[""])
- New service methods (e.g.,
create_and_poll())
- Changed return types
- Note: deprecation warnings (
warnings.warn, @deprecated) are informational
only — the methods still exist in the SDK. Do not surface these as
user-facing changes in release notes unless the deprecation is new in this
release AND accompanied by a replacement in the same release.
gh pr diff {N} --repo G-Core/gcore-python
List of changed files. Use commit scopes and file paths to infer product areas:
gh pr diff {N} --repo G-Core/gcore-python --name-only
| File path prefix |
Product Area |
resources/cdn/, types/cdn/ |
CDN |
resources/cloud/, types/cloud/ |
Cloud |
resources/security/, types/security/ |
DDoS Protection |
resources/dns/, types/dns/ |
DNS |
resources/fastedge/, types/fastedge/ |
FastEdge |
resources/iam/, types/iam/ |
IAM |
resources/storage/, types/storage/ |
Object Storage |
resources/streaming/, types/streaming/ |
Streaming |
resources/waap/, types/waap/ |
WAAP |
_client.py, _base_client.py, _utils/, _models.py, _streaming.py, pagination.py, lib/ |
Other |
For canonical sub-product names within each product area, consult
references/products.md. Always use the exact names listed there.
These are heuristics. When a scope or path does not clearly map, use
judgment based on the commit scope, file path, and diff context.
Within a product area, split into distinct sub-areas by resource type.
Do not lump unrelated resources into a single sub-area.
Step 2.5 — Check Go SDK Release (Cross-SDK Sync)
Check whether G-Core/gcore-go already has a release for the same
version. Both SDKs are generated from the same API specs and share version
numbers, so matching releases cover the same underlying API changes.
gh release view v{VERSION} --repo G-Core/gcore-go --json tagName,body
- If a matching release exists, extract its Part 1 (everything before the
## {VERSION} auto-generated changelog heading). Store it as the Go
reference notes for use in Step 4.
- If the release does not exist (exit code ≠ 0), proceed without reference.
This is expected when the Python SDK releases first.
Do not display the Go notes to the user — they are an internal
reference for wording alignment only.
Step 3 — Check CI Status
gh pr checks {N} --repo G-Core/gcore-python --json name,state,bucket
Ignore detect-breaking-changes when evaluating CI status — it is
informational only. Breaking API changes are expected in release PRs and
documented in the changelog. If it fails, note it for the user but do not
treat it as a blocker.
After excluding detect-breaking-changes:
- All checks pass — report CI green, proceed.
- Some checks pending — warn user, ask: wait or proceed?
- Any check fails — show failing checks, do not offer to merge.
Step 4 — Generate Human-Readable Release Notes
Read references/release-notes-examples.md for style reference and examples.
Read references/products.md for canonical product and sub-product names.
Using the changelog (Step 2.1) and diff analysis (Step 2.2), generate the
human-readable summary (Part 1) following this structure:
We're excited to announce version {VERSION}!
### **{Product Area}**
* **{Sub-area}**
* Added `{field/method}` to `{Type}` — {description}
* ⚠ BREAKING CHANGE: `{Type.field}` changed from `{old}` to `{new}`
* Deprecated `{service.method()}` — use `{alternative}` instead
* Fixed {description} — {detail}
Part 1 Rules
- Group by product area (alphabetically: CDN, Cloud, DDoS Protection,
DNS, FastEdge, IAM, Object Storage, Streaming, WAAP). Place Other last.
Only include areas that have changes.
- Within each area, group by sub-area alphabetically (e.g., Bare Metal,
GPU Bare Metal, Managed Kubernetes, Load Balancers). Use the canonical names
from
references/products.md. If changes do not fit a sub-area, list
directly under the product area.
- Breaking changes get
⚠ BREAKING CHANGE: prefix inline. Always specify
old value/type and new value/type.
- Deprecations:
Deprecated `method()` — use `alternative()` instead
- Additions:
Added `name` field/method to `Type` — description
- Fixes:
Fixed {what} — {detail}
- Always use backtick-wrapped Python identifiers for types, fields, methods.
Types use
PascalCase, methods/fields use snake_case.
- No commit hashes or links in Part 1 (those are in Part 2).
- Cross-SDK alignment: If Go reference notes were fetched in Step 2.5,
use them as a wording guide for overlapping API changes. For each change that
appears in both SDKs, match the Go description's phrasing and structure
while substituting Python identifiers (
snake_case methods, Optional[T]
instead of param.Opt[T], etc.). Python-only changes (SDK internals,
Python-specific fixes) have no Go counterpart — write those fresh.
- Do not copy the auto-generated changelog verbatim. Aggregate related
changes. Skip noise.
- Omit
codegen metadata and aggregated API specs update entries unless
they introduce a specific user-visible change visible in the diff.
- Omit doc-only changes — if a diff only updates comments, docstrings, or
descriptions (e.g.,
"IPv4" → "IPv4 or IPv6" in a docstring, or adding a
description to a service/resource for Terraform enablement) with no API
behavioral change (no new fields, methods, types, or changed signatures),
do not surface it in Part 1. These are internal metadata updates, not
user-facing SDK changes.
Display the generated Part 1 to the user. Ask if they want to edit or approve.
Step 5 — Merge the Release PR
Present to the user:
- CI status (from Step 3)
- Generated release notes preview (Part 1 from Step 4)
- Auto-generated changelog (Part 2 from PR body)
- Recommended merge method: rebase
Ask for explicit confirmation before merging.
If user declines or wants changes, return to Step 4.
Once confirmed, merge via Bash:
gh pr merge {PR_NUMBER} --repo G-Core/gcore-python --rebase
If merge fails, report the error and stop.
Step 6 — Update the GitHub Release
After merge, stainless-app[bot] auto-creates a GitHub Release.
Fetch the latest release. Verify tagName matches expected version
v{VERSION}. If not found, sleep 10 and retry once.
gh release view --repo G-Core/gcore-python --json tagName,body,url
Build the final release body by combining Part 1 and the existing Part 2:
{Part 1 — human-readable summary}
{Part 2 — auto-generated changelog already in release body}
Update the release via Bash:
gh release edit v{VERSION} \
--repo G-Core/gcore-python \
--notes "$(cat <<'RELEASE_EOF'
{combined release notes}
RELEASE_EOF
)"
Display the release URL and confirm completion.
Failure Modes
| Situation |
Action |
| No open release PR |
Inform user, stop |
detect-breaking-changes fails |
Informational only. Report to user, proceed with merge |
| CI failing (other checks) |
Show failures, do not merge |
| CI pending |
Warn, ask user preference |
| Merge conflict |
Report, suggest manual resolution |
| Merge fails |
Report error, stop |
| Release not found after merge |
Retry once after 10s, then report |
| Go SDK release not found |
Proceed without cross-SDK reference |
gh CLI not authenticated |
Report, suggest gh auth login |
Source: G-Core/gcore-python — distributed by TomeVault.
1---2name: g-core-gcore-python-gcore-python3description: Release Skill — G-Core/gcore-python4---56# Release Skill — G-Core/gcore-python78## Constraints910- **Repository**: `G-Core/gcore-python` (hardcoded, do not use for other repos)11- **Allowed tools**: `gh` CLI (scoped to `G-Core/gcore-python` + read-only12 `G-Core/gcore-go` releases) and `Read`13- **Never**: modify source code, force-push, delete branches, or merge without14 explicit user confirmation15- **Release PRs** are created by `stainless-app[bot]` with title `release: {version}`1617## Workflow1819Execute steps 1-6 in order. Present findings at each step before proceeding.2021### Step 1 — Discover the Release PR2223```bash24gh pr list --repo G-Core/gcore-python --state open --app stainless-app \25 --json number,title,author,url,createdAt26```2728Find the PR whose title starts with `release: `.2930- If **no open release PR** exists, inform the user and stop.31- If found, display: PR number, title (contains version), URL, creation date.3233### Step 2 — Analyze the Release3435Fetch all three in parallel:36371. PR body containing the auto-generated changelog (Part 2). Parse it to extract:38 - Version number and date39 - Breaking changes, Features, Bug Fixes, Refactors, Chores, Documentation4041 ```bash42 gh pr view {N} --repo G-Core/gcore-python --json body,title,number,url43 ```44452. The actual code diff. Analyze for Python API-level changes:46 - New/removed/renamed types, fields, methods47 - Changed field types (e.g., `str` -> `Optional[str]`, `int` -> `Literal[""]`)48 - New service methods (e.g., `create_and_poll()`)49 - Changed return types50 - Note: deprecation warnings (`warnings.warn`, `@deprecated`) are informational51 only — the methods still exist in the SDK. Do **not** surface these as52 user-facing changes in release notes unless the deprecation is new in this53 release AND accompanied by a replacement in the same release.5455 ```bash56 gh pr diff {N} --repo G-Core/gcore-python57 ```58593. List of changed files. Use commit scopes and file paths to infer product areas:6061 ```bash62 gh pr diff {N} --repo G-Core/gcore-python --name-only63 ```6465 | File path prefix | Product Area |66 |---|---|67 | `resources/cdn/`, `types/cdn/` | **CDN** |68 | `resources/cloud/`, `types/cloud/` | **Cloud** |69 | `resources/security/`, `types/security/` | **DDoS Protection** |70 | `resources/dns/`, `types/dns/` | **DNS** |71 | `resources/fastedge/`, `types/fastedge/` | **FastEdge** |72 | `resources/iam/`, `types/iam/` | **IAM** |73 | `resources/storage/`, `types/storage/` | **Object Storage** |74 | `resources/streaming/`, `types/streaming/` | **Streaming** |75 | `resources/waap/`, `types/waap/` | **WAAP** |76 | `_client.py`, `_base_client.py`, `_utils/`, `_models.py`, `_streaming.py`, `pagination.py`, `lib/` | **Other** |7778 For canonical sub-product names within each product area, consult79 `references/products.md`. Always use the exact names listed there.8081 These are heuristics. When a scope or path does not clearly map, use82 judgment based on the commit scope, file path, and diff context.8384 Within a product area, split into distinct **sub-areas** by resource type.85 Do not lump unrelated resources into a single sub-area.8687### Step 2.5 — Check Go SDK Release (Cross-SDK Sync)8889Check whether `G-Core/gcore-go` already has a release for the same90version. Both SDKs are generated from the same API specs and share version91numbers, so matching releases cover the same underlying API changes.9293```bash94gh release view v{VERSION} --repo G-Core/gcore-go --json tagName,body95```9697- If a matching release **exists**, extract its Part 1 (everything before the98 `## {VERSION}` auto-generated changelog heading). Store it as the **Go99 reference notes** for use in Step 4.100- If the release **does not exist** (exit code ≠ 0), proceed without reference.101 This is expected when the Python SDK releases first.102103Do **not** display the Go notes to the user — they are an internal104reference for wording alignment only.105106### Step 3 — Check CI Status107108```bash109gh pr checks {N} --repo G-Core/gcore-python --json name,state,bucket110```111112**Ignore `detect-breaking-changes`** when evaluating CI status — it is113informational only. Breaking API changes are expected in release PRs and114documented in the changelog. If it fails, note it for the user but do not115treat it as a blocker.116117After excluding `detect-breaking-changes`:118119- **All checks pass** — report CI green, proceed.120- **Some checks pending** — warn user, ask: wait or proceed?121- **Any check fails** — show failing checks, do not offer to merge.122123### Step 4 — Generate Human-Readable Release Notes124125Read `references/release-notes-examples.md` for style reference and examples.126Read `references/products.md` for canonical product and sub-product names.127128Using the changelog (Step 2.1) and diff analysis (Step 2.2), generate the129human-readable summary (Part 1) following this structure:130131```markdown132We're excited to announce version {VERSION}!133134### **{Product Area}**135136* **{Sub-area}**137 * Added `{field/method}` to `{Type}` — {description}138 * ⚠ BREAKING CHANGE: `{Type.field}` changed from `{old}` to `{new}`139 * Deprecated `{service.method()}` — use `{alternative}` instead140 * Fixed {description} — {detail}141```142143#### Part 1 Rules144145- **Group by product area** (alphabetically: CDN, Cloud, DDoS Protection,146 DNS, FastEdge, IAM, Object Storage, Streaming, WAAP). Place **Other** last.147 Only include areas that have changes.148- **Within each area, group by sub-area** alphabetically (e.g., Bare Metal,149 GPU Bare Metal, Managed Kubernetes, Load Balancers). Use the canonical names150 from `references/products.md`. If changes do not fit a sub-area, list151 directly under the product area.152- **Breaking changes** get `⚠ BREAKING CHANGE:` prefix inline. Always specify153 old value/type and new value/type.154- **Deprecations**: ``Deprecated `method()` — use `alternative()` instead``155- **Additions**: ``Added `name` field/method to `Type` — description``156- **Fixes**: `Fixed {what} — {detail}`157- **Always use backtick-wrapped Python identifiers** for types, fields, methods.158 Types use `PascalCase`, methods/fields use `snake_case`.159- **No commit hashes or links** in Part 1 (those are in Part 2).160- **Cross-SDK alignment**: If Go reference notes were fetched in Step 2.5,161 use them as a wording guide for overlapping API changes. For each change that162 appears in both SDKs, match the Go description's phrasing and structure163 while substituting Python identifiers (`snake_case` methods, `Optional[T]`164 instead of `param.Opt[T]`, etc.). Python-only changes (SDK internals,165 Python-specific fixes) have no Go counterpart — write those fresh.166- **Do not copy** the auto-generated changelog verbatim. Aggregate related167 changes. Skip noise.168- **Omit `codegen metadata` and `aggregated API specs update`** entries unless169 they introduce a specific user-visible change visible in the diff.170- **Omit doc-only changes** — if a diff only updates comments, docstrings, or171 descriptions (e.g., `"IPv4"` → `"IPv4 or IPv6"` in a docstring, or adding a172 description to a service/resource for Terraform enablement) with no API173 behavioral change (no new fields, methods, types, or changed signatures),174 do **not** surface it in Part 1. These are internal metadata updates, not175 user-facing SDK changes.176177Display the generated Part 1 to the user. Ask if they want to edit or approve.178179### Step 5 — Merge the Release PR180181Present to the user:1821. CI status (from Step 3)1832. Generated release notes preview (Part 1 from Step 4)1843. Auto-generated changelog (Part 2 from PR body)1854. Recommended merge method: **rebase**186187**Ask for explicit confirmation before merging.**188189If user declines or wants changes, return to Step 4.190191Once confirmed, merge via Bash:192```bash193gh pr merge {PR_NUMBER} --repo G-Core/gcore-python --rebase194```195196If merge fails, report the error and stop.197198### Step 6 — Update the GitHub Release199200After merge, `stainless-app[bot]` auto-creates a GitHub Release.2012021. Fetch the latest release. Verify `tagName` matches expected version203 `v{VERSION}`. If not found, `sleep 10` and retry once.204205 ```bash206 gh release view --repo G-Core/gcore-python --json tagName,body,url207 ```2082092. Build the final release body by combining Part 1 and the existing Part 2:210211 ```212 {Part 1 — human-readable summary}213214215 {Part 2 — auto-generated changelog already in release body}216 ```2172183. Update the release via Bash:219 ```bash220 gh release edit v{VERSION} \221 --repo G-Core/gcore-python \222 --notes "$(cat <<'RELEASE_EOF'223 {combined release notes}224 RELEASE_EOF225 )"226 ```2272284. Display the release URL and confirm completion.229230## Failure Modes231232| Situation | Action |233|---|---|234| No open release PR | Inform user, stop |235| `detect-breaking-changes` fails | Informational only. Report to user, proceed with merge |236| CI failing (other checks) | Show failures, do not merge |237| CI pending | Warn, ask user preference |238| Merge conflict | Report, suggest manual resolution |239| Merge fails | Report error, stop |240| Release not found after merge | Retry once after 10s, then report |241| Go SDK release not found | Proceed without cross-SDK reference |242| `gh` CLI not authenticated | Report, suggest `gh auth login` |243244---245> Source: [G-Core/gcore-python](https://github.com/G-Core/gcore-python) — distributed by [TomeVault](https://tomevault.io).246<!-- tomevault:4.0:skill_md:2026-06-19 -->