Update dependency doc with info on testing backend updates (#4919)

* update details for backend dependency testing
* add details to README about load testing using k6
* types/k6 package

Co-authored-by: Vincent <Vinnl@users.noreply.github.com>
This commit is contained in:
Robert Helmer 2024-08-06 11:49:55 -07:00 коммит произвёл GitHub
Родитель ebc38a8632
Коммит 246e0194bd
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
5 изменённых файлов: 118 добавлений и 7 удалений

Просмотреть файл

@ -22,6 +22,7 @@ the "what" and "why" of data breach alerts.
- [Volta](https://volta.sh/) (installs the correct version of Node and npm)
- [Postgres](https://www.postgresql.org/) | Note: On a Mac, we recommend downloading the [Postgres.app](https://postgresapp.com/) instead.
- [Python](https://www.python.org/downloads/) | [With Homebrew](https://docs.brew.sh/Homebrew-and-Python)
- [k6](https://grafana.com/docs/k6/latest/set-up/install-k6/) | k6 load testing tool
### Code style
@ -209,6 +210,20 @@ To test this part of Monitor:
4. Go to `about:protections`
5. Everything should be using your localhost instance of Monitor.
#### Load testing
k6 is used for load testing.
To test the HIBP breach alerts endpoint, use:
```sh
export SERVER_URL=...
export HIBP_NOTIFY_TOKEN=...
k6 -u 10 src/scripts/loadtest/hibp.js # Run with 10 virtual users
```
See https://grafana.com/docs/k6/latest/get-started/running-k6/ for more information.
## Localization
All text that is visible to the user is defined in [Fluent](https://projectfluent.org/) files inside `/locales/en/` and `/locales-pending/`. After strings get added to files in the former directory on our `main` branch, they will be made available to our volunteer localizers via Pontoon, Mozilla's localization platform. Be sure to reference the [localization documentation](https://mozilla-l10n.github.io/documentation/localization/dev_best_practices.html) for best practices. It's best to only move the strings to `/locales/en/` when they are more-or-less final and ready for localization. Your PR should be automatically tagged with a reviewer from the [Mozilla L10n team](https://wiki.mozilla.org/L10n:Mozilla_Team) to approve your request.

Просмотреть файл

@ -215,31 +215,66 @@ TODO: Describe how the `fxa-rp-events` endpoint uses these packages.
### `uuid`
TODO: Describe how to verify that `uuid` updates didn't break anything.
Used in places where a random identifier is needed:
- as a `nonce` in `src/middleware.ts` for CSP
- server-side Glean document IDs in `src/app/functions/server/glean.ts`
- as an experimentation ID for Nimbus in `src/app/functions/server/getUserId.tsx` and `src/app/functions/server/getExperimentationId.ts`
- for email verification tokens in `src/db/tables/emailAddresses.js`
1. Check that `nonce` is present in `content-security-policy` header for HTTP responses.
2. Check that `experimentationId` is set as a cookie in the form `guest-${uuid}`
3. Add a secondary email from the Settings screen and ensure that email verification works
### `@aws-sdk/*`
TODO: Describe how to verify that AWS SDK updates didn't break anything.
Used for S3, by the `npm run cron:db-pull-breaches` cron job.
This job runs periodically on stage and production to download Favicon files from DuckDuckGo and re-uploads them to Monitor's S3 bucket.
Check in the server logs that this job completed without errors.
### `@google-cloud/pubsub`
TODO: Describe how to verify that GCP pubsub updates didn't break anything.
GCP PubSub is used for email breach notifications from HIBP:
- `src/app/api/v1/hibp/notify/route.ts` receives the breach notification and queues in PubSub
- `src/scripts/cronjobs/emailBreachAlerts.ts` is run by a periodic cron job
Check the server logs and ensure there are no errors. See
[this section of the README](https://github.com/mozilla/blurts-server/blob/main/README.md#incoming-webhook-requests-from-hibp-will-be-of-the-form)
for information about simulating a breach alert.
See `./src/loadtest/hibp.js` for a K6 load testing script which will exercise this.
### `@grpc/grpc-js`
TODO: Describe how to verify that GRPC updates didn't break anything.
GRPC is used as a communication protocol for various GCP services.
Monitor uses it to facilitate the local PubSub emulator. See [this section of the README](https://github.com/mozilla/blurts-server/blob/main/README.md#pubsub)
for instructions on running the Pub/Sub emulator locally.
### `winston` and `@google-cloud/logging-winston`
TODO: Describe how to verify that logger updates didn't break anything.
Winston is a logging library that provides structured logging in GCP.
Look for any `logger.*` statement in `./src` and ensure that log messages are being written as [structured logs](https://cloud.google.com/logging/docs/structured-logging).
### `@sentry/*`
TODO: Describe how to verify that Sentry updates didn't break anything.
Sentry is an error reporting service that captured front-end (browser) as well as back-end (Node) error messages.
In normal operation nothing should be sent to Sentry, but you can verify that the SDK is loading:
1. in the browser, verify that there are no errors related to Sentry in the devtools console
2. in the server logs, verify `instrumentationHook` is logged as enabled and there are no errors related to Sentry
### `nodemailer`
TODO: Describe how to verify that nodemailer updates didn't break anything.
Nodemailer is used by `src/utils/email.js` to send all email related to Monitor. It uses AWS Simple Email Services (SES) by default,
which is controlled by the `SMTP_URL` environment variable. Any `smtps://` URL can be used here for testing, and any email Monitor sends
can be used for testing.
Monitor provides a tool for sending test email at the endpoint `/admin/emails`.
### `adm-zip`

8
package-lock.json сгенерированный
Просмотреть файл

@ -69,6 +69,7 @@
"@types/jest-axe": "^3.5.9",
"@types/jsonwebtoken": "^9.0.6",
"@types/jwk-to-pem": "^2.0.3",
"@types/k6": "^0.52.0",
"@types/mjml": "^4.7.4",
"@types/mjml-browser": "^4.15.0",
"@types/nodemailer": "^6.4.15",
@ -10952,6 +10953,13 @@
"integrity": "sha512-I/WFyFgk5GrNbkpmt14auGO3yFK1Wt4jXzkLuI+fDBNtO5ZI2rbymyGd6bKzfSBEuyRdM64ZUwxU1+eDcPSOEQ==",
"dev": true
},
"node_modules/@types/k6": {
"version": "0.52.0",
"resolved": "https://registry.npmjs.org/@types/k6/-/k6-0.52.0.tgz",
"integrity": "sha512-yaw2wg61nKQtToDML+nngzgXVjZ6wNA4R0Q3jKDTeadG5EqfZgis5a1Q2hwY7kjuGuXmu8eM6gHg3tgnOj4vNw==",
"dev": true,
"license": "MIT"
},
"node_modules/@types/lodash": {
"version": "4.14.202",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz",

Просмотреть файл

@ -122,6 +122,7 @@
"@types/jest-axe": "^3.5.9",
"@types/jsonwebtoken": "^9.0.6",
"@types/jwk-to-pem": "^2.0.3",
"@types/k6": "^0.52.0",
"@types/mjml": "^4.7.4",
"@types/mjml-browser": "^4.15.0",
"@types/nodemailer": "^6.4.15",

Просмотреть файл

@ -0,0 +1,52 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* NOTE: This is a k6 loadtest script, see https://k6.io/ for more information.
*
* In particular, k6 supports JS but is not a Node package: https://k6.io/docs/get-started/installation/
* This is why import/no-unresolved and no-undef are ignored.
*
* @see https://grafana.com/docs/k6/latest/get-started/running-k6
*/
/* eslint-disable import/no-unresolved */
/* eslint-disable no-undef */
import { post } from "k6/http";
const url = `${__ENV.SERVER_URL}/api/v1/hibp/notify`;
// eslint-disable-next-line import/no-anonymous-default-export
export default function () {
let data = {
breachName: "ApexSMS",
// NOTE: modify this hash range if you want to receive email to specific test account(s).
// This example should only email an address that is a sha1 hash for 1c48923da9f6f17165711712d11bc104087444cc.
// See https://www.troyhunt.com/understanding-have-i-been-pwneds-use-of-sha-1-and-k-anonymity/ for more information.
hashPrefix: "1c4892",
hashSuffixes: [
"3da9f6f17165711712d11bc104087444cc",
"3da9f6fffff5711712d11bc104087444cc",
],
};
// Using a JSON string as body
let res = post(url, JSON.stringify(data), {
headers: {
"Content-Type": "application/json",
// eslint-disable-next-line no-undef
Authorization: `Bearer ${__ENV.HIBP_NOTIFY_TOKEN}`,
},
});
try {
const result = res.json();
if (result.success !== true) {
throw new Error(`Non-success result: ${JSON.stringify(result)}`);
}
} catch (ex) {
throw new Error(`Failed to parse result: ${res.status}, ${res.text}`);
}
}