mirror of https://github.com/zulip/zulip.git
dependencies: Switch to pnpm.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
b3f9fdf99a
commit
3a27b12a7d
|
@ -9,6 +9,7 @@ on:
|
||||||
- .github/workflows/production-suite.yml
|
- .github/workflows/production-suite.yml
|
||||||
- "**/migrations/**"
|
- "**/migrations/**"
|
||||||
- manage.py
|
- manage.py
|
||||||
|
- pnpm-lock.yaml
|
||||||
- puppet/**
|
- puppet/**
|
||||||
- requirements/**
|
- requirements/**
|
||||||
- scripts/**
|
- scripts/**
|
||||||
|
@ -17,7 +18,6 @@ on:
|
||||||
- web/postcss.config.js
|
- web/postcss.config.js
|
||||||
- web/third/**
|
- web/third/**
|
||||||
- web/webpack.config.ts
|
- web/webpack.config.ts
|
||||||
- yarn.lock
|
|
||||||
- zerver/worker/queue_processors.py
|
- zerver/worker/queue_processors.py
|
||||||
- zerver/lib/push_notifications.py
|
- zerver/lib/push_notifications.py
|
||||||
- zerver/decorator.py
|
- zerver/decorator.py
|
||||||
|
@ -68,16 +68,15 @@ jobs:
|
||||||
|
|
||||||
- name: Create cache directories
|
- name: Create cache directories
|
||||||
run: |
|
run: |
|
||||||
dirs=(/srv/zulip-{npm,venv,emoji}-cache)
|
dirs=(/srv/zulip-{venv,emoji}-cache)
|
||||||
sudo mkdir -p "${dirs[@]}"
|
sudo mkdir -p "${dirs[@]}"
|
||||||
sudo chown -R github "${dirs[@]}"
|
sudo chown -R github "${dirs[@]}"
|
||||||
|
|
||||||
- name: Restore node_modules cache
|
- name: Restore pnpm store
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: /srv/zulip-npm-cache
|
path: ~/.local/share/pnpm/store
|
||||||
key: v1-yarn-deps-focal-${{ hashFiles('package.json') }}-${{ hashFiles('yarn.lock') }}
|
key: v1-pnpm-store-focal-${{ hashFiles('pnpm-lock.yaml') }}
|
||||||
restore-keys: v1-yarn-deps-focal
|
|
||||||
|
|
||||||
- name: Restore python cache
|
- name: Restore python cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
|
@ -175,16 +174,15 @@ jobs:
|
||||||
|
|
||||||
- name: Create cache directories
|
- name: Create cache directories
|
||||||
run: |
|
run: |
|
||||||
dirs=(/srv/zulip-{npm,venv,emoji}-cache)
|
dirs=(/srv/zulip-{venv,emoji}-cache)
|
||||||
sudo mkdir -p "${dirs[@]}"
|
sudo mkdir -p "${dirs[@]}"
|
||||||
sudo chown -R github "${dirs[@]}"
|
sudo chown -R github "${dirs[@]}"
|
||||||
|
|
||||||
- name: Restore node_modules cache
|
- name: Restore pnpm store
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: /srv/zulip-npm-cache
|
path: ~/.local/share/pnpm/store
|
||||||
key: v1-yarn-deps-${{ matrix.os }}-${{ hashFiles('/tmp/package.json') }}-${{ hashFiles('/tmp/yarn.lock') }}
|
key: v1-pnpm-store-${{ matrix.os }}-${{ hashFiles('/tmp/pnpm-lock.yaml') }}
|
||||||
restore-keys: v1-yarn-deps-${{ matrix.os }}
|
|
||||||
|
|
||||||
- name: Install production
|
- name: Install production
|
||||||
run: sudo /tmp/production-install ${{ matrix.extra-args }}
|
run: sudo /tmp/production-install ${{ matrix.extra-args }}
|
||||||
|
@ -280,7 +278,7 @@ jobs:
|
||||||
|
|
||||||
- name: Create cache directories
|
- name: Create cache directories
|
||||||
run: |
|
run: |
|
||||||
dirs=(/srv/zulip-{npm,venv,emoji}-cache)
|
dirs=(/srv/zulip-{venv,emoji}-cache)
|
||||||
sudo mkdir -p "${dirs[@]}"
|
sudo mkdir -p "${dirs[@]}"
|
||||||
sudo chown -R github "${dirs[@]}"
|
sudo chown -R github "${dirs[@]}"
|
||||||
|
|
||||||
|
|
|
@ -64,16 +64,15 @@ jobs:
|
||||||
|
|
||||||
- name: Create cache directories
|
- name: Create cache directories
|
||||||
run: |
|
run: |
|
||||||
dirs=(/srv/zulip-{npm,venv,emoji}-cache)
|
dirs=(/srv/zulip-{venv,emoji}-cache)
|
||||||
sudo mkdir -p "${dirs[@]}"
|
sudo mkdir -p "${dirs[@]}"
|
||||||
sudo chown -R github "${dirs[@]}"
|
sudo chown -R github "${dirs[@]}"
|
||||||
|
|
||||||
- name: Restore node_modules cache
|
- name: Restore pnpm store
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: /srv/zulip-npm-cache
|
path: ~/.local/share/pnpm/store
|
||||||
key: v1-yarn-deps-${{ matrix.os }}-${{ hashFiles('package.json', 'yarn.lock') }}
|
key: v1-pnpm-store-${{ matrix.os }}-${{ hashFiles('pnpm-lock.yaml') }}
|
||||||
restore-keys: v1-yarn-deps-${{ matrix.os }}
|
|
||||||
|
|
||||||
- name: Restore python cache
|
- name: Restore python cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
|
|
|
@ -44,11 +44,11 @@ package-lock.json
|
||||||
# Static build
|
# Static build
|
||||||
*.mo
|
*.mo
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
|
/.pnpm-store
|
||||||
/node_modules
|
/node_modules
|
||||||
/prod-static
|
/prod-static
|
||||||
/staticfiles.json
|
/staticfiles.json
|
||||||
/webpack-stats-production.json
|
/webpack-stats-production.json
|
||||||
/yarn-error.log
|
|
||||||
zulip-git-version
|
zulip-git-version
|
||||||
|
|
||||||
# Test / analysis tools
|
# Test / analysis tools
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
pnpm-lock.yaml
|
||||||
/api_docs/**/*.md
|
/api_docs/**/*.md
|
||||||
/corporate/tests/stripe_fixtures
|
/corporate/tests/stripe_fixtures
|
||||||
/help/**/*.md
|
/help/**/*.md
|
||||||
|
|
|
@ -869,23 +869,6 @@ Likely causes are:
|
||||||
not, go to your VM settings and increase the RAM, then restart
|
not, go to your VM settings and increase the RAM, then restart
|
||||||
the VM.
|
the VM.
|
||||||
|
|
||||||
##### yarn install warnings
|
|
||||||
|
|
||||||
```console
|
|
||||||
$ yarn install
|
|
||||||
yarn install v0.24.5
|
|
||||||
[1/4] Resolving packages...
|
|
||||||
[2/4] Fetching packages...
|
|
||||||
warning fsevents@1.1.1: The platform "linux" is incompatible with this module.
|
|
||||||
info "fsevents@1.1.1" is an optional dependency and failed compatibility check. Excluding it from installation.
|
|
||||||
[3/4] Linking dependencies...
|
|
||||||
[4/4] Building fresh packages...
|
|
||||||
Done in 23.50s.
|
|
||||||
```
|
|
||||||
|
|
||||||
These are warnings produced by spammy third party JavaScript packages.
|
|
||||||
It is okay to proceed and start the Zulip server.
|
|
||||||
|
|
||||||
#### VBoxManage errors related to VT-x or WHvSetupPartition
|
#### VBoxManage errors related to VT-x or WHvSetupPartition
|
||||||
|
|
||||||
```console
|
```console
|
||||||
|
|
|
@ -160,18 +160,18 @@ $ tools/clean-branches --reviews
|
||||||
Deleting local branch review-original-5156 (was 5a1e982)
|
Deleting local branch review-original-5156 (was 5a1e982)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Merge conflict on yarn.lock file
|
## Merge conflict on `pnpm-lock.yaml` file
|
||||||
|
|
||||||
If there is a merge conflict on yarn.lock, yarn should be run to
|
If there is a merge conflict on `pnpm-lock.yaml`, pnpm should be run to
|
||||||
regenerate the file. _Important_ don't delete the yarn.lock file. Check out the
|
regenerate the file. _Important:_ don't delete the `pnpm-lock.yaml` file. Check out the
|
||||||
latest one from `origin/main` so that yarn knows the previous asset versions.
|
latest one from `origin/main` so that pnpm knows the previous asset versions.
|
||||||
|
|
||||||
Run the following commands
|
Run the following commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git checkout origin/main -- yarn.lock
|
git checkout origin/main -- pnpm-lock.yaml
|
||||||
yarn install
|
pnpm install
|
||||||
git add yarn.lock
|
git add pnpm-lock.yaml
|
||||||
git rebase --continue
|
git rebase --continue
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,7 @@ templating systems.
|
||||||
|
|
||||||
- `web/third/` Third-party JavaScript and CSS that has been vendored.
|
- `web/third/` Third-party JavaScript and CSS that has been vendored.
|
||||||
|
|
||||||
- `node_modules/` Third-party JavaScript installed via `yarn`.
|
- `node_modules/` Third-party JavaScript installed via pnpm.
|
||||||
|
|
||||||
- `web/shared/icons/` Icons placed in this directory are compiled
|
- `web/shared/icons/` Icons placed in this directory are compiled
|
||||||
into an icon font.
|
into an icon font.
|
||||||
|
|
|
@ -219,18 +219,13 @@ We use the same set of strategies described for Python dependencies
|
||||||
for most of our JavaScript dependencies, so we won't repeat the
|
for most of our JavaScript dependencies, so we won't repeat the
|
||||||
reasoning here.
|
reasoning here.
|
||||||
|
|
||||||
- In a fashion very analogous to the Python codebase,
|
- We use [pnpm][], a `pip`-like tool for JavaScript, to download most
|
||||||
`scripts/lib/node_cache.py` manages cached `node_modules`
|
JavaScript dependencies. pnpm talks to the standard [npm][]
|
||||||
directories in `/srv/zulip-npm-cache`. Each is named by its hash,
|
|
||||||
computed by the `generate_sha1sum_node_modules` function.
|
|
||||||
`scripts/lib/clean_node_cache.py` handles garbage-collection.
|
|
||||||
- We use [yarn][], a `pip`-like tool for JavaScript, to download most
|
|
||||||
JavaScript dependencies. Yarn talks to standard the [npm][]
|
|
||||||
repository. We use the standard `package.json` file to declare our
|
repository. We use the standard `package.json` file to declare our
|
||||||
direct dependencies, with sections for development and
|
direct dependencies, with sections for development and
|
||||||
production. Yarn takes care of pinning the versions of indirect
|
production. pnpm takes care of pinning the versions of indirect
|
||||||
dependencies in the `yarn.lock` file; `yarn install` updates the
|
dependencies in the `pnpm-lock.yaml` file; `pnpm install` updates the
|
||||||
`yarn.lock` files.
|
`pnpm-lock.yaml` file.
|
||||||
- `tools/update-prod-static`. This process is discussed in detail in
|
- `tools/update-prod-static`. This process is discussed in detail in
|
||||||
the [static asset pipeline](html-css.md#static-asset-pipeline)
|
the [static asset pipeline](html-css.md#static-asset-pipeline)
|
||||||
article, but we don't use the `node_modules` directories directly in
|
article, but we don't use the `node_modules` directories directly in
|
||||||
|
@ -247,11 +242,11 @@ reasoning here.
|
||||||
these checked-in versions of dependencies and instead use versions
|
these checked-in versions of dependencies and instead use versions
|
||||||
managed by the npm repositories.
|
managed by the npm repositories.
|
||||||
|
|
||||||
## Node.js and Yarn
|
## Node.js and pnpm
|
||||||
|
|
||||||
Node.js is installed by `scripts/lib/install-node` to
|
Node.js is installed by `scripts/lib/install-node` to
|
||||||
`/srv/zulip-node` and symlinked to `/usr/local/bin/node`. A Yarn
|
`/srv/zulip-node` and symlinked to `/usr/local/bin/node`. A pnpm
|
||||||
symlink at `/usr/local/bin/yarn` is managed by
|
symlink at `/usr/local/bin/pnpm` is managed by
|
||||||
[Corepack](https://nodejs.org/api/corepack.html).
|
[Corepack](https://nodejs.org/api/corepack.html).
|
||||||
|
|
||||||
We don't do anything special to try to manage multiple versions of
|
We don't do anything special to try to manage multiple versions of
|
||||||
|
@ -338,7 +333,7 @@ usually one needs to think about making changes in 3 places:
|
||||||
|
|
||||||
[virtualenv]: https://virtualenv.pypa.io/en/stable/
|
[virtualenv]: https://virtualenv.pypa.io/en/stable/
|
||||||
[virtualenv-clone]: https://github.com/edwardgeorge/virtualenv-clone/
|
[virtualenv-clone]: https://github.com/edwardgeorge/virtualenv-clone/
|
||||||
[yarn]: https://yarnpkg.com/
|
[pnpm]: https://pnpm.io/
|
||||||
[npm]: https://npmjs.com/
|
[npm]: https://npmjs.com/
|
||||||
[iamcal]: https://github.com/iamcal/emoji-data
|
[iamcal]: https://github.com/iamcal/emoji-data
|
||||||
[pygments]: https://pygments.org/
|
[pygments]: https://pygments.org/
|
||||||
|
|
|
@ -177,8 +177,8 @@ To add a static file to the app (JavaScript, TypeScript, CSS, images, etc),
|
||||||
first add it to the appropriate place under `static/`.
|
first add it to the appropriate place under `static/`.
|
||||||
|
|
||||||
- Third-party packages from the NPM repository should be added to
|
- Third-party packages from the NPM repository should be added to
|
||||||
`package.json` for management by yarn, this allows them to be upgraded easily
|
`package.json` for management by pnpm, this allows them to be upgraded easily
|
||||||
and not bloat our codebase. Run `./tools/provision` for yarn to install the
|
and not bloat our codebase. Run `./tools/provision` for pnpm to install the
|
||||||
new packages and update its lock file. You should also update
|
new packages and update its lock file. You should also update
|
||||||
`PROVISION_VERSION` in `version.py` in the same commit.
|
`PROVISION_VERSION` in `version.py` in the same commit.
|
||||||
- Third-party files that we have patched should all go in
|
- Third-party files that we have patched should all go in
|
||||||
|
|
20
package.json
20
package.json
|
@ -1,11 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "zulip",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"license": "Apache-2.0",
|
|
||||||
"description": "",
|
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "",
|
"packageManager": "pnpm@7.30.0+sha256.f5e9a8789a6d41925dc4fcacae2e18537c7bf297306ce506d7730e15082626f9",
|
||||||
"packageManager": "yarn@1.22.19+sha256.732620bac8b1690d507274f025f3c6cfdc3627a84d9642e38a07452cc00e0f2e",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "^7.5.5",
|
"@babel/core": "^7.5.5",
|
||||||
"@babel/preset-env": "^7.5.5",
|
"@babel/preset-env": "^7.5.5",
|
||||||
|
@ -123,7 +118,7 @@
|
||||||
"openapi-types": "^12.0.0",
|
"openapi-types": "^12.0.0",
|
||||||
"prettier": "^2.8.4",
|
"prettier": "^2.8.4",
|
||||||
"puppeteer": "19.7.2",
|
"puppeteer": "19.7.2",
|
||||||
"source-map": "https://codeload.github.com/benthemonkey/source-map/tar.gz/d95423f77edef6cbb9e21d2d6014c7de85ae220a",
|
"source-map": "npm:source-map-js@1.0.1",
|
||||||
"stylelint": "^15.2.0",
|
"stylelint": "^15.2.0",
|
||||||
"stylelint-config-standard": "^31.0.0",
|
"stylelint-config-standard": "^31.0.0",
|
||||||
"svgo": "^3.0.0",
|
"svgo": "^3.0.0",
|
||||||
|
@ -135,15 +130,12 @@
|
||||||
"xvfb": "^0.4.0",
|
"xvfb": "^0.4.0",
|
||||||
"yaml": "^2.0.0-8",
|
"yaml": "^2.0.0-8",
|
||||||
"yargs": "^17.1.1",
|
"yargs": "^17.1.1",
|
||||||
"yarn-deduplicate": "^6.0.0",
|
|
||||||
"zulip-js": "^2.0.8"
|
"zulip-js": "^2.0.8"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"pnpm": {
|
||||||
"/source-map": "https://codeload.github.com/benthemonkey/source-map/tar.gz/d95423f77edef6cbb9e21d2d6014c7de85ae220a"
|
"overrides": {
|
||||||
},
|
"source-map@^0.6": "npm:source-map-js@1.0.1"
|
||||||
"repository": {
|
}
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/zulip/zulip.git"
|
|
||||||
},
|
},
|
||||||
"nyc": {
|
"nyc": {
|
||||||
"exclude": [
|
"exclude": [
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -184,7 +184,6 @@ class zulip::app_frontend_base {
|
||||||
'/home/zulip/tornado',
|
'/home/zulip/tornado',
|
||||||
'/home/zulip/prod-static',
|
'/home/zulip/prod-static',
|
||||||
'/home/zulip/deployments',
|
'/home/zulip/deployments',
|
||||||
'/srv/zulip-npm-cache',
|
|
||||||
'/srv/zulip-emoji-cache',
|
'/srv/zulip-emoji-cache',
|
||||||
'/srv/zulip-uploaded-files-cache',
|
'/srv/zulip-uploaded-files-cache',
|
||||||
]:
|
]:
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# TODO: After switching from yarn to pnpm, we no longer create
|
||||||
|
# /srv/zulip-npm-cache or symlink node_modules, so this script can be
|
||||||
|
# replaced with shutil.rmtree("/srv/zulip-npm-cache").
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
|
@ -5,7 +5,7 @@ import sys
|
||||||
|
|
||||||
ZULIP_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
ZULIP_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
sys.path.append(ZULIP_PATH)
|
sys.path.append(ZULIP_PATH)
|
||||||
from scripts.lib import clean_emoji_cache, clean_node_cache, clean_venv_cache, clean_yarn_cache
|
from scripts.lib import clean_emoji_cache, clean_node_cache, clean_venv_cache
|
||||||
from scripts.lib.zulip_tools import parse_cache_script_args
|
from scripts.lib.zulip_tools import parse_cache_script_args
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ def main(args: argparse.Namespace) -> None:
|
||||||
os.chdir(ZULIP_PATH)
|
os.chdir(ZULIP_PATH)
|
||||||
clean_venv_cache.main(args)
|
clean_venv_cache.main(args)
|
||||||
clean_node_cache.main(args)
|
clean_node_cache.main(args)
|
||||||
clean_yarn_cache.main(args)
|
|
||||||
clean_emoji_cache.main(args)
|
clean_emoji_cache.main(args)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
ZULIP_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
||||||
sys.path.append(ZULIP_PATH)
|
|
||||||
|
|
||||||
from scripts.lib.zulip_tools import maybe_perform_purging, parse_cache_script_args
|
|
||||||
|
|
||||||
YARN_CACHE_PATH = os.path.expanduser("~/.cache/yarn/")
|
|
||||||
CURRENT_VERSION = "v6"
|
|
||||||
|
|
||||||
|
|
||||||
def remove_unused_versions_dir(args: argparse.Namespace) -> None:
|
|
||||||
"""Deletes cache data from obsolete Yarn versions.
|
|
||||||
|
|
||||||
Yarn does not provide an interface for removing obsolete data from
|
|
||||||
~/.cache/yarn for packages that you haven't installed in years; but one
|
|
||||||
can always remove the cache entirely.
|
|
||||||
"""
|
|
||||||
current_version_dir = os.path.join(YARN_CACHE_PATH, CURRENT_VERSION)
|
|
||||||
try:
|
|
||||||
dirs_to_purge = {
|
|
||||||
os.path.join(YARN_CACHE_PATH, directory)
|
|
||||||
for directory in os.listdir(YARN_CACHE_PATH)
|
|
||||||
if directory != CURRENT_VERSION
|
|
||||||
}
|
|
||||||
except FileNotFoundError:
|
|
||||||
return
|
|
||||||
|
|
||||||
no_headings = getattr(args, "no_headings", False)
|
|
||||||
maybe_perform_purging(
|
|
||||||
dirs_to_purge,
|
|
||||||
{current_version_dir},
|
|
||||||
"yarn cache",
|
|
||||||
args.dry_run,
|
|
||||||
args.verbose,
|
|
||||||
no_headings,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def main(args: argparse.Namespace) -> None:
|
|
||||||
remove_unused_versions_dir(args)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
args = parse_cache_script_args("This script cleans redundant Zulip yarn caches.")
|
|
||||||
main(args)
|
|
|
@ -18,7 +18,7 @@ esac
|
||||||
|
|
||||||
check_version() {
|
check_version() {
|
||||||
out="$(node --version)" && [ "$out" = "v$version" ] \
|
out="$(node --version)" && [ "$out" = "v$version" ] \
|
||||||
&& [ /usr/local/bin/yarn -ef /srv/zulip-node/lib/node_modules/corepack/dist/yarn.js ]
|
&& [ /usr/local/bin/pnpm -ef /srv/zulip-node/lib/node_modules/corepack/dist/pnpm.js ]
|
||||||
}
|
}
|
||||||
|
|
||||||
if ! check_version 2>/dev/null; then
|
if ! check_version 2>/dev/null; then
|
||||||
|
|
|
@ -1,96 +1,26 @@
|
||||||
import hashlib
|
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
|
||||||
import subprocess
|
|
||||||
from typing import Dict, List, Optional
|
|
||||||
|
|
||||||
from scripts.lib.zulip_tools import run
|
from scripts.lib.zulip_tools import run
|
||||||
|
|
||||||
ZULIP_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
||||||
ZULIP_SRV_PATH = "/srv"
|
|
||||||
|
|
||||||
NODE_MODULES_CACHE_PATH = os.path.join(ZULIP_SRV_PATH, "zulip-npm-cache")
|
|
||||||
YARN_BIN = "/usr/local/bin/yarn"
|
|
||||||
|
|
||||||
DEFAULT_PRODUCTION = False
|
DEFAULT_PRODUCTION = False
|
||||||
|
|
||||||
|
|
||||||
def get_yarn_args(production: bool) -> List[str]:
|
def setup_node_modules(production: bool = DEFAULT_PRODUCTION) -> None:
|
||||||
if production:
|
|
||||||
yarn_args = ["--prod"]
|
|
||||||
else:
|
|
||||||
yarn_args = []
|
|
||||||
return yarn_args
|
|
||||||
|
|
||||||
|
|
||||||
def generate_sha1sum_node_modules(
|
|
||||||
setup_dir: Optional[str] = None,
|
|
||||||
production: bool = DEFAULT_PRODUCTION,
|
|
||||||
) -> str:
|
|
||||||
if setup_dir is None:
|
|
||||||
setup_dir = os.path.realpath(os.getcwd())
|
|
||||||
PACKAGE_JSON_FILE_PATH = os.path.join(setup_dir, "package.json")
|
|
||||||
YARN_LOCK_FILE_PATH = os.path.join(setup_dir, "yarn.lock")
|
|
||||||
data: Dict[str, object] = {}
|
|
||||||
with open(PACKAGE_JSON_FILE_PATH) as f:
|
|
||||||
data[PACKAGE_JSON_FILE_PATH] = f.read().strip()
|
|
||||||
if os.path.exists(YARN_LOCK_FILE_PATH):
|
|
||||||
# For backwards compatibility, we can't assume yarn.lock exists
|
|
||||||
with open(YARN_LOCK_FILE_PATH) as f:
|
|
||||||
data[YARN_LOCK_FILE_PATH] = f.read().strip()
|
|
||||||
data["node-version"] = subprocess.check_output(["node", "--version"], text=True).strip()
|
|
||||||
data["yarn-args"] = get_yarn_args(production=production)
|
|
||||||
|
|
||||||
sha1sum = hashlib.sha1()
|
|
||||||
sha1sum.update(json.dumps(data, sort_keys=True).encode())
|
|
||||||
return sha1sum.hexdigest()
|
|
||||||
|
|
||||||
|
|
||||||
def setup_node_modules(
|
|
||||||
production: bool = DEFAULT_PRODUCTION,
|
|
||||||
prefer_offline: bool = False,
|
|
||||||
) -> None:
|
|
||||||
yarn_args = get_yarn_args(production=production)
|
|
||||||
if prefer_offline:
|
|
||||||
yarn_args.append("--prefer-offline")
|
|
||||||
sha1sum = generate_sha1sum_node_modules(production=production)
|
|
||||||
target_path = os.path.join(NODE_MODULES_CACHE_PATH, sha1sum)
|
|
||||||
cached_node_modules = os.path.join(target_path, "node_modules")
|
|
||||||
success_stamp = os.path.join(target_path, ".success-stamp")
|
|
||||||
# Check if a cached version already exists
|
|
||||||
if not os.path.exists(success_stamp):
|
|
||||||
do_yarn_install(target_path, yarn_args, success_stamp)
|
|
||||||
|
|
||||||
print(f"Using cached node modules from {cached_node_modules}")
|
|
||||||
if os.path.islink("node_modules"):
|
if os.path.islink("node_modules"):
|
||||||
os.remove("node_modules")
|
os.unlink("node_modules")
|
||||||
elif os.path.isdir("node_modules"):
|
|
||||||
shutil.rmtree("node_modules")
|
|
||||||
os.symlink(cached_node_modules, "node_modules")
|
|
||||||
|
|
||||||
|
try:
|
||||||
def do_yarn_install(
|
with open("node_modules/.pnpm/lock.yaml") as a, open("pnpm-lock.yaml") as b:
|
||||||
target_path: str,
|
if a.read() == b.read():
|
||||||
yarn_args: List[str],
|
return
|
||||||
success_stamp: str,
|
except FileNotFoundError:
|
||||||
) -> None:
|
|
||||||
os.makedirs(target_path, exist_ok=True)
|
|
||||||
shutil.copy("package.json", target_path)
|
|
||||||
shutil.copy("yarn.lock", target_path)
|
|
||||||
shutil.copy(".yarnrc", target_path)
|
|
||||||
cached_node_modules = os.path.join(target_path, "node_modules")
|
|
||||||
print("Cached version not found! Installing node modules.")
|
|
||||||
|
|
||||||
# Copy the existing node_modules to speed up install
|
|
||||||
if os.path.exists("node_modules") and not os.path.exists(cached_node_modules):
|
|
||||||
shutil.copytree("node_modules/", cached_node_modules, symlinks=True)
|
|
||||||
if os.path.isdir(os.path.join(cached_node_modules, ".cache")):
|
|
||||||
shutil.rmtree(os.path.join(cached_node_modules, ".cache"))
|
|
||||||
if os.environ.get("CUSTOM_CA_CERTIFICATES"):
|
|
||||||
run([YARN_BIN, "config", "set", "cafile", os.environ["CUSTOM_CA_CERTIFICATES"]])
|
|
||||||
run(
|
|
||||||
[YARN_BIN, "install", "--non-interactive", "--frozen-lockfile", *yarn_args], cwd=target_path
|
|
||||||
)
|
|
||||||
with open(success_stamp, "w"):
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
run(
|
||||||
|
[
|
||||||
|
"/usr/local/bin/pnpm",
|
||||||
|
"install",
|
||||||
|
"--frozen-lockfile",
|
||||||
|
*(["--prod"] if production else []),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
|
@ -9,7 +9,6 @@ import logging
|
||||||
import os
|
import os
|
||||||
import pwd
|
import pwd
|
||||||
import random
|
import random
|
||||||
import re
|
|
||||||
import shlex
|
import shlex
|
||||||
import shutil
|
import shutil
|
||||||
import signal
|
import signal
|
||||||
|
@ -347,6 +346,9 @@ def purge_unused_caches(
|
||||||
cache_type: str,
|
cache_type: str,
|
||||||
args: argparse.Namespace,
|
args: argparse.Namespace,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
if not os.path.exists(caches_dir):
|
||||||
|
return
|
||||||
|
|
||||||
all_caches = {os.path.join(caches_dir, cache) for cache in os.listdir(caches_dir)}
|
all_caches = {os.path.join(caches_dir, cache) for cache in os.listdir(caches_dir)}
|
||||||
caches_to_purge = get_caches_to_be_purged(caches_dir, caches_in_use, args.threshold_days)
|
caches_to_purge = get_caches_to_be_purged(caches_dir, caches_in_use, args.threshold_days)
|
||||||
caches_to_keep = all_caches - caches_to_purge
|
caches_to_keep = all_caches - caches_to_purge
|
||||||
|
@ -376,22 +378,8 @@ def generate_sha1sum_emoji(zulip_path: str) -> str:
|
||||||
|
|
||||||
# Take into account the version of `emoji-datasource-google` package
|
# Take into account the version of `emoji-datasource-google` package
|
||||||
# while generating success stamp.
|
# while generating success stamp.
|
||||||
PACKAGE_FILE_PATH = os.path.join(zulip_path, "package.json")
|
with open(os.path.join(zulip_path, "node_modules/emoji-datasource-google/package.json")) as fp:
|
||||||
with open(PACKAGE_FILE_PATH) as fp:
|
emoji_datasource_version = json.load(fp)["version"]
|
||||||
parsed_package_file = json.load(fp)
|
|
||||||
dependency_data = parsed_package_file["dependencies"]
|
|
||||||
|
|
||||||
if "emoji-datasource-google" in dependency_data:
|
|
||||||
with open(os.path.join(zulip_path, "yarn.lock")) as fp:
|
|
||||||
(emoji_datasource_version,) = re.findall(
|
|
||||||
r"^emoji-datasource-google@"
|
|
||||||
+ re.escape(dependency_data["emoji-datasource-google"])
|
|
||||||
+ r':\n version "(.*)"',
|
|
||||||
fp.read(),
|
|
||||||
re.M,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
emoji_datasource_version = "0"
|
|
||||||
sha.update(emoji_datasource_version.encode())
|
sha.update(emoji_datasource_version.encode())
|
||||||
|
|
||||||
return sha.hexdigest()
|
return sha.hexdigest()
|
||||||
|
|
|
@ -40,14 +40,14 @@ cp -a \
|
||||||
tools/ci/production-pgroonga \
|
tools/ci/production-pgroonga \
|
||||||
tools/ci/production-upgrade-pg \
|
tools/ci/production-upgrade-pg \
|
||||||
tools/ci/generate-failure-message \
|
tools/ci/generate-failure-message \
|
||||||
package.json yarn.lock \
|
package.json pnpm-lock.yaml \
|
||||||
/tmp/production-build
|
/tmp/production-build
|
||||||
|
|
||||||
# Check that webpack bundles use only ES2019 syntax.
|
# Check that webpack bundles use only ES2019 syntax.
|
||||||
# Use the yarn binary installed by tools/provision.
|
# Use the pnpm binary installed by tools/provision.
|
||||||
YARN="/usr/local/bin/yarn"
|
PNPM="/usr/local/bin/pnpm"
|
||||||
tar -C /tmp -xzf /tmp/production-build/zulip-server-test.tar.gz zulip-server-test/prod-static/serve/webpack-bundles
|
tar -C /tmp -xzf /tmp/production-build/zulip-server-test.tar.gz zulip-server-test/prod-static/serve/webpack-bundles
|
||||||
(
|
(
|
||||||
GLOBIGNORE=/tmp/zulip-server-test/prod-static/serve/webpack-bundles/katex-cli.js
|
GLOBIGNORE=/tmp/zulip-server-test/prod-static/serve/webpack-bundles/katex-cli.js
|
||||||
$YARN run es-check es2019 /tmp/zulip-server-test/prod-static/serve/webpack-bundles/*.js
|
"$PNPM" exec es-check es2019 /tmp/zulip-server-test/prod-static/serve/webpack-bundles/*.js
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,7 +14,7 @@ ZULIP_PATH = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__f
|
||||||
|
|
||||||
sys.path.append(ZULIP_PATH)
|
sys.path.append(ZULIP_PATH)
|
||||||
|
|
||||||
from scripts.lib.node_cache import NODE_MODULES_CACHE_PATH, setup_node_modules
|
from scripts.lib.node_cache import setup_node_modules
|
||||||
from scripts.lib.setup_venv import get_venv_dependencies
|
from scripts.lib.setup_venv import get_venv_dependencies
|
||||||
from scripts.lib.zulip_tools import (
|
from scripts.lib.zulip_tools import (
|
||||||
ENDC,
|
ENDC,
|
||||||
|
@ -346,7 +346,7 @@ def install_yum_deps(deps_to_install: List[str]) -> None:
|
||||||
|
|
||||||
|
|
||||||
def main(options: argparse.Namespace) -> NoReturn:
|
def main(options: argparse.Namespace) -> NoReturn:
|
||||||
# yarn and management commands expect to be run from the root of the
|
# pnpm and management commands expect to be run from the root of the
|
||||||
# project.
|
# project.
|
||||||
os.chdir(ZULIP_PATH)
|
os.chdir(ZULIP_PATH)
|
||||||
|
|
||||||
|
@ -400,22 +400,16 @@ def main(options: argparse.Namespace) -> NoReturn:
|
||||||
]
|
]
|
||||||
run_as_root([*proxy_env, "scripts/lib/install-node"], sudo_args=["-H"])
|
run_as_root([*proxy_env, "scripts/lib/install-node"], sudo_args=["-H"])
|
||||||
|
|
||||||
if not os.access(NODE_MODULES_CACHE_PATH, os.W_OK):
|
|
||||||
run_as_root(["mkdir", "-p", NODE_MODULES_CACHE_PATH])
|
|
||||||
run_as_root(["chown", f"{os.getuid()}:{os.getgid()}", NODE_MODULES_CACHE_PATH])
|
|
||||||
|
|
||||||
# This is a wrapper around `yarn`, which we run last since
|
|
||||||
# it can often fail due to network issues beyond our control.
|
|
||||||
try:
|
try:
|
||||||
setup_node_modules(prefer_offline=True)
|
setup_node_modules()
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
print(WARNING + "`yarn install` failed; retrying..." + ENDC)
|
print(WARNING + "`pnpm install` failed; retrying..." + ENDC)
|
||||||
try:
|
try:
|
||||||
setup_node_modules()
|
setup_node_modules()
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
print(
|
print(
|
||||||
FAIL
|
FAIL
|
||||||
+ "`yarn install` is failing; check your network connection (and proxy settings)."
|
+ "`pnpm install` is failing; check your network connection (and proxy settings)."
|
||||||
+ ENDC
|
+ ENDC
|
||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
11
tools/lint
11
tools/lint
|
@ -72,14 +72,14 @@ def run() -> None:
|
||||||
|
|
||||||
linter_config.external_linter(
|
linter_config.external_linter(
|
||||||
"css",
|
"css",
|
||||||
["node", "node_modules/.bin/stylelint"],
|
["node_modules/.bin/stylelint"],
|
||||||
["css"],
|
["css"],
|
||||||
fix_arg="--fix",
|
fix_arg="--fix",
|
||||||
description="Standard CSS style and formatting linter (config: stylelint.config.js)",
|
description="Standard CSS style and formatting linter (config: stylelint.config.js)",
|
||||||
)
|
)
|
||||||
linter_config.external_linter(
|
linter_config.external_linter(
|
||||||
"eslint",
|
"eslint",
|
||||||
["node", "node_modules/.bin/eslint", "--max-warnings=0", "--cache", "--ext", ".js,.ts"],
|
["node_modules/.bin/eslint", "--max-warnings=0", "--cache", "--ext", ".js,.ts"],
|
||||||
["js", "ts"],
|
["js", "ts"],
|
||||||
fix_arg="--fix",
|
fix_arg="--fix",
|
||||||
description="Standard JavaScript style and formatting linter (config: .eslintrc).",
|
description="Standard JavaScript style and formatting linter (config: .eslintrc).",
|
||||||
|
@ -157,13 +157,6 @@ def run() -> None:
|
||||||
pass_targets=False,
|
pass_targets=False,
|
||||||
description="TypeScript compiler (config: tsconfig.json)",
|
description="TypeScript compiler (config: tsconfig.json)",
|
||||||
)
|
)
|
||||||
linter_config.external_linter(
|
|
||||||
"yarn-deduplicate",
|
|
||||||
["tools/run-yarn-deduplicate"],
|
|
||||||
["lock"],
|
|
||||||
pass_targets=False,
|
|
||||||
description="Shares duplicate packages in yarn.lock",
|
|
||||||
)
|
|
||||||
linter_config.external_linter(
|
linter_config.external_linter(
|
||||||
"gitlint",
|
"gitlint",
|
||||||
["tools/commit-message-lint"],
|
["tools/commit-message-lint"],
|
||||||
|
|
|
@ -20,7 +20,7 @@ if [ "$#" -eq 0 ]; then
|
||||||
':!postgresql.conf.template.erb' \
|
':!postgresql.conf.template.erb' \
|
||||||
':!tools/setup/emoji/emoji_map.json' \
|
':!tools/setup/emoji/emoji_map.json' \
|
||||||
':!tools/setup/emoji/emoji_names.py' \
|
':!tools/setup/emoji/emoji_names.py' \
|
||||||
':!yarn.lock' \
|
':!pnpm-lock.yaml' \
|
||||||
':!zerver/management/data/unified_reactions.json'
|
':!zerver/management/data/unified_reactions.json'
|
||||||
)"
|
)"
|
||||||
mapfile -t FILES_TO_BE_CHECKED <<<"$FILES_TO_BE_CHECKED"
|
mapfile -t FILES_TO_BE_CHECKED <<<"$FILES_TO_BE_CHECKED"
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
set -eu
|
|
||||||
if ! "$(dirname "$0")/../node_modules/.bin/yarn-deduplicate" --fail --list; then
|
|
||||||
echo
|
|
||||||
echo "Duplicates could be shared in yarn.lock. Run:"
|
|
||||||
echo "node_modules/.bin/yarn-deduplicate; yarn"
|
|
||||||
false
|
|
||||||
fi
|
|
|
@ -42,7 +42,7 @@ if [ "$#" -gt 0 ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ZULIP_PATH="$(readlink -f "$(dirname "$0")"/../..)"
|
ZULIP_PATH="$(readlink -f "$(dirname "$0")"/../..)"
|
||||||
YARN="/usr/local/bin/yarn"
|
PNPM="/usr/local/bin/pnpm"
|
||||||
|
|
||||||
if [ -n "$CHECK_UNOPTIMIZED" ]; then
|
if [ -n "$CHECK_UNOPTIMIZED" ]; then
|
||||||
if [ "$(node_modules/.bin/svgo -f static/images/integrations/logos | grep -o '\.[0-9]% = ' | wc -l)" -ge 1 ]; then
|
if [ "$(node_modules/.bin/svgo -f static/images/integrations/logos | grep -o '\.[0-9]% = ' | wc -l)" -ge 1 ]; then
|
||||||
|
@ -53,6 +53,6 @@ if [ -n "$CHECK_UNOPTIMIZED" ]; then
|
||||||
echo "SUCCESS: SVG files in static/images/integrations/logos are all optimized!"
|
echo "SUCCESS: SVG files in static/images/integrations/logos are all optimized!"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
$YARN run svgo -q -f static/images/integrations/logos
|
"$PNPM" exec svgo -q -f static/images/integrations/logos
|
||||||
"$ZULIP_PATH"/tools/setup/generate_integration_bots_avatars.py
|
"$ZULIP_PATH"/tools/setup/generate_integration_bots_avatars.py
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -64,8 +64,6 @@ options = parser.parse_args()
|
||||||
|
|
||||||
def run_single_test(test_file: str, test_number: int, total_tests: int) -> int:
|
def run_single_test(test_file: str, test_number: int, total_tests: int) -> int:
|
||||||
cmd = [
|
cmd = [
|
||||||
"node",
|
|
||||||
"--unhandled-rejections=strict",
|
|
||||||
os.path.join(ZULIP_PATH, "node_modules/.bin/ts-node"),
|
os.path.join(ZULIP_PATH, "node_modules/.bin/ts-node"),
|
||||||
"--script-mode",
|
"--script-mode",
|
||||||
"--transpile-only",
|
"--transpile-only",
|
||||||
|
|
|
@ -17,11 +17,10 @@ from version import ZULIP_VERSION
|
||||||
def build_for_prod_or_puppeteer(quiet: bool) -> NoReturn:
|
def build_for_prod_or_puppeteer(quiet: bool) -> NoReturn:
|
||||||
"""Builds for production, writing the output to disk"""
|
"""Builds for production, writing the output to disk"""
|
||||||
|
|
||||||
webpack_args = ["node"]
|
|
||||||
with open("/proc/meminfo") as meminfo:
|
with open("/proc/meminfo") as meminfo:
|
||||||
if int(next(meminfo).split()[1]) < 3 * 1024 * 1024:
|
if int(next(meminfo).split()[1]) < 3 * 1024 * 1024:
|
||||||
webpack_args += ["--max-old-space-size=1536"]
|
os.environ["NODE_OPTIONS"] = "--max-old-space-size=1536"
|
||||||
webpack_args += [
|
webpack_args = [
|
||||||
"../node_modules/.bin/webpack-cli",
|
"../node_modules/.bin/webpack-cli",
|
||||||
"--mode=production",
|
"--mode=production",
|
||||||
f"--env=ZULIP_VERSION={ZULIP_VERSION}",
|
f"--env=ZULIP_VERSION={ZULIP_VERSION}",
|
||||||
|
@ -37,7 +36,7 @@ def build_for_dev_server(host: str, port: str, minify: bool, disable_host_check:
|
||||||
# This is our most dynamic configuration, which we use for our
|
# This is our most dynamic configuration, which we use for our
|
||||||
# dev server. The key piece here is that we identify changes to
|
# dev server. The key piece here is that we identify changes to
|
||||||
# files as devs make edits and serve new assets on the fly.
|
# files as devs make edits and serve new assets on the fly.
|
||||||
webpack_args = ["node", "../node_modules/.bin/webpack-cli", "serve"]
|
webpack_args = ["../node_modules/.bin/webpack-cli", "serve"]
|
||||||
webpack_args += [
|
webpack_args += [
|
||||||
# webpack-cli has a bug where it ignores --watch-poll with
|
# webpack-cli has a bug where it ignores --watch-poll with
|
||||||
# multi-config, and we don't need the katex-cli part anyway.
|
# multi-config, and we don't need the katex-cli part anyway.
|
||||||
|
|
|
@ -48,4 +48,4 @@ API_FEATURE_LEVEL = 169
|
||||||
# historical commits sharing the same major version, in which case a
|
# historical commits sharing the same major version, in which case a
|
||||||
# minor version bump suffices.
|
# minor version bump suffices.
|
||||||
|
|
||||||
PROVISION_VERSION = (226, 0)
|
PROVISION_VERSION = (227, 0)
|
||||||
|
|
|
@ -28,9 +28,6 @@ export default (
|
||||||
config: [__filename],
|
config: [__filename],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
snapshot: {
|
|
||||||
immutablePaths: ["/srv/zulip-npm-cache"],
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const frontendConfig: webpack.Configuration = {
|
const frontendConfig: webpack.Configuration = {
|
||||||
|
|
Loading…
Reference in New Issue