|
1 | | -# Making a JupyterLab release |
2 | | - |
3 | | -This document guides a contributor through creating a release of JupyterLab. |
4 | | - |
5 | | -Review `CONTRIBUTING.md`. Make sure all the tools needed to generate the |
6 | | -built JavaScript files are properly installed. |
7 | | - |
8 | | -## Creating a full release |
9 | | - |
10 | | -We publish the npm packages, a Python source package, and a Python universal |
11 | | -binary wheel. We also publish a conda package on conda-forge (see below). See |
12 | | -the Python docs on [package |
13 | | -uploading](https://packaging.python.org/guides/tool-recommendations/) for twine |
14 | | -setup instructions and for why twine is the recommended method. |
15 | | - |
16 | | -## Getting a clean environment |
17 | | - |
18 | | -For convenience, here is a script for getting a completely clean repo. This |
19 | | -makes sure that we don't have any extra tags or commits in our repo (especially |
20 | | -since we will push our tags later in the process), and that we are on the correct branch. The script creates a conda env, pulls down a git checkout with the |
21 | | -appropriate branch, and installs JupyterLab with `pip install -e .`. |
22 | | - |
23 | | -Make sure you are running an sh-compatible shell, and it is set up to be able to do `conda activate`. Then do: |
24 | | - |
25 | | -```bash |
26 | | -source scripts/release_prep.sh <branch_name> |
27 | | -``` |
28 | | - |
29 | | -## Bump version |
30 | | - |
31 | | -The next step is to bump the appropriate version numbers. We use |
32 | | -[bump2version](https://github.com/c4urself/bump2version) to manage the Python |
33 | | -version, and we keep the JS versions and tags in sync with the release cycle. |
34 | | - |
35 | | -Here is an example of how version numbers progress through a release process. |
36 | | -Choose and run an appropriate command to bump version numbers for this release. |
37 | | - |
38 | | -| Command | Python Version Change | NPM Version change | |
39 | | -| -------------------------- | --------------------- | ---------------------------------- | |
40 | | -| `jlpm bumpversion minor` | x.y.z-> x.(y+1).0.a0 | All a.b.c -> a.(b+10).0-alpha.0 | |
41 | | -| `jlpm bumpversion build` | x.y.z.a0-> x.y.z.a1 | All a.b.c-alpha.0 -> a.b.c-alpha.1 | |
42 | | -| `jlpm bumpversion release` | x.y.z.a1-> x.y.z.b0 | All a.b.c-alpha.1 -> a.b.c-beta.0 | |
43 | | -| `jlpm bumpversion release` | x.y.z.a1-> x.y.z.rc0 | All a.b.c-alpha.1 -> a.b.c-rc.0 | |
44 | | -| `jlpm bumpversion release` | x.y.z.rc0-> x.y.z | All a.b.c-rc0 -> a.b.c | |
45 | | -| `jlpm bumpversion patch` | x.y.z -> x.y.(z+1) | Changed a.b.c -> a.b.(c+1) | |
46 | | - |
47 | | -Note: For a minor release, we bump the JS packages by 10 versions so that |
48 | | -we are not competing amongst the minor releases for version numbers. |
49 | | -We are essentially sub-dividing semver to allow us to bump minor versions |
50 | | -of the JS packages as many times as we need to for minor releases of the |
51 | | -top level JupyterLab application. |
52 | | - |
53 | | -Other note: It's ok if `yarn-deduplicate` exits with a non zero code. This is |
54 | | -expected! |
55 | | - |
56 | | -### JS major release(s) |
57 | | - |
58 | | -In a major Python release, we can have one or more JavaScript packages also have |
59 | | -a major bump. During the prerelease stage of a major release, if there is a |
60 | | -backwards-incompatible change to a JS package, bump the major version number for |
61 | | -that JS package: |
62 | | - |
63 | | -`jlpm bump:js:major [...packages]` |
64 | | - |
65 | | -Results: |
66 | | - |
67 | | -- Python package is not affected. |
68 | | -- JS dependencies are also bumped a major version. |
69 | | -- Packages that have already had a major bump in this prerelease cycle are not affected. |
70 | | -- All affected packages changed to match the current release type of the Python package (`alpha`, `beta`, or `rc`). |
71 | | - |
72 | | -## Publishing Packages |
73 | | - |
74 | | -Now publish the JS packages |
75 | | - |
76 | | -```bash |
77 | | -npm run publish:js |
78 | | -``` |
79 | | - |
80 | | -If there is a network error during JS publish, run `npm run publish:js --skip-build` to resume publish without requiring another clean and build phase of the JS packages. |
81 | | - |
82 | | -Note that the use of `npm` instead of `jlpm` is [significant on Windows](https://github.com/jupyterlab/jupyterlab/issues/6733). |
83 | | - |
84 | | -Next, prepare the python release by running: |
85 | | - |
86 | | -```bash |
87 | | -npm run prepare:python-release |
88 | | -``` |
89 | | - |
90 | | -This will update the Python package to use the new JS packages and |
91 | | -create the Python release assets. Note: sometimes the npm registry |
92 | | -is slow to update with the new packages, so this script tries to fetch |
93 | | -the packages until they are available. |
94 | | - |
95 | | -At this point, run the `./scripts/release_test.sh` to test the wheel in |
96 | | -a fresh conda environment with and without extensions installed. Open and run |
97 | | -the Outputs notebook and verify everything runs properly. Also add a cell with the following code and make sure the widget renders: |
98 | | - |
99 | | -```python |
100 | | -from ipywidgets import IntSlider |
101 | | -IntSlider() |
102 | | -``` |
103 | | - |
104 | | -## Finish |
105 | | - |
106 | | -Follow instructions printed at the end of the publish step above: |
107 | | - |
108 | | -```bash |
109 | | -twine upload dist/* |
110 | | -git push origin --tags <BRANCH> |
111 | | -``` |
112 | | - |
113 | | -These lines: |
114 | | - |
115 | | -- upload to pypi with twine |
116 | | -- double-check what branch you are on, then push changes to the correct upstream branch with the `--tags` option. |
117 | | - |
118 | | -## Post release candidate checklist |
119 | | - |
120 | | -- [ ] Modify and run `python scripts/milestone_check.py` to check the issues assigned to this milestone |
121 | | -- [ ] Write [release highlights](CHANGELOG.md), starting with: |
122 | | - ```bash |
123 | | - loghub jupyterlab/jupyterlab -m XXX -t $GITHUB_TOKEN --template scripts/release_template.txt |
124 | | - ``` |
125 | | -- [ ] Test the release candidate in a clean environment |
126 | | -- [ ] Make sure the CI builds pass |
127 | | - - The build will fail if we publish a new package because by default it is |
128 | | - private. Use `npm access public @jupyterlab/<name>` to make it public. |
129 | | - - The build will fail if we forget to include `style/` in the `files:` |
130 | | - of a package (it will fail on the `jupyter lab build` command because |
131 | | - webpack cannot find the referenced styles to import. |
132 | | -- [ ] Update the other repos: |
133 | | - - [ ] https://github.com/jupyterlab/extension-cookiecutter-js |
134 | | - - [ ] https://github.com/jupyterlab/extension-cookiecutter-ts |
135 | | - - [ ] https://github.com/jupyterlab/mimerender-cookiecutter |
136 | | - - [ ] https://github.com/jupyterlab/mimerender-cookiecutter-ts |
137 | | - - [ ] https://github.com/jupyterlab/theme-cookiecutter |
138 | | - - [ ] https://github.com/jupyterlab/jupyter-renderers |
139 | | -- [ ] Add a tag to [ts cookiecutter](https://github.com/jupyterlab/extension-cookiecutter-ts) with the new JupyterLab version |
140 | | -- [ ] Update the extension examples: |
141 | | - - [ ] [Notebook toolbar button](https://github.com/jupyterlab/jupyterlab/blob/3.3.x/docs/source/extension/notebook.rst#adding-a-button-to-the-toolbar) |
142 | | -- [ ] Update the [extension tutorial](https://github.com/jupyterlab/jupyterlab/blob/3.3.x/RELEASE.md#updating-the-extension-tutorial) |
143 | | -- [ ] At this point, there may have been some more commits merged. Run `python scripts/milestone_check.py` to check the issues assigned to this milestone one more time. Update changelog if necessary. |
144 | | - |
145 | | -Now do the actual final release: |
146 | | - |
147 | | -- [ ] Run `jlpm run bumpversion release` to switch to final release |
148 | | -- [ ] Push the commit and tags to master |
149 | | -- [ ] Run `npm run publish:all` to publish the packages |
150 | | -- [ ] Create a branch for the release and push to GitHub |
151 | | -- [ ] Update the API [docs](#updating-api-docs) |
152 | | -- [ ] Merge the PRs on the other repos and set the default branch of the |
153 | | - xckd repo |
154 | | -- [ ] Publish to [conda-forge](https://github.com/jupyterlab/jupyterlab/blob/3.3.x/RELEASE.md#publishing-to-conda-forge). |
155 | | - |
156 | | -After a few days (to allow for possible patch releases), set up development for |
157 | | -the next release: |
158 | | - |
159 | | -- [ ] Run `jlpm run bumpversion minor` to bump to alpha for the next alpha release |
160 | | -- [ ] Put the commit and tags to master |
161 | | -- [ ] Run `npm run publish:all` to publish the packages |
162 | | -- [ ] Release the other repos as appropriate |
163 | | -- [ ] Update version for [binder](https://github.com/jupyterlab/jupyterlab/blob/3.3.x/RELEASE.md#update-version-for-binder) |
164 | | - |
165 | | -### Updating the extension tutorial |
166 | | - |
167 | | -- Clone the repo if you don't have it |
168 | | - |
169 | | -```bash |
170 | | -git clone git@github.com:jupyterlab/jupyterlab_apod.git |
171 | | -``` |
172 | | - |
173 | | -#### Simple updates by rebasing |
174 | | - |
175 | | -If the updates are simple, it may be enough to check out a new branch based on |
176 | | -the current base branch, then rebase from the root commit, editing the root |
177 | | -commit and other commits that involve installing packages to update to the new |
178 | | -versions: |
179 | | - |
180 | | -```bash |
181 | | -git checkout -b BRANCH # whatever the new version is, e.g., 1.0 |
182 | | -git rebase -i --root |
183 | | -``` |
184 | | - |
185 | | -"Edit" the commits that involve installing packages, so you can update the |
186 | | -`package.json`. Amend the last commit to bump the version number in package.json |
187 | | -in preparation for publishing to npm. Then skip down to the step below about |
188 | | -publishing the extension tutorial. If the edits are more substantial than just |
189 | | -updating package versions, then do the next steps instead. |
190 | | - |
191 | | -#### Creating the tutorial from scratch |
192 | | - |
193 | | -- Create a new empty branch in the extension repo. |
194 | | - |
195 | | -```bash |
196 | | -git checkout --orphan name-of-branch |
197 | | -git rm -rf . |
198 | | -git clean -dfx |
199 | | -cookiecutter -o initial path-to-local-extension-cookiecutter-ts |
200 | | -# Fill in the values from the previous branch package.json initial commit |
201 | | -cp -r initial/jupyterlab_apod . |
202 | | -rm -rf initial |
203 | | -``` |
204 | | - |
205 | | -- Create a new PR in JupyterLab. |
206 | | -- Run through the tutorial in the PR, making commits and updating |
207 | | - the tutorial as appropriate. |
208 | | -- For the publish section of the readme, use the `README` |
209 | | - file from the previous branch, as well as the `package.json` fields up to |
210 | | - `license`. Bump the version number in preparation for publishing to npm. |
211 | | - |
212 | | -#### Publishing extension tutorial changes |
213 | | - |
214 | | -- Tag commits in the branch with the appropriate `branch-step` tag. If you are at the final commit, you can tag all commits with the below, replacing `BRANCH` with the branch name (e.g., `1.0-01-show-a-panel`) ```bash |
215 | | - git tag BRANCH-01-show-a-panel HEAD~4 |
216 | | - git tag BRANCH-02-show-an-image HEAD~3 |
217 | | - git tag BRANCH-03-style-and-attribute HEAD~2 |
218 | | - git tag BRANCH-04-refactor-and-refresh HEAD~1 |
219 | | - git tag BRANCH-05-restore-panel-state HEAD |
220 | | - |
221 | | - ``` |
222 | | -
|
223 | | - ``` |
224 | | - |
225 | | -- Push the branch with the new tags |
226 | | - ```bash |
227 | | - git push origin BRANCH --tags |
228 | | - ``` |
229 | | - Set the branch as the default branch (see `github.com/jupyterlab/jupyterlab_apod/settings/branches`). |
230 | | -- If there were changes to the example in the documentation, submit a PR to JupyterLab |
231 | | -- Publish the new `jupyterlab_apod` python package. Make sure to update the version |
232 | | - number in the last commit of the branch. |
233 | | - ```bash |
234 | | - twine upload dist/* |
235 | | - ``` |
236 | | - |
237 | | -If you make a mistake and need to start over, clear the tags using the |
238 | | -following pattern (replacing `BRANCH` with the branch name): |
239 | | - |
240 | | -```bash |
241 | | -git tag | grep BRANCH | xargs git tag -d |
242 | | -``` |
243 | | - |
244 | | -### Publishing to conda-forge |
245 | | - |
246 | | -- If no requirements have changed, wait for the conda-forge autotick-bot. |
247 | | -- Otherwise: |
248 | | -- Get the sha256 hash for conda-forge release: |
249 | | - |
250 | | -```bash |
251 | | -shasum -a 256 dist/*.tar.gz |
252 | | -``` |
253 | | - |
254 | | -- Fork https://github.com/conda-forge/jupyterlab-feedstock |
255 | | -- Create a PR with the version bump |
256 | | -- Update `recipe/meta.yaml` with the new version and md5 and reset the build number to 0. |
257 | | - |
258 | | -## Updating API Docs |
259 | | - |
260 | | -Run `source scripts/docs_push.sh` to update the `gh-pages` branch that backs http://jupyterlab.github.io/jupyterlab/. |
261 | | - |
262 | | -## Making a patch release |
263 | | - |
264 | | -- Backport the change to the previous release branch |
265 | | -- Run the following script, where the package is in `/packages/package-folder-name` (note that multiple packages can be given, or no packages for a Python-only patch release): |
266 | | - |
267 | | -```bash |
268 | | -jlpm run patch:release package-folder-name |
269 | | -``` |
270 | | - |
271 | | -- Push the resulting commit and tag |
272 | | - |
273 | | -## Update version for binder |
274 | | - |
275 | | -Each time we release JupyterLab, we should update the version of JupyterLab |
276 | | -used in binder and repo2docker. Here is an example PR that updates the |
277 | | -relevant files: |
278 | | - |
279 | | -https://github.com/jupyter/repo2docker/pull/169/files |
280 | | - |
281 | | -This needs to be done in both the conda and pip buildpacks in both the |
282 | | -frozen and non-frozen version of the files. |
0 commit comments