plainx.dev 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plainx/dev/CHANGELOG.md +11 -0
- plainx/dev/__init__.py +0 -0
- plainx/dev/agents/.claude/skills/plainx-release/SKILL.md +230 -0
- plainx/dev/agents/.claude/skills/plainx-release/get-package-info +176 -0
- plainx/dev/agents/.claude/skills/plainx-release/release-workflow.yml +32 -0
- plainx_dev-0.1.0.dist-info/METADATA +42 -0
- plainx_dev-0.1.0.dist-info/RECORD +8 -0
- plainx_dev-0.1.0.dist-info/WHEEL +4 -0
plainx/dev/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# plainx-dev changelog
|
|
2
|
+
|
|
3
|
+
## [0.1.0](https://github.com/dropseed/plain/releases/plainx-dev@0.1.0) (2026-02-05)
|
|
4
|
+
|
|
5
|
+
Initial release.
|
|
6
|
+
|
|
7
|
+
- `/plainx-release` skill for releasing plainx packages with guided workflow
|
|
8
|
+
- Version bump suggestions based on commit analysis
|
|
9
|
+
- First release detection (0.0.0 convention)
|
|
10
|
+
- Changelog generation from code diffs
|
|
11
|
+
- GitHub Actions workflow template for PyPI trusted publishing
|
plainx/dev/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plainx-release
|
|
3
|
+
description: Releases plainx packages with version suggestions, changelog generation, and git tagging. Use when releasing a package to PyPI.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Release Package
|
|
7
|
+
|
|
8
|
+
Release a plainx package with version bumping, changelog generation, and git tagging.
|
|
9
|
+
|
|
10
|
+
## Arguments
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
/plainx-release [--major|--minor|--patch]
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- No args: analyze commits and prompt for version type
|
|
17
|
+
- `--major`: auto-select major release
|
|
18
|
+
- `--minor`: auto-select minor release
|
|
19
|
+
- `--patch`: auto-select patch release
|
|
20
|
+
|
|
21
|
+
## Scripts
|
|
22
|
+
|
|
23
|
+
| Script | Purpose |
|
|
24
|
+
| ------------------ | --------------------------------------------------- |
|
|
25
|
+
| `get-package-info` | Get package metadata and commits since last release |
|
|
26
|
+
|
|
27
|
+
## Workflow
|
|
28
|
+
|
|
29
|
+
### Phase 1: Check Preconditions
|
|
30
|
+
|
|
31
|
+
1. Check git status is clean:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
git status --porcelain
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
If not clean, stop and ask user to commit or stash changes.
|
|
38
|
+
|
|
39
|
+
### Phase 2: Get Package Info
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
uv run ./.claude/skills/plainx-release/get-package-info
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This outputs JSON with:
|
|
46
|
+
|
|
47
|
+
- `name`: Package name from pyproject.toml
|
|
48
|
+
- `current_version`: Current version
|
|
49
|
+
- `changelog_path`: Path to CHANGELOG.md
|
|
50
|
+
- `last_tag`: Most recent git tag for this package
|
|
51
|
+
- `repo_url`: GitHub URL (extracted from pyproject.toml)
|
|
52
|
+
- `commits`: List of commits since last tag (excluding tests)
|
|
53
|
+
|
|
54
|
+
If no commits since last release, inform the user and stop.
|
|
55
|
+
|
|
56
|
+
### Phase 2b: First Release Detection
|
|
57
|
+
|
|
58
|
+
If `current_version` is `0.0.0`, this is the **first release**:
|
|
59
|
+
|
|
60
|
+
1. Inform the user: "This package has never been released (version 0.0.0)."
|
|
61
|
+
2. Ask what version to release:
|
|
62
|
+
- **0.1.0** - First development release (recommended for most packages)
|
|
63
|
+
- **1.0.0** - First stable release (if the package is already production-ready)
|
|
64
|
+
3. Skip to Phase 4 with the chosen version (use `uv version <version>` to set it directly)
|
|
65
|
+
|
|
66
|
+
### Phase 3: Collect Release Decision
|
|
67
|
+
|
|
68
|
+
1. Display the commits since last release
|
|
69
|
+
2. **Analyze commits and suggest release type**:
|
|
70
|
+
- **Major**: breaking changes, major API redesigns, significant removals
|
|
71
|
+
- **Minor**: new features, significant additions, new APIs
|
|
72
|
+
- **Patch**: small bugfixes, minor tweaks, documentation updates, refactors
|
|
73
|
+
3. Ask user to confirm or adjust (major/minor/patch/skip)
|
|
74
|
+
- If `--major`, `--minor`, or `--patch` was passed, auto-select that type
|
|
75
|
+
- If user chooses to skip, stop
|
|
76
|
+
|
|
77
|
+
### Phase 4: Set Version
|
|
78
|
+
|
|
79
|
+
For first releases (from 0.0.0):
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
uv version <version>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Where `<version>` is the chosen version like `0.1.0` or `1.0.0`.
|
|
86
|
+
|
|
87
|
+
For subsequent releases:
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
uv version --bump <type>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Where `<type>` is `major`, `minor`, or `patch`.
|
|
94
|
+
|
|
95
|
+
### Phase 5: Generate Release Notes
|
|
96
|
+
|
|
97
|
+
1. Get the new version:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
uv version --short
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
2. Get the file changes since the last release:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
git diff <last_tag>..HEAD -- . ":(exclude)tests"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
If no `last_tag`, use the initial commit or recent history.
|
|
110
|
+
|
|
111
|
+
3. Read the existing `<changelog_path>` file.
|
|
112
|
+
|
|
113
|
+
4. Prepend a new release entry to the changelog.
|
|
114
|
+
|
|
115
|
+
**For first releases:**
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
## [<new_version>](<repo_url>/releases/v<new_version>) (<today's date>)
|
|
119
|
+
|
|
120
|
+
Initial release.
|
|
121
|
+
|
|
122
|
+
- Brief summary of what the package provides
|
|
123
|
+
- Key features or capabilities
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**For subsequent releases:**
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
## [<new_version>](<repo_url>/releases/v<new_version>) (<today's date>)
|
|
130
|
+
|
|
131
|
+
### What's changed
|
|
132
|
+
|
|
133
|
+
- Summarize user-facing changes based on the actual diff (not just commit messages)
|
|
134
|
+
- Include commit hash links: ([abc1234](<repo_url>/commit/abc1234))
|
|
135
|
+
- Skip test changes, internal refactors that don't affect public API
|
|
136
|
+
|
|
137
|
+
### Upgrade instructions
|
|
138
|
+
|
|
139
|
+
- Specific steps if any API changed
|
|
140
|
+
- If no changes required: "- No changes required."
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Phase 6: Commit, Tag, and Push
|
|
144
|
+
|
|
145
|
+
Guide the user through these steps explicitly:
|
|
146
|
+
|
|
147
|
+
1. **Stage files**:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
git add pyproject.toml <changelog_path> uv.lock
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
2. **Show what will be committed**:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
git diff --cached --stat
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
3. **Create commit**:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
git commit -m "Release v<new_version>"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
4. **Create tag**:
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
git tag -a v<new_version> -m "Release v<new_version>"
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
5. **GitHub Workflow Setup (first release only)**:
|
|
172
|
+
|
|
173
|
+
Check if `.github/workflows/release.yml` exists. If not, ask:
|
|
174
|
+
|
|
175
|
+
> "No release workflow found. Would you like to set up GitHub Actions to publish to PyPI when you push a tag?"
|
|
176
|
+
|
|
177
|
+
If yes, copy `.claude/skills/plainx-release/release-workflow.yml` to `.github/workflows/release.yml`, then amend the commit:
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
git add .github/workflows/release.yml
|
|
181
|
+
git commit --amend --no-edit
|
|
182
|
+
git tag -fa v<new_version> -m "Release v<new_version>"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Remind the user to configure PyPI trusted publishing after pushing:
|
|
186
|
+
- Go to https://pypi.org/manage/account/publishing/
|
|
187
|
+
- Add trusted publisher: GitHub owner, repo name, workflow "release.yml" (no environment needed)
|
|
188
|
+
|
|
189
|
+
6. **Push commit and tag**:
|
|
190
|
+
```
|
|
191
|
+
git push && git push --tags
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Ask user to confirm before each destructive step (commit, push).
|
|
195
|
+
|
|
196
|
+
### Phase 7: GitHub Release (Optional)
|
|
197
|
+
|
|
198
|
+
After pushing, wait for the GitHub workflow to publish to PyPI. Once published, ask the user if they want to create a GitHub release:
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
gh release create v<new_version> --notes "<changelog entry summary>"
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Or to use the full changelog entry from the file, extract and pass it manually.
|
|
205
|
+
|
|
206
|
+
## Release Type Guidelines
|
|
207
|
+
|
|
208
|
+
Consider the current version when suggesting release types:
|
|
209
|
+
|
|
210
|
+
### Pre-1.0 packages (0.x.y)
|
|
211
|
+
|
|
212
|
+
Most packages stay pre-1.0 for a long time. For these packages:
|
|
213
|
+
|
|
214
|
+
- **Minor (0.x.0)**: New features, breaking changes, new APIs, significant additions
|
|
215
|
+
- **Patch (0.0.x)**: Bugfixes, minor tweaks, documentation, refactors
|
|
216
|
+
- **Major (1.0.0)**: Only suggest if the user explicitly wants to mark the package as stable/production-ready
|
|
217
|
+
|
|
218
|
+
### Post-1.0 packages (x.y.z where x >= 1)
|
|
219
|
+
|
|
220
|
+
Once a package has reached 1.0, follow semver strictly:
|
|
221
|
+
|
|
222
|
+
- **Major (x.0.0)**: Breaking changes, API removals, incompatible changes
|
|
223
|
+
- **Minor (x.y.0)**: New features, new APIs, backwards-compatible additions
|
|
224
|
+
- **Patch (x.y.z)**: Bugfixes, minor tweaks, documentation, refactors
|
|
225
|
+
|
|
226
|
+
### Commit message indicators
|
|
227
|
+
|
|
228
|
+
- Breaking/major indicators: "breaking", "remove", "rename API", "redesign", "incompatible"
|
|
229
|
+
- Feature/minor indicators: "add", "new", "feature", "implement"
|
|
230
|
+
- Fix/patch indicators: "fix", "bugfix", "typo", "docs", "refactor", "update"
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Get package metadata and commits since last release.
|
|
4
|
+
|
|
5
|
+
Outputs JSON with package info for the current directory's pyproject.toml.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import subprocess
|
|
12
|
+
import sys
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
try:
|
|
16
|
+
import tomllib
|
|
17
|
+
except ImportError:
|
|
18
|
+
import tomli as tomllib
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def run(cmd: list[str], cwd: Path | None = None) -> str:
|
|
22
|
+
"""Run a command and return stdout."""
|
|
23
|
+
result = subprocess.run(cmd, capture_output=True, text=True, cwd=cwd)
|
|
24
|
+
return result.stdout.strip()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_package_name(pyproject: dict) -> str:
|
|
28
|
+
"""Get the package name from pyproject.toml."""
|
|
29
|
+
return pyproject.get("project", {}).get("name", "")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_current_version() -> str:
|
|
33
|
+
"""Get the current version using uv."""
|
|
34
|
+
return run(["uv", "version", "--short"])
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_repo_url(pyproject: dict) -> str | None:
|
|
38
|
+
"""Extract GitHub repo URL from pyproject.toml."""
|
|
39
|
+
project = pyproject.get("project", {})
|
|
40
|
+
|
|
41
|
+
# Check project.urls
|
|
42
|
+
urls = project.get("urls", {})
|
|
43
|
+
for key in ["Repository", "repository", "Source", "source", "GitHub", "github"]:
|
|
44
|
+
if key in urls:
|
|
45
|
+
url = urls[key]
|
|
46
|
+
# Normalize to https://github.com/owner/repo format
|
|
47
|
+
if "github.com" in url:
|
|
48
|
+
return url.rstrip("/").rstrip(".git")
|
|
49
|
+
|
|
50
|
+
# Check project.homepage
|
|
51
|
+
homepage = project.get("homepage", "")
|
|
52
|
+
if "github.com" in homepage:
|
|
53
|
+
return homepage.rstrip("/").rstrip(".git")
|
|
54
|
+
|
|
55
|
+
return None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def get_changelog_path() -> str:
|
|
59
|
+
"""Find the CHANGELOG.md file."""
|
|
60
|
+
root = Path.cwd()
|
|
61
|
+
|
|
62
|
+
# Common locations
|
|
63
|
+
candidates = [
|
|
64
|
+
root / "CHANGELOG.md",
|
|
65
|
+
root / "changelog.md",
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
# Check for package-specific changelog (src layout or namespace package)
|
|
69
|
+
for pyproject_path in [root / "pyproject.toml"]:
|
|
70
|
+
if pyproject_path.exists():
|
|
71
|
+
with open(pyproject_path, "rb") as f:
|
|
72
|
+
pyproject = tomllib.load(f)
|
|
73
|
+
name = get_package_name(pyproject)
|
|
74
|
+
if name:
|
|
75
|
+
# Handle namespace packages like plainx.sentry -> plainx/sentry
|
|
76
|
+
parts = name.replace(".", "/").replace("-", "/")
|
|
77
|
+
candidates.extend([
|
|
78
|
+
root / parts / "CHANGELOG.md",
|
|
79
|
+
root / "src" / parts / "CHANGELOG.md",
|
|
80
|
+
])
|
|
81
|
+
|
|
82
|
+
for path in candidates:
|
|
83
|
+
if path.exists():
|
|
84
|
+
return str(path.relative_to(root))
|
|
85
|
+
|
|
86
|
+
# Default to root CHANGELOG.md even if it doesn't exist yet
|
|
87
|
+
return "CHANGELOG.md"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def get_last_tag(name: str) -> str | None:
|
|
91
|
+
"""Get the most recent release tag for this package."""
|
|
92
|
+
# Try v-prefixed tags first (most common for single-package repos)
|
|
93
|
+
output = run(["git", "tag", "-l", "v*", "--sort=-v:refname"])
|
|
94
|
+
tags = [t for t in output.split("\n") if t]
|
|
95
|
+
if tags:
|
|
96
|
+
return tags[0]
|
|
97
|
+
|
|
98
|
+
# Fall back to name@version format (monorepo style)
|
|
99
|
+
output = run(["git", "tag", "-l", f"{name}@*", "--sort=-v:refname"])
|
|
100
|
+
tags = [t for t in output.split("\n") if t]
|
|
101
|
+
if tags:
|
|
102
|
+
return tags[0]
|
|
103
|
+
|
|
104
|
+
return None
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def get_commits_since(since_ref: str | None) -> list[dict]:
|
|
108
|
+
"""Get commits since a given ref, excluding tests."""
|
|
109
|
+
if since_ref:
|
|
110
|
+
cmd = [
|
|
111
|
+
"git", "log", "--format=%H|%s",
|
|
112
|
+
f"{since_ref}..HEAD",
|
|
113
|
+
"--", ".",
|
|
114
|
+
":(exclude)tests",
|
|
115
|
+
":(exclude)**/tests",
|
|
116
|
+
]
|
|
117
|
+
else:
|
|
118
|
+
# No previous tag, get recent commits
|
|
119
|
+
cmd = [
|
|
120
|
+
"git", "log", "--format=%H|%s",
|
|
121
|
+
"-n", "50",
|
|
122
|
+
"--", ".",
|
|
123
|
+
":(exclude)tests",
|
|
124
|
+
":(exclude)**/tests",
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
output = run(cmd)
|
|
128
|
+
|
|
129
|
+
commits = []
|
|
130
|
+
for line in output.split("\n"):
|
|
131
|
+
if "|" in line:
|
|
132
|
+
hash_, subject = line.split("|", 1)
|
|
133
|
+
commits.append({
|
|
134
|
+
"hash": hash_[:12],
|
|
135
|
+
"subject": subject
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
return commits
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def main():
|
|
142
|
+
root = Path.cwd()
|
|
143
|
+
pyproject_path = root / "pyproject.toml"
|
|
144
|
+
|
|
145
|
+
if not pyproject_path.exists():
|
|
146
|
+
print(json.dumps({"error": "No pyproject.toml found in current directory"}))
|
|
147
|
+
sys.exit(1)
|
|
148
|
+
|
|
149
|
+
with open(pyproject_path, "rb") as f:
|
|
150
|
+
pyproject = tomllib.load(f)
|
|
151
|
+
|
|
152
|
+
name = get_package_name(pyproject)
|
|
153
|
+
if not name:
|
|
154
|
+
print(json.dumps({"error": "No project.name found in pyproject.toml"}))
|
|
155
|
+
sys.exit(1)
|
|
156
|
+
|
|
157
|
+
current_version = get_current_version()
|
|
158
|
+
changelog_path = get_changelog_path()
|
|
159
|
+
last_tag = get_last_tag(name)
|
|
160
|
+
repo_url = get_repo_url(pyproject)
|
|
161
|
+
commits = get_commits_since(last_tag)
|
|
162
|
+
|
|
163
|
+
result = {
|
|
164
|
+
"name": name,
|
|
165
|
+
"current_version": current_version,
|
|
166
|
+
"changelog_path": changelog_path,
|
|
167
|
+
"last_tag": last_tag,
|
|
168
|
+
"repo_url": repo_url,
|
|
169
|
+
"commits": commits,
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
print(json.dumps(result, indent=2))
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
if __name__ == "__main__":
|
|
176
|
+
main()
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
release:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: astral-sh/setup-uv@v5
|
|
16
|
+
- run: uv python install
|
|
17
|
+
|
|
18
|
+
# https://docs.pypi.org/trusted-publishers/using-a-publisher/
|
|
19
|
+
- name: Mint API token
|
|
20
|
+
id: mint-token
|
|
21
|
+
run: |
|
|
22
|
+
resp=$(curl -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
|
|
23
|
+
"$ACTIONS_ID_TOKEN_REQUEST_URL&audience=pypi")
|
|
24
|
+
oidc_token=$(jq -r '.value' <<< "${resp}")
|
|
25
|
+
resp=$(curl -X POST https://pypi.org/_/oidc/mint-token -d "{\"token\": \"${oidc_token}\"}")
|
|
26
|
+
api_token=$(jq -r '.token' <<< "${resp}")
|
|
27
|
+
echo "::add-mask::${api_token}"
|
|
28
|
+
echo "api-token=${api_token}" >> "${GITHUB_OUTPUT}"
|
|
29
|
+
|
|
30
|
+
- run: uv build && uv publish
|
|
31
|
+
env:
|
|
32
|
+
UV_PUBLISH_TOKEN: ${{ steps.mint-token.outputs.api-token }}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: plainx.dev
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Development tools for plainx package developers, including release automation.
|
|
5
|
+
Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
|
|
6
|
+
License-Expression: BSD-3-Clause
|
|
7
|
+
Requires-Python: >=3.13
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
# plainx-dev
|
|
11
|
+
|
|
12
|
+
Development tools for plainx package developers.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
Add as a dev dependency:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
uv add --dev plainx-dev
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Skills
|
|
23
|
+
|
|
24
|
+
After installing, run `plain agent install` to copy skills to your `.claude/` directory.
|
|
25
|
+
|
|
26
|
+
### /plainx-release
|
|
27
|
+
|
|
28
|
+
A release workflow skill that helps you:
|
|
29
|
+
|
|
30
|
+
- Analyze commits and suggest version bump type (major/minor/patch)
|
|
31
|
+
- Generate release notes from actual code changes
|
|
32
|
+
- Update CHANGELOG.md
|
|
33
|
+
- Guide through commit, tag, and push steps
|
|
34
|
+
|
|
35
|
+
Usage:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
/plainx-release
|
|
39
|
+
/plainx-release --major
|
|
40
|
+
/plainx-release --minor
|
|
41
|
+
/plainx-release --patch
|
|
42
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
plainx/dev/CHANGELOG.md,sha256=UaeXQEf3pVrgjDznfhmn96-5DLjYz1VngRg4a69eQM0,404
|
|
2
|
+
plainx/dev/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
plainx/dev/agents/.claude/skills/plainx-release/SKILL.md,sha256=ejl0g7aOM2o6eCaJVfYb3KPrJ3uoGzVB3t0tmVOF1So,6419
|
|
4
|
+
plainx/dev/agents/.claude/skills/plainx-release/get-package-info,sha256=9F6s78ZxpI5n_H-hahABuTw1kTotiKRhM5pL8HyLVfc,4908
|
|
5
|
+
plainx/dev/agents/.claude/skills/plainx-release/release-workflow.yml,sha256=NgccczrHmTw2yZLnTq0GeL5FZ7InJFMECaVhZaAsyVs,955
|
|
6
|
+
plainx_dev-0.1.0.dist-info/METADATA,sha256=mAEw3Wn-EbZEGb-xTbdCoHl-Pg6IVKXaEM554pz3WV8,894
|
|
7
|
+
plainx_dev-0.1.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
8
|
+
plainx_dev-0.1.0.dist-info/RECORD,,
|