This project is for the REST API that handles interactions on the feedback widget UI and adds this data to a database, currently Google Sheets. It is deployed to AWS Lambda + API Gateway. For full architecture of feedback system, see "Technical diagram" section below.
For the latest information on the API endpoints maintained, see the functions imported and configured within the feedback-api-stack.ts file. Within the src/functions/ folder, each file corresponds to an API endpoint. For example, see src/functions/comment.ts for details on the POST /comment endpoint. For a quick summary, this repo supports the following endpoints:
POST /rating- saves Yes/No rating to databasePOST /comment- saves text comment to database (and cleans PII)POST /email- saves email to database
- Clone this repository
- Run
npm install(on Node 22, as listed in.nvmrc) to install Node dependencies - Save the credentials from the
Innov-Platform-DevAWS account to your~/.aws/credentialsfile
To get started or continue working:
npm install # Install dependencies
npm run diff # Preview infrastructure changes
npm run deploy # Deploy to AWS
npm run deploy:api # Deploy the API to AWS
npm run synth:api # Synthesizes the API stack into a CloudFormation templateThis repo has two primary branches: dev and main.
devbranch maps to theInnov-Platform-DevAWS accountmainbranch maps to theInnov-Platform-ProdAWS account
- Create a feature branch from the latest commit on
dev. - Once your implementation is complete, thoroughly test your changes in the dev environment by deploying to the
Innov-Platform-Devaccount (see Deployment for detailed steps.). - Once you've confirmed the dev deployment is working, push your changes and create a PR against the
devbranch. - Once the PR is approved, merge the
devbranch intomain. - At this point, the changes are ready to be deployed to production.
- Check out the
mainbranch and pull the latest commits locally. - Deploy the
mainbranch to theInnov-Platform-Prodaccount.
Deployment to AWS is done locally on the command line and is not yet connected to Github version control.
The code can be deployed to either the dev account (Innov-Platform-Dev) or to the prod account (Innov-Platform-Prod).
⚠️ Please be careful to deploy to the prod account only with extreme caution and after thoroughly testing changes in dev. Make sure to test that API requests work in the browser before deploying to prod (see Test API Requests in the browser for instructions). This ensures that CORS is enabled properly.
- Ensure AWS CLI is installed/up to date.
- Configure your
~/.aws/configfiles withdevandprodprofiles. A sample~/.aws/configcan be found in the ResX Bitwarden under theFeedback API ~/.aws/configitem. - Run
sso:login:devorsso:login:prodto start an active AWS SSO session with the desired account.
- Go to the AWS access portal.
- Click the desired account, and then click "Access keys"
- Export the environment variables under "Option 1: Set AWS environment variables" to your terminal.
- These environment variables will expire after the session duration, so you will have to periodically re-export new variables following the instructions.
To deploy this AWS CDK project to AWS
- If you authenticated using AWS SSO (Option A):
- Run
deploy:api:devordeploy:api:prodbased on which account you want to deploy to.
- Run
- If you authenticated by setting env vars (Option B):
- Run
deploy:api. The CDK project will be deployed to the account whose env vars you last exported.
- Run
Note: If you don't run the scripts, you'll have to navigate to the /infra directory before deploying. Running npx cdk deploy deploys this entire AWS CDK project to AWS. See individual scripts for stack-specific deploys.
This template contains a single lambda function triggered by an HTTP request made on the provisioned API Gateway REST API /rating route with POST method. The request body must be provided as application/json. The body structure is tested by API Gateway against src/functions/rating/schema.ts JSON-Schema definition: it must contain the name property.
- requesting any other path than
/ratingwith any other method thanPOSTwill result in API Gateway returning a403HTTP error code - sending a
POSTrequest to/ratingwith a payload not containing a string property namednamewill result in API Gateway returning a400HTTP error code - sending a
POSTrequest to/ratingwith a payload containing a string property namednamewill result in API Gateway returning a200HTTP status code with a message saluting the provided name and the detailed event processed by the lambda
⚠️ As is, this template, once deployed, opens a public endpoint within your AWS account resources. Anybody with the URL can actively execute the API Gateway endpoint and the corresponding lambda. You should protect this endpoint with the authentication method of your choice.
This section includes test requests for testing the Feedback API Lambdas/endpoints. Update the body of the request as needed to test different scenarios.
There are three different methods for testing these requests outside the browser:
-
Run requests as JSON via the AWS console: Go to the "Testing" tab in the Lambda console for the appropriate function.
-
Send API requests to the dev API Gateway URL. Go the API Gateway resource in the AWS console to find the URL. The URL can also be found in the ResX Bitwarden under the
Feedback API Testing Infoitem. -
Send API requests to our dummy app for testing redirects.
- In production, the frontend feedback widget doesn't send requests directly to the API Gateway URL. Instead, the widget sends requests to a URL on the Innovation site which then redirects to the prod API Gateway URL.
- The URL and test CURL requests can be found in the ResX Bitwarden under the
Feedback API Testing Infoitem.
⚠️ Please note that all requests will write directly to the Prod Google Sheet for the time being. After running requests, be sure to remove any changes from the spreadsheet
{
"headers": {
"Content-Type": "application/json"
},
"body": "{\"pageURL\":\"example.com\",\"rating\":\"true\"}"
}
{
"headers": {
"Content-Type": "application/json"
},
"body": "{\"email\":\"hi@example.com\",\"feedbackId\":\"2\"}"
}
{
"headers": {
"Content-Type": "application/json"
},
"body": "{\"feedbackId\":\"1\",\"comment\":\"good\"}"
}
It is crucial to test API requests in the browser before deploying to prod, because only web browsers enforce CORS. Non-browser clients (e.g. cURL, Postman, etc.) bypass CORS restrictions entirely.
Test the dev API deployment in the browser by running the front-end feedback widget component locally and redirecting its API requests to the dev API Gateway URL:
- Clone the feedback-widget repo.
- Update the
API_URLin feedback-widget.js to the dev API Gateway URL.- To find the URL in the AWS Console, first make sure you're logged into the Innov-Platform-Dev account! Then search "API Gateway" -> click "Feedback API" in the list of APIs -> click "Stages" in the sidebar -> "Invoke URL" under "Stage details"
- Open the
feedback-widget.htmlin the browser — you should see a page containing just the frontend feedback widget component. Test that submiting a rating/comment/email works (use the network tab to ensure requests are being sent to the dev API URL and are returning a success response).
⚠️ Please note that all requests will write directly to the Prod Google Sheet for the time being. After running requests, be sure to remove any changes from the spreadsheet
Note: We can't use Docker Desktop because we don't currently have a way to procure licenses and it's not certified for use at the Office.
Linux
Install the docker daemon as normal since this is open source software.
Windows
Install WSL2 and install the docker daemon inside the linux environment.
macOS
- Install colima with
brew install colima - Install docker with
brew install docker - Install docker-compose with
brew install docker-compose- This will give the message (also in Homebrew docs):
Make sure to follow these instructions or you won't able to run commands using==> Caveats
Compose is a Docker plugin. For Docker to find the plugin, add "cliPluginsExtraDirs" to ~/.docker/config.json:"cliPluginsExtraDirs": [ "/opt/homebrew/lib/docker/cli-plugins" ]docker compose(you will have to usedocker-composeinstead)
- This will give the message (also in Homebrew docs):
- Run
colima startto start the Docker runtime- If it prompts you to, run
brew install lima-additional-guestagents(this is because there was a recent split in the package, see GitHub issue #1333 for more detail)
- If it prompts you to, run
- Run
docker-compose up -d(ornpm run docker:up) from the project root.- The
-dflag indicated detached mode, which runs the container in the background (so it won't be attached to your terminal)
- The
- The database should now be running at the connection string
postgresql://postgres:postgres@localhost:5432/postgres- You can test this by checking that you can connect to the database via psql without erroring:
psql postgresql://postgres:postgres@localhost:5432/postgres
- You can test this by checking that you can connect to the database via psql without erroring:
- To stop the docker container, run
docker compose down(ornpm run docker:down) from the project root. - When you’re done developing, run
colima stopto stop the Docker runtime- Remember to run
colima startin the future whenever you want to use Docker Compose
- Remember to run
We use Prisma Migrate to handle schema migrations.
- Make your desired changes to database schema by editing the
schema.prismafile. - Run
npx prisma migrate dev(ornpm run prisma-migrate:dev) to generate AND apply the migration to the local database.
- (Optional) Use the
--create-onlyflag to generate themigration.sqlfile without applying it to the database.- This allows us to directly customize the
migration.sqlfile, which is useful if we need to make a schema change that isn't supported by Prisma. - If you use this flag, make sure to run
npx prisma migrate devagain to apply the migration to the database.
- This allows us to directly customize the
- (Optional) Run
npx prisma generate(ornpm run prisma:generate) to generate the Prisma Client.
- This generates the Prisma Client code, which is a database client customized based on the
schema.prismafile. The Prisma Client is what you'll use to write SQL queries in TypeScript, and this generation step provides the types to make these queries type-safe. - The generated Prisma Client code is output to the
generated/prisma/directory. Since this directory is git ignored, it doesn't matter whether you run prisma generate before committing schema migrations. It's just that you need to re-run the prisma generate command after every change that's made toschema.prismato sync the Prisma Client to the new schema (including when you haven't personally made schema changes but you're pulling down code that has).
In general, we should "squash" migrations before merging a feature branch to keep our migration history clean. For example, when setting up in the initial schema, several progressive changes were made, but it's more efficient to just execute all of those in a single migration in the same CREATE TABLE query.
Unlike squashing git commits, Prisma Migrate doesn't have a special squash function. Instead, when squashing in a development environment we can follow the procedure below:
- Reset the migration history to the last migration we want to keep
- In practice, do this by deleting the migrations you want to squash from the
migrations/directory
- Reset the local database by running
npx prisma migrate reset(ornpm run prisma-migrate:reset) - Run
npx prisma migrate dev
- When we do this, Prisma will sequentially apply all the migrations in the
migrationsfolder to the freshly reset database. - Since we deleted the migrations we wanted to squash, it's as if they never existed in the first place from the perspective of the database.
- So Prisma will generate a single
migration.sqlfile that accounts for all the schema changes between the last migration we kept in step (1) and theschema.prisma.
Important note: Never squash migrations that have already been applied to the prod database. The procedure described here relies on dropping the entire database in step (2), which causes all data to be lost. There's a separate procedure for cleaning the migration history in a prod environment which we don't need to do during normal development.
Below is the latest technical architecture as of November 2024. To update the file, download the docs/Feedback-Widget-Diagram.excalidraw file, import it on Excalidraw, edit the diagram, and update the corresponding files in this repository with the latest versions.
