Skip to content

Load the mixed web example's IP Intelligence engine by package, and check what the location examples print - #95

Merged
jwrosewell merged 3 commits into
rcfrom
fix/publish-mixed-web-engine
Nov 14, 2026
Merged

jwrosewell merged 3 commits into
rcfrom
fix/publish-mixed-web-engine

Conversation

@jwrosewell

@jwrosewell jwrosewell commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

Problem

The Publish run for release 4.5.103, run 43412143722 on main at 4d5832f (the merge of #83), failed, so nothing was published and npm still has 4.5.102. In each of the eight "Publish / Test" jobs (Ubuntu, Ubuntu ARM, Windows and macOS, on Node.js 22 and 24) exactly one test failed, "Examples without settings › the mixed web page marks the Enterprise properties" in examplesWithoutSettings.test.js.

thrown: "There is no directory at '/home/runner/work/51degrees-node/51degrees-node/51degrees-node/ip-intelligence/fiftyone.ipintelligence.onpremise/build'. This is expected to contain the native modules for the IP intelligence engine. For example, /home/runner/work/51degrees-node/51degrees-node/51degrees-node/ip-intelligence/fiftyone.ipintelligence.onpremise/build/FiftyOneIpIntelligenceIpiV41-linux-x64-24.node"

The same test passed in every job of the release build, run 43368219214, on the same code (8f14aa0).

The same Publish logs show location/examples/examples.test.js printing ReferenceError: resourceKey is not defined three times, once from each example it runs, while every test in it passed.

Cause

The mixed web example

  • The Publish Test jobs run common-ci's nightly-publish.test.ps1, which clones this repository, runs ci/setup-environment.ps1 (npm install) and then ci/install-package.ps1. That script replaces each workspace link in node_modules with the files of the packed tarball, which carry the native modules. Nothing builds a native module in a source folder in those jobs, which is the point of them, because they test what was packed.
  • mixed/gettingstarted-web/51d.json named the IP Intelligence engine ../../../../ipIntelligenceOnPremise, a path to the source file. The test's webOptions turns a name starting with . into a path from the example's folder, so buildFromConfiguration loaded ip-intelligence/fiftyone.ipintelligence.onpremise/ipIntelligenceOnPremise.js from the source folder. That file looks for its native module in its own build folder (lines 197 to 202), which a Build and Test job makes and a Publish Test job does not.
  • The other tests in the file pass because they reach the engine through its package name. The plain web example builds its pipeline with require51('fiftyone.ipintelligence.onpremise') and does not use the element name in its 51d.json, the console examples use the package, and the Device Detection element of the same mixed 51d.json already names fiftyone.devicedetection.onpremise/deviceDetectionOnPremise. So the IP Intelligence element of the mixed web example was the only element in a test that named an engine with a native module by a source path. The cloud examples' source paths still load in a Publish job because their engines have no native module.
  • AGENTS.md, under "Everything hoists to the root", already says an elementName in 51d.json is a package path.

The location examples

  • gettingStarted.js (lines 101 to 110), combiningServices.js (lines 52 to 61) and configureFromFile.js (lines 69 to 78) read a global variable called resourceKey inside a try, and print a ReferenceError with console.log(e). Only the globals setting of the jest configuration in location/package.json defined that variable. The location project in the root package.json does not, and a person running an example never has it, so every run printed the error and its stack before the example went on to read _51DEGREES_RESOURCE_KEY.
  • examples.test.js read each example, ran it with eval (line 51) and ended each test after one second with setTimeout(done, 1000) (lines 65, 71 and 77). It checked nothing the examples printed, and the examples do not wait for their cloud call, so each test passed whatever the example did.

So the examples and the test were both wrong.

What changed

  1. mixed/gettingstarted-web/51d.json names the engine fiftyone.ipintelligence.onpremise/ipIntelligenceOnPremise. In a clone, npm workspaces link that name to the source package, where the build step puts the native module. In a Publish job it is the installed package, and in a project that copies the example it is the npm package. The failing test is not changed and still runs. The mixed example's own gettingStarted.test.js only turns names starting with . into paths, so it takes the package name as it is.
  2. The location examples take the key from the code, where the comment tells a person to replace !!YOUR_RESOURCE_KEY!!, or from _51DEGREES_RESOURCE_KEY, and still read RESOURCE_KEY as the deprecated name with its warning, as ci/tests/deprecatedVariableNames.test.js checks. They load fiftyone.geolocation by its package name, and configureFromFile.js reads 51d.json from its own folder with path.join. webIntegration.js loads the package the same way. process.env.directory, which only the old test set, is no longer read.
  3. location/examples/examples.test.js runs each example in its own process from its own folder, as examplesWithoutSettings.test.js does, and fails unless the example exits with status 0, writes nothing to standard error and prints exactly the expected lines. With _51DEGREES_RESOURCE_KEY set it expects the country, and for combiningServices.js the mobile answer as well. Without it, it expects the message that says where to create a key. Any other line, such as a caught error, fails the test. The deprecated RESOURCE_KEY is taken out of the example's environment, so the name the test reads decides what it expects. Each example has 60 seconds and each test 120. Each example took under a second on Ubuntu (460 to 620 ms in run 43458115396 below), and every job passed within the limit.
  4. The unused resourceKey global is removed from the jest configuration in location/package.json and location/remote_package.json, and from the lint settings in location/.eslintrc.

Package files

  • The first commit changes only mixed/gettingstarted-web/51d.json. The files list of fiftyone.ipintelligence.onpremise (build, *.js, types) leaves out examples, as npm pack --dry-run in that folder shows, so the first commit changes no file in any npm package.
  • The second and third commits do change files that go into the fiftyone.geolocation package. location/package.json has no files list, and npm pack --dry-run in location includes .eslintrc and examples/ with the four examples, examples.test.js and 51d.json. They also change the jest field of the package.json in that package, which ci/build-package.ps1 takes from remote_package.json. They change no library file (index.js, geoLocationCloud.js, geoLocationPipelineBuilder.js), but the fiftyone.geolocation tarball is different. The first commit stands alone, so it can go without the other two.
  • The two commits on rc that are not on main (Say in AGENTS.md that a test failing on timing is fixed #93 and Point AGENTS.md at the one list of environment variable names #89) change only the root AGENTS.md and README.md, which no package carries.
  • The package artifacts of the red and green Publish runs below were compared file by file. Both hold the same 16 tarballs at 4.5.103 with the same 424 files. The files whose contents differ are the 7 this pull request changes in fiftyone.geolocation (.eslintrc, package.json and the five files under examples/), and the 8 macOS and Windows native modules. Those 8 native modules also differ between the failed Publish run 43412143722 and the red run 43434654686, which were both built from 4d5832f, so they change on every build and not because of this pull request. The Linux native modules and every other file are identical. So with this pull request, Publish releases what it would have released for Release candidate #83, apart from the fiftyone.geolocation files above.

How it was verified

Each run was started from a temporary branch, deleted afterwards. The Publish runs are this repository's Publish workflow with dryrun true. On a branch other than main the Package job skips npm publish, and as a dry run it pushes no tag and creates no release.

Run What Commit Result
43434654686 Publish dry run of main as it is 4d5832f All eight Test jobs failed the same one test, "Examples without settings › the mixed web page marks the Enterprise properties", with the error above. Each reports 1 failed, 4 skipped, 131 passed, 136 total. Package was skipped.
43458127308 Publish dry run of the head of this pull request 0468ed4 All eight Test jobs passed, each reporting 4 skipped, 132 passed, 136 total, with examplesWithoutSettings.test.js and location/examples/examples.test.js passing. The Package job ran as a dry run for the same 16 packages at 4.5.103 and logged "Not on the main branch, skipping publishing" and "Dry run - not pushing tag '4.5.103'".
43458115953 common-ci's nightly-pull-request.yml for this pull request into rc, with dryrun true, full-matrix true and fail-fast false 0468ed4 All eight Build and Test jobs passed, macOS on Node.js 22 and 24 included. Every job's PullRequestSha line reads 0468ed4. Each reports 2 skipped and 1355 passed for the unit tests, and 4 skipped and 132 passed for the integration tests.
43458115396 The new examples.test.js on Ubuntu with Node.js 24 and the test resource key, first with the three examples as they are on rc, then as this pull request changes them 0468ed4 with the temporary workflow on top (5952959) Before, 3 failed, each showing the ReferenceError: resourceKey is not defined line and its stack that the example printed. After, 3 passed.

Earlier runs on the first two commits (279ccb4) are superseded. The Publish dry run 43434662397 passed all eight Test jobs. The full build 43435057298 failed lint in all eight jobs (n/no-path-concat in configureFromFile.js and describe not defined in examples.test.js), which the third commit fixes. The location check 43435056863 gave the same before and after results.

Merge order

This draft and #87 both change four location examples, combiningServices.js, configureFromFile.js, gettingStarted.js and webIntegration.js, and the two that conflict are combiningServices.js and gettingStarted.js. Also, location/examples/examples.test.js line 44 here expects the old address, /^You need to create a resource key at https:\/\/configure\.51degrees\.com/, which #87 changes to https://51degrees.com/configure. That check runs only without a resource key, which CI always has, so CI cannot catch it. This draft merges first, and #87 then takes rc again, resolves the two examples and changes that line to the new address.

What remains

  • Other 51d.json files still name an engine by a source path, being the cloud examples and Device Detection's on-premise gettingstarted-web. They load in a Publish job because cloud engines have no native module and ci/install-package.ps1 rewrites two of them, but the others run the source rather than the packed package, and device-detection/run_examples.md and ip-intelligence/run_examples.md tell a person to change them by hand. Naming each engine by its package would remove both the rewrite and that step.
  • device-detection/fiftyone.devicedetection/examples/gettingstarted.test.js and device-detection/fiftyone.devicedetection.onpremise/examples/onpremise/performance-console/performance.test.js use the same eval and setTimeout(done, ...) pattern, so they pass whatever the example does.
  • The tests of the three mixed on-premise examples (mixed/gettingstarted-api, mixed/gettingstarted-console and mixed/gettingstarted-web) skip themselves when they find no .hash file in the IP Intelligence tests folder or cxx/data/ip-intelligence (tests/testHelper.js lines 32 to 35), and ci/fetch-assets.ps1 links the .hash files only into the Device Detection folders, so CI skips them. Only examplesWithoutSettings.test.js runs the mixed examples in CI.

The mixed web example's 51d.json named the IP Intelligence engine by a path
into the source folder next to the examples, ../../../../ipIntelligenceOnPremise.
The Publish workflow's Test jobs install the packed packages and do not build
the native modules in the source folder, so the engine loaded from that path
found no build folder and "Examples without settings, the mixed web page
marks the Enterprise properties" failed in every Test job.

The Device Detection element in the same file already uses its package name.
Naming the IP Intelligence engine the same way loads the installed package in
the Publish jobs, the workspace package in a clone, and the npm package where
the example is copied into a project.
The location examples read a global variable called resourceKey, which only a
jest globals setting in location/package.json ever defined. The repository's
jest projects do not set it, and a person running an example never has it, so
every run printed a ReferenceError and its stack before going on to read the
environment variable. examples.test.js evaluated each example and passed after
one second whatever the example did, so the error never failed a test.

The examples now read the key from the code or from the environment, and load
fiftyone.geolocation by its package name instead of by a path set through
process.env.directory, which only the old test set. The test runs each example
in its own process from its own folder and fails unless the example exits
with status 0, writes nothing to standard error and prints exactly the lines
expected, with or without a resource key. The unused jest global is removed
from both location manifests.
configureFromFile.js builds the path of 51d.json with path.join, as the lint
rule n/no-path-concat asks now that the path starts at __dirname. The test
no longer wraps its tests in describe, which the location lint settings do
not declare. The resourceKey global is removed from location/.eslintrc, as
nothing reads that variable now.
@jwrosewell
jwrosewell marked this pull request as ready for review November 14, 2026 00:47
@jwrosewell
jwrosewell merged commit ce8d917 into rc Nov 14, 2026
23 checks passed
@jwrosewell
jwrosewell deleted the fix/publish-mixed-web-engine branch November 14, 2026 00:47
jwrosewell added a commit that referenced this pull request Nov 14, 2026
rc's #95 changed the location examples' key handling. combiningServices.js
and gettingStarted.js take rc's code with the new address, and
examples.test.js expects the new address in the message for a missing key.
jwrosewell added a commit that referenced this pull request Nov 14, 2026
Eleven of the examples' `51d.json` files name an engine by a path into this repository's source, such as `"../../../deviceDetectionCloud"` in [`device-detection/fiftyone.devicedetection.cloud/examples/cloud/gettingstarted-console/51d.json` at fe81e01](https://github.com/51Degrees/51degrees-node/blob/fe81e01866b5aae0e2c6ec11a25a4f0a5d1ccd31/device-detection/fiftyone.devicedetection.cloud/examples/cloud/gettingstarted-console/51d.json). Such a file only works beside the source. [`ci/install-package.ps1` lines 43 to 55](https://github.com/51Degrees/51degrees-node/blob/fe81e01866b5aae0e2c6ec11a25a4f0a5d1ccd31/ci/install-package.ps1#L43-L55) rewrites two of them so the Publish tests run them against the packed packages, and [`device-detection/run_examples.md` lines 72 to 92](https://github.com/51Degrees/51degrees-node/blob/fe81e01866b5aae0e2c6ec11a25a4f0a5d1ccd31/device-detection/run_examples.md#L72-L92) and [`ip-intelligence/run_examples.md` lines 61 to 81](https://github.com/51Degrees/51degrees-node/blob/fe81e01866b5aae0e2c6ec11a25a4f0a5d1ccd31/ip-intelligence/run_examples.md#L61-L81) tell a person running an example against the published packages to edit the rest by hand. This is gap DX-node-20, left under "What remains" in [#95](#95), which named the mixed web example's engine by package.
jwrosewell added a commit that referenced this pull request Nov 14, 2026
… name what needs the Enterprise files (#111)

The IP Intelligence mixed API example, which runs a local copy of the cloud service's API on both on-premise engines, does not run from a fresh clone as the other examples do (gap DX-node-29, left under "Not changed" in [#32](#32) and "What remains" in [#95](#95)). At [7539a0b](https://github.com/51Degrees/51degrees-node/tree/7539a0be284aec3e0aae12cf50cf727ead68fb4c):
@jwrosewell jwrosewell mentioned this pull request Nov 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant