Skip to content

Commit 80f2c2d

Browse files
authored
feat: use client registration token for ndt7 tests (#81)
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 `mlab-staging` as the default when the placeholder is not substituted (local development and PR previews), so we always know which `m-lab/speed-proxy` commit we're testing against. Only the production merge workflow substitutes the placeholder with `mlab-oti`. Also, update `yarn.lock`. Also, make sure we use correct permissions for GitHub actions. Also, mention deployment location in the `README.md`.
1 parent cb3dd7d commit 80f2c2d

File tree

3 files changed

+61
-1
lines changed

3 files changed

+61
-1
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ jobs:
1515
steps:
1616
- uses: actions/checkout@v4
1717
- 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
1820
- uses: FirebaseExtended/action-hosting-deploy@v0
1921
with:
2022
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: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,56 @@ 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+
//
80+
// TODO(bassosimone): when we modernize the website build system, we should
81+
// replace this placeholder-and-sed approach with proper build-time environment
82+
// variable injection. The current approach is acceptable for a single config
83+
// value, but if we find ourselves adding two or three more substitutions, we
84+
// should refactor to use a proper configuration mechanism instead.
85+
function mlabProject() {
86+
const placeholder = 'MLAB_PROJECT_PLACEHOLDER';
87+
return placeholder === 'MLAB_PROJECT_PLACEHOLDER' ? 'mlab-staging' : placeholder;
88+
}
89+
90+
// Build the locate service priority URL for the given project. Production uses
91+
// locate.measurementlab.net while `staging` uses locate.mlab-`staging`.measurementlab.net.
92+
function locatePriorityURLForProject(project) {
93+
const host = project === 'mlab-oti'
94+
? 'locate.measurementlab.net'
95+
: `locate.${project}.measurementlab.net`;
96+
return `https://${host}/v2/priority/nearest/ndt/ndt7`;
97+
}
98+
7099
async function runNdt7(sid) {
100+
// Fetch a short-lived token from the speed-backend service to enable
101+
// priority access to the Locate API for registered integrations.
102+
// If token fetch fails, gracefully degrade to running without a token.
103+
const project = mlabProject();
104+
const tokenURL = `https://speed-backend.${project}.measurementlab.net/v0/token`;
105+
const locatePriorityURL = locatePriorityURLForProject(project);
106+
107+
let token = null;
108+
try {
109+
const tokenResp = await fetch(tokenURL);
110+
const tokenData = await tokenResp.json();
111+
token = tokenData.token;
112+
} catch (err) {
113+
console.warn('Failed to fetch token, running without priority access:', err);
114+
}
115+
71116
return ndt7.test(
72117
{
118+
clientRegistrationToken: token,
119+
loadbalancer: token ? locatePriorityURL : null,
73120
userAcceptedDataPolicy: true,
74121
uploadworkerfile: "/libraries/ndt7-upload-worker.js",
75122
downloadworkerfile: "/libraries/ndt7-download-worker.js",

0 commit comments

Comments
 (0)