1- import os
2- import tempfile
31from pathlib import Path
4- from shutil import which
5- from subprocess import call
62
73import semver
84from invoke import run as invoke_run
@@ -19,16 +15,9 @@ def test_version():
1915 assert __version__ == "{version_string}"
2016"""
2117
22- RELEASE_NOTES_TEMPLATE = """# Write the release notes here
23- # Delete the version title to cancel
24- Version {version_string}
25- {underline}
26- """
27-
2818HERE = Path (__file__ ).parent
2919
3020DASH_BOOTSTRAP_DIR = HERE / "dash_bootstrap_components"
31- JS_DIR = HERE
3221
3322
3423@task (help = {"version" : "Version number to release" })
@@ -39,51 +28,45 @@ def prerelease(ctx, version):
3928 - Bump the version number
4029 - Push a release to pypi
4130 """
42- check_prerequisites ()
43- info (f"Releasing version { version } as prerelease" )
44- build_publish (version )
31+ info (f"Creating prerelease branch for { version } " )
32+ set_source_version (version )
33+ run (f"git checkout -b prerelease/{ version } " )
34+ run (
35+ "git add package.json package-lock.json "
36+ "dash_bootstrap_components/__init__.py "
37+ "tests/test_version.py"
38+ )
39+ run (f'git commit -m "Set version to { version } "' )
40+ run (f"git push origin prerelease/{ version } " )
4541
4642
4743@task (help = {"version" : "Version number to release" })
4844def release (ctx , version ):
4945 """
5046 Release a new version
5147 Running this task will:
52- - Prompt the user for a changelog and write it to
53- the release notes
54- - Commit the release notes
48+ - Create a release branch
5549 - Bump the version number
56- - Push a release to pypi
57- - commit the version changes to source control
58- - tag the commit
50+ Release notes should be written in the body of the pull request. When
51+ changes are merged GitHub actions will
52+ - Build the package
53+ - Push a release to PyPI
54+ - Create a release
55+ - Revert to a dev version change.
5956 """
60- check_prerequisites ( )
61- info ( f"Releasing version { version } as full release" )
57+ info ( f"Creating release branch for { version } " )
58+ set_source_version ( version )
6259 set_documentation_version (version )
63- release_notes_lines = get_release_notes (version )
6460
65- if release_notes_lines is None :
66- error ("No release notes: exiting" )
67- exit ()
68-
69- info ("Writing release notes to changelog.tmp" )
70- with open ("changelog.tmp" , "w" ) as f :
71- f .writelines (release_notes_lines )
72-
73- # TODO when we have release notes, these should be amended here
74-
75- build_publish (version )
76-
77- info ("Committing version changes" )
78- run (f"git checkout -b release-{ version } " )
61+ run (f"git checkout -b release/{ version } " )
7962 run (
80- "git add package.json package-lock.json tests/test_version.py"
81- "docs/requirements.txt dash_bootstrap_components/_version.py"
63+ "git add package.json package-lock.json "
64+ "docs/requirements.txt "
65+ "dash_bootstrap_components/__init__.py "
66+ "tests/test_version.py"
8267 )
8368 run (f'git commit -m "Bump version to { version } "' )
84- info (f"Tagging version { version } and pushing to GitHub" )
85- run (f'git tag -a "{ version } " -F changelog.tmp' )
86- run (f"git push origin release-{ version } --tags" )
69+ run (f"git push origin release/{ version } " )
8770
8871
8972@task
@@ -104,23 +87,7 @@ def copy_examples(ctx):
10487 )
10588
10689
107- @task (copy_examples )
108- def documentation (ctx ):
109- """
110- Push documentation to Heroku
111- """
112- info ("Pushing documentation to Heroku" )
113- run ("git checkout -b inv-push-docs" )
114- run ("git add docs/examples/vendor/*.py -f" )
115- run ('git commit -m "Add examples" --allow-empty' )
116- run ("git subtree split --prefix docs -b inv-push-docs-subtree" )
117- run ("git push -f heroku inv-push-docs-subtree:master" )
118- run ("git checkout master" )
119- run ("git branch -D inv-push-docs inv-push-docs-subtree" )
120-
121-
12290@task (
123- documentation ,
12491 help = {
12592 "version" : "Version number to finalize. Must be "
12693 "the same version number that was used in the release."
@@ -133,54 +100,24 @@ def postrelease(ctx, version):
133100 - bump the version to the next dev version
134101 - push changes to master
135102 """
136- new_version = semver .bump_patch (version ) + "-dev"
137- info (f"Bumping version numbers to { new_version } and committing" )
138- set_pyversion (new_version )
139- set_jsversion (new_version )
140- run (f"git checkout -b postrelease-{ version } " )
141- run (
142- "git add package.json package-lock.json tests/test_version.py "
143- "dash_bootstrap_components/_version.py"
144- )
145- run ('git commit -m "Back to dev"' )
146- run (f"git push origin postrelease-{ version } " )
147-
148-
149- def build_publish (version ):
150- info ("Cleaning" )
151- clean ()
152- info ("Updating versions" )
153- set_pyversion (version )
154- set_jsversion (version )
155- info ("Building JavaScript components" )
156- build_js ()
157- info ("Building and uploading Python source distribution" )
158- info ("PyPI credentials:" )
159- release_python_sdist ()
160-
161-
162- def clean ():
163- paths_to_clean = ["dash_bootstrap_components/_components" , "dist/" , "lib/" ]
164- for path in paths_to_clean :
165- run (f"rm -rf { path } " )
166-
103+ clean_version = semver .finalize_version (version )
104+ if clean_version == version :
105+ # last release was full release, bump patch
106+ new_version = semver .bump_patch (version ) + "-dev"
107+ else :
108+ # last release was prerelease, revert to dev version
109+ new_version = clean_version + "-dev"
167110
168- def build_js ():
169- os .chdir (JS_DIR )
170- try :
171- run ("npm install" )
172- run ("npm publish" )
173- finally :
174- os .chdir (HERE )
111+ info (f"Bumping version numbers to { new_version } and committing" )
112+ set_source_version (new_version )
175113
176114
177- def release_python_sdist ():
178- run ("rm -f dist/*" )
179- run ("python setup.py sdist" )
180- invoke_run ("twine upload dist/*" )
115+ def set_source_version (version ):
116+ set_js_version (version )
117+ set_py_version (version )
181118
182119
183- def set_pyversion (version ):
120+ def set_py_version (version ):
184121 version = normalize_version (version )
185122 init_path = DASH_BOOTSTRAP_DIR / "__init__.py"
186123 with init_path .open ("r" ) as f :
@@ -197,7 +134,7 @@ def set_pyversion(version):
197134 f .write (TEST_VERSION_TEMPLATE .format (version_string = version ))
198135
199136
200- def set_jsversion (version ):
137+ def set_js_version (version ):
201138 version = normalize_version (version )
202139 package_json_path = HERE / "package.json"
203140 with package_json_path .open () as f :
@@ -222,51 +159,6 @@ def set_documentation_version(version):
222159 f .writelines (docs_requirements )
223160
224161
225- def get_release_notes (version ):
226- version = normalize_version (version )
227- underline = "=" * len (f"Version { version } " )
228- initial_message = RELEASE_NOTES_TEMPLATE .format (
229- version_string = version , underline = underline
230- )
231- lines = open_editor (initial_message )
232- non_commented_lines = [line for line in lines if not line .startswith ("#" )]
233- changelog = "" .join (non_commented_lines )
234- if version in changelog :
235- if not non_commented_lines [- 1 ].isspace ():
236- non_commented_lines .append ("\n " )
237- return non_commented_lines
238- else :
239- return None
240-
241-
242- def open_editor (initial_message ):
243- editor = os .environ .get ("EDITOR" , "vim" )
244- tmp = tempfile .NamedTemporaryFile (suffix = ".tmp" )
245- fname = tmp .name
246-
247- with open (fname , "w" ) as f :
248- f .write (initial_message )
249- f .flush ()
250-
251- call ([editor , fname ], close_fds = True )
252-
253- with open (fname , "r" ) as f :
254- lines = f .readlines ()
255-
256- return lines
257-
258-
259- def check_prerequisites ():
260- for executable in ["twine" , "npm" , "dash-generate-components" ]:
261- if which (executable ) is None :
262- error (
263- f"{ executable } executable not found. "
264- f"You must have { executable } to release "
265- "dash-bootstrap-components."
266- )
267- exit (127 )
268-
269-
270162def normalize_version (version ):
271163 version_info = semver .parse_version_info (version )
272164 version_string = str (version_info )
0 commit comments