diff --git a/.github/workflows/node.yaml b/.github/workflows/node.yaml index 15b057fe..b00ce002 100644 --- a/.github/workflows/node.yaml +++ b/.github/workflows/node.yaml @@ -26,6 +26,11 @@ jobs: poetry-version: - '1.1.13' runs-on: ubuntu-22.04 + services: + verdaccio: + image: verdaccio/verdaccio + ports: + - 4873:4873 steps: - uses: actions/checkout@v3 - name: Configure git @@ -40,6 +45,8 @@ jobs: poetry-version: ${{ matrix.poetry-version }} - name: Install OS dependencies run: sudo apt-get update && sudo apt-get install -y flatpak-builder + - name: Setup the local npm register + run: tools/setup-local-registry.sh - name: Install Flatpak dependencies run: | flatpak --user remote-add flathub https://flathub.org/repo/flathub.flatpakrepo diff --git a/node/README.md b/node/README.md index 06c2cca4..8ad3ae72 100644 --- a/node/README.md +++ b/node/README.md @@ -321,6 +321,19 @@ $ poetry run pytest -n auto Note that these tests can take up quite a bit of space in /tmp, so if you hit `No space left on device` errors, try expanding `/tmp` or changing `$TMPDIR`. +### Local Registry + +Some of the tests require a local npm registry to work. For this purpose, you can use +[Verdaccio](https://verdaccio.org/), preferably via Docker / podman: + +```bash +$ docker run --rm -it -p 4873:4873 verdaccio/verdaccio +``` + +Then run `tools/setup-local-registry.sh` to set up this registry with a pre-published +package. (Note that running it twice will result in an error, since it tries to publish +the same package twice.) + ### Utility Scripts A few utility scripts are included in the `tools` directory: @@ -333,6 +346,8 @@ A few utility scripts are included in the `tools` directory: - `lockfile-utils.sh peek-cache PACKAGE-MANAGER PACKAGE` will install the dependencies from the corresponding lockfile and then extract the resulting package cache (npm) or mirror directory (yarn), for closer examination. +- `setup-local-registry.sh` will set up a local npm registry as [described + above](#local-registry). - `b64-to-hex.sh` will convert a base64 hash value from npm into hex, e.g.: ``` $ echo x+sXyT4RLLEIb6bY5R+wZnt5pfk= | tools/b64-to-hex.sh diff --git a/node/tests/conftest.py b/node/tests/conftest.py index dbec767d..fa171a0c 100644 --- a/node/tests/conftest.py +++ b/node/tests/conftest.py @@ -170,6 +170,14 @@ class ProviderPaths: def package_json(self) -> Path: return self.root / 'package.json' + @property + def npmrc(self) -> Path: + return self.root / '.npmrc' + + @property + def yarnrc(self) -> Path: + return self.root / '.yarnrc' + @property def lockfile_source(self) -> Path: if self.type == ProviderFactoryType.NPM: @@ -192,6 +200,11 @@ def lockfile_dest(self) -> str: def add_to_manifest(self, gen: ManifestGenerator) -> None: gen.add_local_file_source(self.package_json) gen.add_local_file_source(self.lockfile_source, Path(self.lockfile_dest)) + + for rc in self.npmrc, self.yarnrc: + if rc.exists(): + gen.add_local_file_source(rc) + if self.type == ProviderFactoryType.YARN: gen.add_data_source( f'yarn-offline-mirror "./flatpak-node/yarn-mirror"', Path('.yarnrc') @@ -266,7 +279,12 @@ async def generate_modules( ) special = SpecialSourceProvider(gen, self.special) - with factory.create_module_provider(gen, special) as module: + config_provider = factory.create_config_provider() + lockfile_configs = { + paths.lockfile_source: config_provider.load_config(paths.lockfile_source), + } + + with factory.create_module_provider(gen, special, lockfile_configs) as module: for package in factory.create_lockfile_provider().process_lockfile( paths.lockfile_source ): diff --git a/node/tests/data/packages/custom-registry/.npmrc b/node/tests/data/packages/custom-registry/.npmrc new file mode 100644 index 00000000..be33d435 --- /dev/null +++ b/node/tests/data/packages/custom-registry/.npmrc @@ -0,0 +1 @@ +"@custom:registry" = "http://localhost:4873" diff --git a/node/tests/data/packages/custom-registry/package-lock.v1.json b/node/tests/data/packages/custom-registry/package-lock.v1.json new file mode 100644 index 00000000..a1e873b2 --- /dev/null +++ b/node/tests/data/packages/custom-registry/package-lock.v1.json @@ -0,0 +1,13 @@ +{ + "name": "@flatpak-node-generator-tests/custom-registry", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@custom/registry-package": { + "version": "1.0.0", + "resolved": "http://localhost:4873/@custom%2fregistry-package/-/registry-package-1.0.0.tgz", + "integrity": "sha512-O6a3tZ0qHF/7tqJRu7DeUAwkMPyVcX3PlNQU+nAxGptTjetipiGQ3jq7Jo7mJNAgMzyv6Psy5riVqMuNjvup5Q==" + } + } +} diff --git a/node/tests/data/packages/custom-registry/package-lock.v2.json b/node/tests/data/packages/custom-registry/package-lock.v2.json new file mode 100644 index 00000000..40c6da89 --- /dev/null +++ b/node/tests/data/packages/custom-registry/package-lock.v2.json @@ -0,0 +1,27 @@ +{ + "name": "@flatpak-node-generator-tests/custom-registry", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "@flatpak-node-generator-tests/custom-registry", + "version": "1.0.0", + "dependencies": { + "@custom/registry-package": "*" + } + }, + "node_modules/@custom/registry-package": { + "version": "1.0.0", + "resolved": "http://localhost:4873/@custom%2fregistry-package/-/registry-package-1.0.0.tgz", + "integrity": "sha512-O6a3tZ0qHF/7tqJRu7DeUAwkMPyVcX3PlNQU+nAxGptTjetipiGQ3jq7Jo7mJNAgMzyv6Psy5riVqMuNjvup5Q==" + } + }, + "dependencies": { + "@custom/registry-package": { + "version": "1.0.0", + "resolved": "http://localhost:4873/@custom%2fregistry-package/-/registry-package-1.0.0.tgz", + "integrity": "sha512-O6a3tZ0qHF/7tqJRu7DeUAwkMPyVcX3PlNQU+nAxGptTjetipiGQ3jq7Jo7mJNAgMzyv6Psy5riVqMuNjvup5Q==" + } + } +} diff --git a/node/tests/data/packages/custom-registry/package.json b/node/tests/data/packages/custom-registry/package.json new file mode 100644 index 00000000..13b97e30 --- /dev/null +++ b/node/tests/data/packages/custom-registry/package.json @@ -0,0 +1,7 @@ +{ + "name": "@flatpak-node-generator-tests/custom-registry", + "version": "1.0.0", + "dependencies": { + "@custom/registry-package": "*" + } +} diff --git a/node/tests/data/packages/custom-registry/registry-package/index.js b/node/tests/data/packages/custom-registry/registry-package/index.js new file mode 100644 index 00000000..12d6ec24 --- /dev/null +++ b/node/tests/data/packages/custom-registry/registry-package/index.js @@ -0,0 +1,7 @@ +const fs = require('fs') + +module.exports = { + sayHello: () => { + fs.writeFileSync('hello.txt', 'Hello!') + }, +} diff --git a/node/tests/data/packages/custom-registry/registry-package/package.json b/node/tests/data/packages/custom-registry/registry-package/package.json new file mode 100644 index 00000000..961d3623 --- /dev/null +++ b/node/tests/data/packages/custom-registry/registry-package/package.json @@ -0,0 +1,4 @@ +{ + "name": "@custom/registry-package", + "version": "1.0.0" +} diff --git a/node/tests/data/packages/custom-registry/yarn.lock b/node/tests/data/packages/custom-registry/yarn.lock new file mode 100644 index 00000000..e537ecd5 --- /dev/null +++ b/node/tests/data/packages/custom-registry/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@custom/registry-package@*": + version "1.0.0" + resolved "http://localhost:4873/@custom%2fregistry-package/-/registry-package-1.0.0.tgz#b632e33e611a829ea94d0a03c53f7c1ee99b219a" + integrity sha512-O6a3tZ0qHF/7tqJRu7DeUAwkMPyVcX3PlNQU+nAxGptTjetipiGQ3jq7Jo7mJNAgMzyv6Psy5riVqMuNjvup5Q== diff --git a/node/tests/test_providers.py b/node/tests/test_providers.py index f0c9efb4..dd37b571 100644 --- a/node/tests/test_providers.py +++ b/node/tests/test_providers.py @@ -37,6 +37,29 @@ def parse_config(self, path: Path) -> Dict[str, Any]: } +async def test_custom_registry( + flatpak_builder: FlatpakBuilder, + provider_factory_spec: ProviderFactorySpec, + node_version: int, +) -> None: + with ManifestGenerator() as gen: + await provider_factory_spec.generate_modules( + 'custom-registry', gen, node_version + ) + + flatpak_builder.build( + sources=gen.ordered_sources(), + commands=[ + provider_factory_spec.install_command, + """node -e 'require("@custom/registry-package").sayHello()'""", + ], + use_node=node_version, + ) + + hello_txt = flatpak_builder.module_dir / 'hello.txt' + assert hello_txt.read_text() == 'Hello!' + + async def test_minimal_git( flatpak_builder: FlatpakBuilder, provider_factory_spec: ProviderFactorySpec, diff --git a/node/tools/lockfile-utils.sh b/node/tools/lockfile-utils.sh index 7e7a84e6..253a2c0b 100755 --- a/node/tools/lockfile-utils.sh +++ b/node/tools/lockfile-utils.sh @@ -1,6 +1,7 @@ #!/usr/bin/env bash set -e +shopt -s nullglob die() { echo "$@" >&2 @@ -54,7 +55,7 @@ package_path="$(dirname "$0")/../tests/data/packages/$package_arg" tmpdir=$(mktemp -d) trap 'rm -rf -- "$tmpdir"' EXIT -cp "$package_path/package.json" "$tmpdir" +cp "$package_path/package.json" "$package_path/".*rc "$tmpdir" # Special-case handling for our test of a local package. [[ -d "$package_path/subdir" ]] && cp -r "$package_path/subdir" "$tmpdir" diff --git a/node/tools/setup-local-registry.sh b/node/tools/setup-local-registry.sh new file mode 100755 index 00000000..f6857b0c --- /dev/null +++ b/node/tools/setup-local-registry.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -e + +REGISTRY=localhost:4873 + +curl -X PUT http://$REGISTRY/-/user/org.couchdb.user:test \ + -H 'Content-Type: application/json' \ + -d '{"name": "test", "password": "test"}' +echo + +pkg_path="$(dirname "$0")/../tests/data/packages/custom-registry/registry-package" + +tmpdir=$(mktemp -d) +trap 'rm -rf -- "$tmpdir"' EXIT + +cp -r "$pkg_path/"* "$tmpdir" + +cat > "$tmpdir/.npmrc" <