Skip to content

Commit a8077a0

Browse files
committed
feat: use client registration token for ndt7 tests
Update ndt7-js to 0.1.3 which supports the `clientRegistrationToken` option. Before running ndt7 tests, fetch a short-lived JWT token from the speed-backend service which enables priority access to the Locate API for registered integrations. This is the first step toward using the client registration system for M-Lab's speed test website along with the new backend that we have written for this purpose: https://github.com/m-lab/speed-proxy. We implement an open failure model where failure to get the token causes ndt7 to avoid using the client-integration code. We use `staging` when not in production so we always know which is the `m-lab/speed-proxy` branch we're testing against. Also, update `yarn.lock`. Also, distinguish between staging and production. Also, make sure we use correct permissions for GitHub actions. Also, mention deployment location in the `README.md`.
1 parent 9f7363f commit a8077a0

File tree

6 files changed

+68
-67
lines changed

6 files changed

+68
-67
lines changed

.github/workflows/firebase-hosting-merge.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@ name: Deploy to Firebase Hosting on merge
66
push:
77
branches:
88
- main
9+
permissions:
10+
contents: read
11+
checks: write
912
jobs:
1013
build_and_deploy:
1114
runs-on: ubuntu-latest
1215
steps:
1316
- uses: actions/checkout@v4
1417
- run: npm install -g yarn && yarn install --frozen-lockfile && yarn build
18+
- name: Substitute M-Lab project placeholder
19+
run: sed -i 's/MLAB_PROJECT_PLACEHOLDER/mlab-oti/g' app/measure/measure.js
1520
- uses: FirebaseExtended/action-hosting-deploy@v0
1621
with:
1722
repoToken: '${{ secrets.GITHUB_TOKEN }}'

.github/workflows/firebase-hosting-pull-request.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33

44
name: Deploy to Firebase Hosting on PR
55
'on': pull_request
6+
permissions:
7+
contents: read
8+
checks: write
69
jobs:
710
build_and_preview:
811
if: '${{ github.event.pull_request.head.repo.full_name == github.repository }}'
912
runs-on: ubuntu-latest
1013
steps:
1114
- uses: actions/checkout@v4
1215
- run: npm install -g yarn && yarn install --frozen-lockfile && yarn build
16+
- name: Substitute M-Lab project placeholder
17+
run: sed -i 's/MLAB_PROJECT_PLACEHOLDER/mlab-sandbox/g' app/measure/measure.js
1318
- uses: FirebaseExtended/action-hosting-deploy@v0
1419
with:
1520
repoToken: '${{ secrets.GITHUB_TOKEN }}'

README.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,15 @@ To preview the site locally, we recommend using the Python Simple HTTP Server.
3838

3939
* Navigate to the `/app` directory and run: `python3 -m http.server 8000`
4040

41-
If you are a user on the M-Lab Firebase project, you can also preview the site locally using the firebase-cli: `firebase serve --only hosting:mlab-speedtest`
41+
If you are a user on the M-Lab Firebase project, you can also preview the site locally using the firebase-cli: `firebase serve --only hosting:mlab-speedtest`
42+
43+
## Deployment
44+
45+
The site is deployed via GitHub Actions to Firebase Hosting:
46+
47+
| Environment | Trigger | URL |
48+
|-------------|-------------------------------|----------------------------------|
49+
| Sandbox | Pull request (from same repo) | https://mlab-sandbox.web.app |
50+
| Production | Merge to `main` | https://speed.measurementlab.net |
51+
52+
**Note:** PR deployments only work for branches pushed directly to `m-lab/mlab-speedtest`, not from forks (due to Firebase secrets not being available to fork PRs).

app/measure/measure.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,50 @@ angular.module('Measure.Measure', ['ngRoute'])
6767
testRunning = false;
6868
}
6969

70+
// Determine the M-Lab project based on a placeholder that is substituted
71+
// during deployment. If the placeholder is not substituted (e.g., local
72+
// development), default to `staging` for safe testing.
73+
//
74+
// The reason for using `staging` as opposed to `sandbox` by default is that
75+
// using `staging` allows us to know which commit of `m-lab/speed-proxy` we
76+
// are testing against (i.e., the latest commit of the `main` branch) as opposed
77+
// to being unsure (which commit of a possibly now deleted `sandbox-*` branch
78+
// are we actually testing against?).
79+
function mlabProject() {
80+
const placeholder = 'MLAB_PROJECT_PLACEHOLDER';
81+
return placeholder.includes('PLACEHOLDER') ? 'mlab-`staging`' : placeholder;
82+
}
83+
84+
// Build the locate service priority URL for the given project. Production uses
85+
// locate.measurementlab.net while `staging` uses locate.mlab-`staging`.measurementlab.net.
86+
function locatePriorityURLForProject(project) {
87+
const host = project === 'mlab-oti'
88+
? 'locate.measurementlab.net'
89+
: `locate.${project}.measurementlab.net`;
90+
return `https://${host}/v2/priority/nearest/ndt/ndt7`;
91+
}
92+
7093
async function runNdt7(sid) {
94+
// Fetch a short-lived token from the speed-backend service to enable
95+
// priority access to the Locate API for registered integrations.
96+
// If token fetch fails, gracefully degrade to running without a token.
97+
const project = mlabProject();
98+
const tokenURL = `https://speed-backend.${project}.measurementlab.net/v0/token`;
99+
const locatePriorityURL = locatePriorityURLForProject(project);
100+
101+
let token = null;
102+
try {
103+
const tokenResp = await fetch(tokenURL);
104+
const tokenData = await tokenResp.json();
105+
token = tokenData.token;
106+
} catch (err) {
107+
console.warn('Failed to fetch token, running without priority access:', err);
108+
}
109+
71110
return ndt7.test(
72111
{
112+
clientRegistrationToken: token,
113+
loadbalancer: token ? locatePriorityURL : null,
73114
userAcceptedDataPolicy: true,
74115
uploadworkerfile: "/libraries/ndt7-upload-worker.min.js",
75116
downloadworkerfile: "/libraries/ndt7-download-worker.min.js",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
"@bower_components/jquery": "jquery/jquery-dist#3.0.0",
3636
"@bower_components/skel": "n33/skel#~3.0.1",
3737
"@m-lab/msak": "0.3.1",
38-
"@m-lab/ndt7": "0.0.6",
38+
"@m-lab/ndt7": "0.1.3",
3939
"@m-lab/packet-test": "0.0.16",
4040
"ng-device-detector": "^5.1.4",
4141
"re-tree": "^0.1.7",

yarn.lock

Lines changed: 4 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,10 @@
4646
dependencies:
4747
ua-parser-js "^1.0.37"
4848

49-
"@m-lab/ndt7@0.0.6":
50-
version "0.0.6"
51-
resolved "https://registry.yarnpkg.com/@m-lab/ndt7/-/ndt7-0.0.6.tgz#844da956dcadf1a03b0f76c11833922b8ee67741"
52-
integrity sha512-vOnbJETYUqg8Tj6V3tLshj7Nch4SmuJGPVmedIkC7V/x7LTWNHU98RdYcZbbhMWoPOrqGwhOylkqZZtjXdi0BA==
53-
dependencies:
54-
node-fetch "^2.6.0"
55-
workerjs "^0.1.1"
56-
ws "^8.5.0"
57-
optionalDependencies:
58-
bufferutil "^4.0.6"
59-
utf-8-validate "^5.0.8"
49+
"@m-lab/ndt7@0.1.3":
50+
version "0.1.3"
51+
resolved "https://registry.yarnpkg.com/@m-lab/ndt7/-/ndt7-0.1.3.tgz#d17db5dda6aec5015069c4a6de397aceb57b4a48"
52+
integrity sha512-/Fmh5oO7NnS4pJ8dmeut+aYcegILEo8OLzH58MmCzDsHGuWYPhw1GZFMYDTQ9Q9ty/fbGQ+i3b/D/ipJnpxxuw==
6053

6154
"@m-lab/packet-test@0.0.16":
6255
version "0.0.16"
@@ -549,13 +542,6 @@ buffer-from@^1.0.0:
549542
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
550543
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
551544

552-
bufferutil@^4.0.6:
553-
version "4.0.8"
554-
resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.8.tgz#1de6a71092d65d7766c4d8a522b261a6e787e8ea"
555-
integrity sha512-4T53u4PdgsXqKaIctwF8ifXlRTTmEPJ8iEPWFdGZvcf7sbwYo6FKFEX9eNNAnzFZ7EzJAQ3CJeOtCRA4rDp7Pw==
556-
dependencies:
557-
node-gyp-build "^4.3.0"
558-
559545
bytes@3.1.2:
560546
version "3.1.2"
561547
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
@@ -2918,18 +2904,6 @@ ng-device-detector@^5.1.4:
29182904
re-tree "^0.1.7"
29192905
ua-device-detector "^1.1.1"
29202906

2921-
node-fetch@^2.6.0:
2922-
version "2.7.0"
2923-
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
2924-
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
2925-
dependencies:
2926-
whatwg-url "^5.0.0"
2927-
2928-
node-gyp-build@^4.3.0:
2929-
version "4.8.0"
2930-
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.8.0.tgz#3fee9c1731df4581a3f9ead74664369ff00d26dd"
2931-
integrity sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==
2932-
29332907
node-uuid@~1.4.7:
29342908
version "1.4.8"
29352909
resolved "https://registry.yarnpkg.com/node-uuid/-/node-uuid-1.4.8.tgz#b040eb0923968afabf8d32fb1f17f1167fdab907"
@@ -4150,11 +4124,6 @@ tough-cookie@~2.2.0:
41504124
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.2.2.tgz#c83a1830f4e5ef0b93ef2a3488e724f8de016ac7"
41514125
integrity sha512-Knz9Yr0hlBoWQgUKzOIvRg5adinizAf49i2gHRhj6cLjlM304zRw7uyiY22ADniDxnPHXfIeyQD0EAkgpIz0ow==
41524126

4153-
tr46@~0.0.3:
4154-
version "0.0.3"
4155-
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
4156-
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
4157-
41584127
tunnel-agent@~0.4.1:
41594128
version "0.4.3"
41604129
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb"
@@ -4298,13 +4267,6 @@ useragent@^2.1.6:
42984267
lru-cache "4.1.x"
42994268
tmp "0.0.x"
43004269

4301-
utf-8-validate@^5.0.8:
4302-
version "5.0.10"
4303-
resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.10.tgz#d7d10ea39318171ca982718b6b96a8d2442571a2"
4304-
integrity sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==
4305-
dependencies:
4306-
node-gyp-build "^4.3.0"
4307-
43084270
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
43094271
version "1.0.2"
43104272
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
@@ -4406,19 +4368,6 @@ void-elements@^2.0.0:
44064368
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
44074369
integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==
44084370

4409-
webidl-conversions@^3.0.0:
4410-
version "3.0.1"
4411-
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
4412-
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
4413-
4414-
whatwg-url@^5.0.0:
4415-
version "5.0.0"
4416-
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
4417-
integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==
4418-
dependencies:
4419-
tr46 "~0.0.3"
4420-
webidl-conversions "^3.0.0"
4421-
44224371
which-module@^1.0.0:
44234372
version "1.0.0"
44244373
resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f"
@@ -4436,11 +4385,6 @@ wordwrap@~0.0.2:
44364385
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
44374386
integrity sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==
44384387

4439-
workerjs@^0.1.1:
4440-
version "0.1.1"
4441-
resolved "https://registry.yarnpkg.com/workerjs/-/workerjs-0.1.1.tgz#b7939ed54400937c1c1ef35b74b37dd9bbcbdde6"
4442-
integrity sha512-fMlithUrdswVB/bDtrncuXeuIOwc4hS+LXsAZNjdcpoOjU0rw1TFV2I5IlCwx6hysU2IveI8uWlkf5mTAQXHcw==
4443-
44444388
wrap-ansi@^2.0.0:
44454389
version "2.1.0"
44464390
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
@@ -4462,11 +4406,6 @@ ws@^1.0.1, ws@~1.1.5:
44624406
options ">=0.0.5"
44634407
ultron "1.0.x"
44644408

4465-
ws@^8.5.0:
4466-
version "8.16.0"
4467-
resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4"
4468-
integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==
4469-
44704409
wtf-8@1.0.0:
44714410
version "1.0.0"
44724411
resolved "https://registry.yarnpkg.com/wtf-8/-/wtf-8-1.0.0.tgz#392d8ba2d0f1c34d1ee2d630f15d0efb68e1048a"

0 commit comments

Comments
 (0)