|
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 [email protected]: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