0
# Release Management
1
2
Automated publishing to PyPI, GitHub releases, and changelog generation. nbdev provides comprehensive release management tools that handle version bumping, changelog generation, and publishing to multiple platforms.
3
4
## Capabilities
5
6
### Release Class
7
8
Main class for managing package releases across platforms.
9
10
```python { .api }
11
class Release:
12
"""
13
Release management for nbdev projects.
14
15
Handles the complete release process including:
16
- Version management
17
- Changelog generation
18
- PyPI publishing
19
- GitHub release creation
20
- Documentation updates
21
"""
22
23
def __init__(self, owner: str = None, repo: str = None, token: str = None):
24
"""
25
Initialize release manager.
26
27
Args:
28
owner: GitHub repository owner
29
repo: GitHub repository name
30
token: GitHub API token for releases
31
"""
32
```
33
34
### Git Release Functions
35
36
Create git tags and releases.
37
38
```python { .api }
39
def release_git(tag: str = None, msg: str = None):
40
"""
41
Create git tag and release.
42
43
Args:
44
tag: Version tag (defaults to current version in settings)
45
msg: Release message (defaults to changelog entry)
46
47
Creates a git tag for the current version and pushes it to
48
the remote repository for release tracking.
49
"""
50
```
51
52
### GitHub Integration
53
54
Create GitHub releases with assets and release notes.
55
56
```python { .api }
57
def release_gh(tag: str = None, notes: str = None,
58
draft: bool = False, prerelease: bool = False):
59
"""
60
Create GitHub release.
61
62
Args:
63
tag: Release tag (defaults to current version)
64
notes: Release notes (defaults to changelog)
65
draft: Create as draft release
66
prerelease: Mark as prerelease
67
68
Creates a GitHub release with automatically generated
69
release notes from changelog and project information.
70
"""
71
```
72
73
### Changelog Management
74
75
Generate and manage project changelogs.
76
77
```python { .api }
78
def changelog(tag: str = None, since_tag: str = None):
79
"""
80
Generate changelog for release.
81
82
Args:
83
tag: Target release tag
84
since_tag: Previous release tag to compare from
85
86
Returns:
87
Formatted changelog with commits, issues, and PRs
88
since the last release.
89
"""
90
```
91
92
### PyPI Integration
93
94
Get information about PyPI packages and releases.
95
96
```python { .api }
97
def pypi_json(name: str):
98
"""
99
Get PyPI package information.
100
101
Args:
102
name: Package name on PyPI
103
104
Returns:
105
JSON data about the package including versions,
106
metadata, and download statistics.
107
"""
108
109
def latest_pypi(name: str):
110
"""
111
Get latest PyPI version for a package.
112
113
Args:
114
name: Package name on PyPI
115
116
Returns:
117
Latest version string available on PyPI
118
"""
119
```
120
121
## Release Workflow
122
123
### Complete Release Process
124
125
```python
126
from nbdev.release import Release, release_git, release_gh, changelog
127
from nbdev.config import get_config
128
129
def complete_release(version: str):
130
"""Complete release workflow."""
131
132
config = get_config()
133
134
# 1. Update version in project
135
from nbdev.config import update_version
136
update_version(version)
137
138
# 2. Generate changelog
139
notes = changelog(tag=version)
140
print(f"Changelog:\n{notes}")
141
142
# 3. Create git release
143
release_git(tag=version, msg=f"Release {version}")
144
145
# 4. Create GitHub release
146
release_gh(tag=version, notes=notes)
147
148
# 5. Publish to PyPI (manual step)
149
print(f"Ready to publish {config.lib_name} {version} to PyPI")
150
print("Run: python -m build && twine upload dist/*")
151
152
complete_release("1.2.0")
153
```
154
155
### Version Management
156
157
```python
158
from nbdev.config import update_version, get_config
159
from nbdev.release import latest_pypi
160
161
def check_version_status():
162
"""Check current version against PyPI."""
163
164
config = get_config()
165
current_version = config.version
166
167
try:
168
pypi_version = latest_pypi(config.lib_name)
169
print(f"Current version: {current_version}")
170
print(f"PyPI version: {pypi_version}")
171
172
if current_version == pypi_version:
173
print("⚠ Version matches PyPI - need to bump version")
174
else:
175
print("✓ Version is different from PyPI")
176
177
except Exception as e:
178
print(f"Could not check PyPI: {e}")
179
180
check_version_status()
181
```
182
183
## GitHub Integration
184
185
### Release Creation
186
187
```python
188
from nbdev.release import Release, release_gh
189
190
# Create GitHub release with custom notes
191
release_notes = """
192
## New Features
193
- Added advanced export functionality
194
- Improved test performance
195
196
## Bug Fixes
197
- Fixed merge conflict resolution
198
- Resolved documentation links
199
200
## Breaking Changes
201
- Updated API for configuration management
202
"""
203
204
release_gh(tag="2.0.0", notes=release_notes)
205
```
206
207
### Draft Releases
208
209
```python
210
from nbdev.release import release_gh
211
212
# Create draft release for review
213
release_gh(tag="2.0.0-beta", draft=True, prerelease=True)
214
# Review and publish manually on GitHub
215
```
216
217
## Automation and CI/CD
218
219
### GitHub Actions Integration
220
221
```yaml
222
# .github/workflows/release.yml
223
name: Release
224
on:
225
push:
226
tags: ['v*']
227
228
jobs:
229
release:
230
runs-on: ubuntu-latest
231
steps:
232
- uses: actions/checkout@v3
233
- name: Setup Python
234
uses: actions/setup-python@v4
235
with:
236
python-version: '3.9'
237
- name: Install nbdev
238
run: pip install nbdev
239
- name: Create GitHub Release
240
run: python -c "from nbdev.release import release_gh; release_gh()"
241
env:
242
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
243
```
244
245
### Automated Version Bumping
246
247
```python
248
from nbdev.release import latest_pypi, Release
249
from nbdev.config import update_version, get_config
250
251
def auto_version_bump(bump_type='patch'):
252
"""Automatically bump version."""
253
254
config = get_config()
255
current = config.version
256
257
# Parse version (simple implementation)
258
parts = current.split('.')
259
major, minor, patch = map(int, parts)
260
261
if bump_type == 'major':
262
major += 1
263
minor = patch = 0
264
elif bump_type == 'minor':
265
minor += 1
266
patch = 0
267
else: # patch
268
patch += 1
269
270
new_version = f"{major}.{minor}.{patch}"
271
update_version(new_version)
272
273
print(f"Version bumped: {current} → {new_version}")
274
return new_version
275
276
# Bump patch version
277
new_ver = auto_version_bump('patch')
278
```
279
280
## Configuration
281
282
Release management uses configuration from `settings.ini`:
283
284
```ini
285
# Release configuration
286
version = 1.0.0
287
author = Your Name
288
author_email = you@example.com
289
copyright = 2024 onwards, %(author)s
290
license = apache2
291
git_url = https://github.com/yourusername/yourproject
292
```
293
294
## Constants and URLs
295
296
```python { .api }
297
GH_HOST: str
298
```
299
GitHub API host URL for release operations.
300
301
```python { .api }
302
CONDA_WARNING: str
303
```
304
Warning message about conda package publishing requirements.
305
306
## Advanced Release Features
307
308
### Multi-Platform Releases
309
310
```python
311
from nbdev.release import Release, release_gh
312
from nbdev.config import get_config
313
314
def multi_platform_release():
315
"""Release to multiple platforms."""
316
317
config = get_config()
318
version = config.version
319
320
# 1. GitHub release
321
release_gh(tag=version)
322
323
# 2. PyPI release (requires separate setup)
324
print("Publishing to PyPI...")
325
import subprocess
326
subprocess.run(['python', '-m', 'build'])
327
subprocess.run(['twine', 'upload', 'dist/*'])
328
329
# 3. Conda release (if configured)
330
print("Consider publishing to conda-forge")
331
print(CONDA_WARNING)
332
333
multi_platform_release()
334
```
335
336
### Release Validation
337
338
```python
339
from nbdev.release import pypi_json, latest_pypi
340
from nbdev.test import nbdev_test
341
from nbdev.export import nb_export
342
343
def validate_release():
344
"""Validate project before release."""
345
346
print("1. Running tests...")
347
if not nbdev_test():
348
return False, "Tests failed"
349
350
print("2. Checking exports...")
351
nb_export()
352
353
print("3. Checking PyPI status...")
354
config = get_config()
355
try:
356
current_pypi = latest_pypi(config.lib_name)
357
if current_pypi == config.version:
358
return False, "Version already exists on PyPI"
359
except:
360
pass # Package might not exist yet
361
362
return True, "Ready for release"
363
364
valid, message = validate_release()
365
print(f"Release validation: {message}")
366
```
367
368
**Complete Release Example:**
369
370
```python
371
from nbdev.release import Release, release_git, release_gh, changelog
372
from nbdev.config import update_version, get_config
373
from nbdev.test import nbdev_test
374
from nbdev.export import nb_export
375
376
def full_release_workflow(new_version: str):
377
"""Complete release workflow with validation."""
378
379
print(f"Starting release workflow for version {new_version}")
380
381
# 1. Validate current state
382
print("Validating project state...")
383
if not nbdev_test():
384
print("❌ Tests failed - aborting release")
385
return False
386
387
# 2. Update version
388
print(f"Updating version to {new_version}")
389
update_version(new_version)
390
391
# 3. Export latest code
392
print("Exporting notebooks...")
393
nb_export()
394
395
# 4. Generate changelog
396
print("Generating changelog...")
397
notes = changelog(tag=new_version)
398
399
# 5. Create releases
400
print("Creating git release...")
401
release_git(tag=new_version, msg=f"Release {new_version}")
402
403
print("Creating GitHub release...")
404
release_gh(tag=new_version, notes=notes)
405
406
print(f"✅ Release {new_version} completed successfully!")
407
print("Don't forget to publish to PyPI with:")
408
print(" python -m build && twine upload dist/*")
409
410
return True
411
412
# Execute full release
413
full_release_workflow("1.3.0")
414
```