portalapp
v1.0.0
Published
- Design doc: [Figma](https://www.figma.com/design/nRnsVlpSoZJC13CbwABE54/NeueHealth-Portal) - Task board: [Notion](https://www.notion.so/NeueHealth-Portal-24a9bc26b8e246018ff39992c167b57c) - Architecture: [Lucid](https://lucid.app/lucidchart/5d346d7f-1
Readme
About
- Design doc: Figma
- Task board: Notion
- Architecture: Lucid
- MVP Details: SharePoint
- Next.js 15 with app router and TypeScript
- Material UI for components and themeing
- npm for package management
- eslint for linting and formatting (rules defined in .eslintrc.json file)
- postgresql for database
- Prisma for database ORM
- NextAuth.js for authentication
- Day.js for date management
- Zod for input validation
- Winston for logging
- Azure Application Insights for monitoring
- Azure Key Vault for storing secrets and most environment variables
- GraphQL / ApolloClient for interacting with portal-data-api to get Location / Patient / Provider data
- Pendo for user tracking and metrics
- TS Code Style Guide from Google, mostly enforced by eslint/prettier
- Project created with command:
npx create-next-app@latest portal-app --ts --eslint --app
Pre-requisites:
- ZScalar VPN on machine
- Admin-level access to your PC for system downloads
- SA (service account) version of your NeueHealth account with read access to the portal-app dev key vault (neu-dev-nhp-kv) secrets in Azure
- Neuehealth github access
Getting Started
Developer environment setup (Windows):
- Install Chocolatey package installer (https://chocolatey.org/install)
- Install packages (git, node, nvm, openssl, azure-cli, and postgresql@15)
choco install git choco install nodejs choco install nvm choco install openssl choco install postgresql15 --params '/Password:postgres' // optionally change `postgres` to a password of your choice. Windows has issues without a password. - Install Github Desktop or other git client (optional)
- Connect your github account to Github Desktop
- Clone the project from https://github.com/neuehealth/portal-app into a suitable folder e.g.
~/Code - Run
Start-Service postgresql-x64-15to create and start the persistent PostgreSQL backend service - Add an empty
~/.nvmfolder - Navigate to
.nvmrc- run
nvm install <NVM_VERSION>whereNVM_VERSIONis whatever is specified in.nvmrc - run
nvm use <NVM_VERSION>- note that you will need to repeat this pattern when switching between projects
- run
- Setup NPM auth to Neuehealth registry:
- Go to Azure DevOps
- Login with your non-_sa account
- Under 'Connect to feed', select 'npm'
- Follow the 'Project setup' instructions for
Windows
- install
vscode(or other IDE supporting vsc exetensions)- install VSCode extensions in
extensions.json
- install VSCode extensions in
- install
chrome(or other chromium browser) - install
pgAdmin(or other db tool)
Developer environment setup (mac/Linux):
Install homebrew
Install git, node, nvm, openssl, azure-cli, and postgresql@15:
brew install git node nvm openssl azure-cli postgresql@15Install Github Desktop or other git client (optional)
- Connect your github account to Github Desktop
Clone the project from https://github.com/neuehealth/portal-app into a suitable folder e.g.
~/CodeRun
brew services start postgresql@15to create and start the persistent PostgreSQL backend serviceAdd an empty
~/.nvmfolderUpdate
~/.zshrcto add postgresql to path, load nvm, and set the node version based on the project.nvmrcfile (from the nvm github readme, scroll for~/.bashrcsetup)export PATH="/usr/local/opt/postgresql@15/bin:$PATH" export NVM_DIR="$HOME/.nvm" [ -s "/usr/local/opt/nvm/nvm.sh" ] && \. "/usr/local/opt/nvm/nvm.sh" [ -s "/usr/local/opt/nvm/etc/bash_completion.d/nvm" ] && \. "/usr/local/opt/nvm/etc/bash_completion.d/nvm" # place this after nvm initialization! autoload -U add-zsh-hook load-nvmrc() { local nvmrc_path nvmrc_path="$(nvm_find_nvmrc)" if [ -n "$nvmrc_path" ]; then local nvmrc_node_version nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")") if [ "$nvmrc_node_version" = "N/A" ]; then nvm install elif [ "$nvmrc_node_version" != "$(nvm version)" ]; then nvm use fi elif [ -n "$(PWD=$OLDPWD nvm_find_nvmrc)" ] && [ "$(nvm version)" != "$(nvm version default)" ]; then echo "Reverting to nvm default version" nvm use default fi } add-zsh-hook chpwd load-nvmrc load-nvmrcSetup NPM auth to Neuehealth registry:
- Go to Azure DevOps
- Login with your non-_sa account
- Under 'Connect to feed', select 'npm'
- Follow the 'Project setup' instructions for your machine (Windows for Windows, Other for MacOS)
Install Chrome
Install VS Code
- Install VSCode extensions in
extensions.json
- Install VSCode extensions in
Install pgAdmin or other PostgreSQL database viewer
Setup your .env file with a pre-existing database url or setup PostgreSQL locally and create the url string based on the local install
Install NPM packages from NeueHealth azure artifacts:
npm installnote: if on windows and experiencing build errors, clear npm cache, delete your
node_modulesfolder, and try again.Regenerate the PrismaClient:
npm run db:generateBuild the project:
npm run buildRun the database migrations:
npm run db:migrate:np npm run db:migrate:g:app # if running static data locally npm run db:migrate:g:configSeed your user account locally:
- Copy the query from
prisma/seedScripts/1-seedLocalAccessGroup.sqlfile into pgAdmin (or whatever you're using to query the DB locally) - Run the query against your local db (ONLY LOCAL DB)
- Copy the query from
prisma/seedScripts/2-seedLocalUser.sqlfile into pgAdmin (or whatever you're using to query the DB locally) - Update the
<>values on lines 20-22 - Run the query against your local db (ONLY LOCAL DB)
- Copy the query from
Login to azure locally with your
sa_account and select theneu-developmentsubscription:az loginRun the local development server:
npm run devOpen http://localhost:3000 in your browser to see the result
On the right-hand side of the homepage, click the
Employee Loginbutton and login with your non-_sa NeueHealth account
Folders / Structure
- Generally follows Next.js folder structure
/app: Next.js app router folder, essentially the traditional/srcfolder/_apiCallers/<page>/apiCaller<Component>.ts: contains front-end functions for validating inputs, building the request object, calling an API endpoint, and handling the response object/_common: contains app-wide constants, validators, and utilities/Components: common components used across multiple pages/Context/<Context>/: contains the FE context definition, provider, and any related types/utilities to be used for global state management/Lib: library definitions/configurations/GraphQL: GraphQL definitions for connecting toportal-data-api/queryWrappers: folder containing a wrapper function for each supportedportal-data-apiGQL queryApolloClient.ts: GraphQL client singletonconstants.ts: constants file for use withportal-data-apiqueriestypes.ts: type file related to eachportal-data-apiquery resolver
ApplicationInsights.ts: Azure Application Insights setup/registration logicAzureKeyVault.ts: Azure key vault read functionsdayjs.ts: DayJS initialization with UTC and timezone supportnext-auth.d.ts: Next-Auth types override to add additional fields to the User object in the SessionNextAuth.ts: Next-Auth NextAuthOptions builder including providers, callbacks, and other configuration optionspendo.ts:Pendometrics tracking initialization logicPrismaClient.ts: Prisma ORM singleton used to query the databaseWinston.ts: wrapper aroundwinstonlogging library
/RolesAndConfigs: contains authorization types and configurations alongside page definition configurationsconstants.ts: constants file for use with user permissionsconstantsDbPermissionNameKeys.ts: constants file for the DB Permission table names to allow for flat table structure and maximum overall flexibilitytypes.ts: type definition file for use with user permissionsutils.ts: contains all utility/helper functions for user permissions
constants.ts: common constants used across the appEnvironment.ts: singleton used to hold environment variables pulled from either local .env or the Key Vault. When developing locally, temporarily update this file to override where variables are pulled fromglobal.d.ts: defines the global object to store/reference singletons within the appinitializeServer.ts: logic that runs on server start. Gets environment variables and initializes singleton objects to hydrate global.d.tstypes.ts: global common type definition fileutils.ts: common util functions used across the appvalidators.ts: common field validators used across the app
/_layout: components folder for the base page layout defined inlayout.tsx/api: API route folder/<component route>: api routes folder for page data component apisroute.ts: controller file that defines the HTTP methodsservice<name>.ts: service files to gather data and perform business logic, called by the route as neededtypes.ts: file that defines the input and output types for the controllervalidators.ts: file that defines the input validators using Zod objects
/guide: project sub-folder for Guide branded tool. Follows the same general format as the base NeuePules/appfolder, with the caveat that every page/api route in this folder is pre-pended with/guide//<page route>: page route folders/_components: folder for non-routeable, page-specific componentslayout.tsx: optional page-specific layout definitionpage.tsx: main page file that defines the page level view and interactionserror.tsx: optional page-specific error page to show for specific errors/<page sub-route>: page sub-route folders, which build on the existing route path e.g./my-patients/[id]/_components: folder for non-routeable, page-specific componentslayout.tsx: optional page-specific layout definitionpage.tsx: main page file that defines the page level view and interactionserror.tsx: optional page-specific error page to show for specific errors
icon.ico: icon image to display alongside the browser tab titlelayout.tsx: base layout file that applies to the entire sitenot-found.tsx: 404 page definitionpage.tsx: home page definition for '/' routetheme.ts: MUI theme definition to use across the site
/database: prisma folder for all database schemas and migrations/prisma-<application>: individual database folder for each application/<schema>: individual schema folders for each application database/migrations: migrations folder for schema changes and any seed data/seedScripts: SQL scripts for seeding a local DBschema.prisma: database schema definition
/public: static assets, mainly logos and other images.dockerignore: similar to .gitignore, specified files/folders to not include in the Docker imageeslint.config.mjs: eslint config definition.env: stores local environment variables (not checked into git).gitignore: defines files/folders for git to ignore.npmrc: package registry definition file for pointing to the NeueHealth internal artifactory in Azure.nvmrc: sets which version of Node to run the project with.prettierrc.json: prettier config definitionazure-pipeline.yaml: Azure pipeline definition for the projectDockerfile: Docker definition for the projectinstrumentation.ts: Next.js instrumentation file that runs once at server startnext-env.d.ts: file generated by Next, do not editnext.config.ts: originally generated from create-next-app, contains configuration options for Nextpackage-lock.json: lock file generated when runningnpm ibased on thepackage.json(not checked into git)package.json: project definition file that defines script aliases and package dependencies for release and devREADME.md: the markdown file that defines this documenttsconfig.json: compiler and file options used to define how the TypeScript in this project is processed and built
Env Variables
Create a top level .env file with:
USE_LOCAL_ENV: boolean used to determine whether or not to use local .env file (true) or Azure key vault (false / undefined). If running portal-data-api locally:trueKEY_VAULT_URL: the URL to the dev key vault in Azure for NeuePulseKEY_VAULT_URL_GUIDE: the URL to the dev key vault in Azure for GuideENVIRONMENT: defines which banner to show to easily distinguish lower environments from each other and from PRODDATABASE_URL: connection string to the PostgreSQL database in formpostgresql://<username>:<password>@<server url>:5432/portal-app?schema=publicNEXTAUTH_URL: base URL of the app e.g.http://localhost:3000NEXTAUTH_SECRET: the secret value string used to encrypt/decrypt session tokens. Generated by runningopenssl rand -base64 32. (If on a Windows machine, openssl is included in the git installation and this command should be run in git bash.)GRAPHQL_URL: portal-data-api GraphQL api URL. If running portal-data-api locally:http://localhost:4000/graphqlAPPLICATIONINSIGHTS_CONNECTION_STRING: generally keep this empty, only add to test/debug Application Insights locallyGQL_ENABLE_VERBOSE_LOGGING: boolean enable verbose GQL query logging that includes timing, criteria, and the query itselfDATABASE_URL_GUIDE_APP: connection string to the PostgreSQL database for Guide in formpostgresql://<username>:<password>@<server url>:5432/guide?schema=appDATABASE_URL_GUIDE_CONFIG: connection string to the PostgreSQL database for Guide config in formpostgresql://<username>:<password>@<server url>:5432/guide?schema=configDATABASE_URL_GUIDE_DATA_VIEWS: connection string to the PostgreSQL database for Guide data_views in formpostgresql://<username>:<password>@<server url>:5432/guide?schema=data_viewsDATABASE_URL_NEUE_DATA_PUBLIC: connection string to the PostgreSQL database for Neue Data (common global data - like patient, provider, etc.) in formpostgresql://<username>:<password>@<server url>:5432/guide?schema=data_viewsENCRYPTION_SECRET_GUIDE: the secret value string used to encrypt/decrypt sensitive database values. Generated by runningopenssl rand -base64 32. (If on a Windows machine, openssl is included in the git installation and this command should be run in git bash.)
Example local .env:
- note that windows requires a db password, so you'll need to reference the syntax above to include yours.
USE_LOCAL_ENV=true
KEY_VAULT_URL="https://neu-dev-nhp-kv.vault.azure.net"
KEY_VAULT_URL_GUIDE="https://neu-dev-dst-kv.vault.azure.net"
ENVIRONMENT="local"
DATABASE_URL="postgresql://postgres:@localhost:5432/portal-app?schema=public"
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="4W9843ALG...Ih/M13dw="
GRAPHQL_URL="https://portal-data-api-dev.neuehealth.com/graphql"
DATABASE_URL_GUIDE_APP="postgresql://postgres:@localhost:5432/guide?schema=app"
DATABASE_URL_GUIDE_CONFIG="postgresql://postgres:@localhost:5432/guide?schema=config"
ENCRYPTION_SECRET_GUIDE="wfB+bpJTr...IYQKDc="Database Models / Migrations
Models are defined in the
database/prisma-<project>/<schema>/schema.prismafileModels are defined manually (or pulled in from an existing DB in the case of the Guide
configschema), followed by a migration to sync the schema changes to the database itselfData migrations can be created by creating a migration without schema changes, followed by updating the empty
migration.sqlgenerated file and then running the migration normallyData changes can also be added as part of a generated schema migration as well by updating the
migration.sqlfile before running the migrationTo format the schema file, run:
npm run db:formatTo create a new migration, run (a timestamp will be added to the front of the name you provide):
npm run db:migration:[np/g:<schema>]:createIf there are errors while running the migration the error will be saved to the _primsa_migrations table of the db in the logs column.
To run the migration against the database, run:
npm run db:migrate:np npm run db:migrate:g:app # if running static data locally npm run db:migrate:g:configTo manually regenerate the PrismaClient, run:
npm run db:generate
Group Configurations
- Defined in
app/_common/RolesAndConfigs/configTypeEntities.ts - Determines which front end pages and components will be shown based on the group (ACO Reach, UPN, etc.)
- New front end features should be added to the group config type and group configs for each group
- Also defines the highest possible component permissions set for a User Role
User Roles
- Role names defined in
app/_common/RolesAndConfigs/constants.ts - Role permissions defined for each group in
app/Common/RolesAndConfigs/userRoleConfigs.ts - Based off the group configurations with the ability to turn off additional components (only turn off)
- New back end/api-only features should be added to the role config type and added for each role/group
Portal-Design Integration
- Local setup using portal-design GitHub locally:
- Open your local
~/.npmrcand project.npmrcand comment out (#) theregistry=line added in Getting Started step 2 - Follow the local setup steps in the portal-design project
- In the local
portal-designproject, runnpm run build-package - Copy the full path to the
/nh-design-library/dist/folder - In this app, run
npm i <full path of the dist folder>
- Open your local
- Azure Artifacts setup:
- Setup your
~/.npmrcas stated above in Getting Started step 2 - Run
npm ias normal
- Setup your
Portal-Data-Api Integration
- Local setup using portal-data-api GitHub locally:
- Add
GRAPHQL_URL="http://localhost:4000/graphql"to .env as defined in Env Variables - Run the portal-data-api project locally, open the graphql sandbox at http://localhost:4000/graphql
- Define the query to call within the sandbox and test that the output matches requirements
- Copy the query into the matching api route service inside a
global.apolloClient.querycall - Create a type for the result and return it up the chain as usual
- Add
- Dev setup using the portal-data-api Dev Environment:
- Add
GRAPHQL_URL="https://portal-data-api-dev.neuehealth.com/graphql"to .env as defined in Env Variables - Open the graphql sandbox at https://portal-data-api-dev.neuehealth.com/graphql
- Define the query to call within the sandbox and test that the output matches requirements
- Copy the query into the matching api route service inside a
global.apolloClient.querycall - Create a type for the result and return it up the chain as usual
- Add
Adding a New Page
- Create a new
/app/<page route>folder - Create a new
page.tsxfile with a standard React page function - Update the
/app/_common/constants.tsfile PAGE_ROUTE enum with the new route- If the page is publicly accessible (no login required), also add the PAGE_ROUTE to the PUBLIC_PAGE_ROUTES array
- If the page requires a login:
- Update
UserRoleConfigto add a new boolean field calledshowPage<New Route> - Update the
/app/_common/Components/PageWrapper.tsxcomponent to add the new PAGE_ROUTE to the route switch statement
- Update
- Wrap the return jsx element html definition in a
PageWrappercomponent, setting the route option to the new PAGE_ROUTE entry - If the page will have a navigation button in the header, update
/app/_layout/HeaderBar.tsxto add the route inbuildNavButtonsbased on a roleConfig check - If the page will have a navigation button in the slide out user navigation drawer, update
/app/_layout/NavDrawer/NavDrawer.tsxto add the route where needed - Update
/app/_common/RolesAndConfigs/types.tsUserRoleConfigtype to addshowPage<Page Name>boolean field - Update
/app/_common/RolesAndConfigs/types.tsConfigTypeEntitytype to addconfigPage<Page Name>field and related empty type - Update
/prisma/schema.prismaUserRolemodel to add the newshowPage<Page Name>boolean field with a proper default (usually true) - Run
npm run db:formatand thennpm run db:generate - Run
npm run db:migration:createto add a migration to add the new column. If not all UserRoles get the permission, update the migration to set the proper boolean for each of the existing UserRoles
Adding a New Data Component to a Page
- Create a new
/app/<page route>/_componentsfolder (if it doesn't exist yet) - Create a new
/_components/<component>.tsxfile with the component definition - Update the
/app/_common/RolesAndConfigs/types.tsto add a newPageConfig<Route>.show<Component>boolean field - Update the
/app/_common/RolesAndConfigs/constantsDbPermissionNameKeys.tsto add the newshow<Component Name>field - Update the
/app/_common/RolesAndConfigs/utils.tsbuildConfigTypeEntityFromAllowedPermissionsmapper function to include the new field - Add a migration to add the new field name string and value row to
Permissiontable for every existingPermissionGroup - Create a new
/app/api/<page>/<route>/route.tsfile with the route definition that checks permissions, validates input, calls required service(s), and returns the data required by the front end component - If any inputs are required, create a new
/app/api/<page>/<route>/validators.tsfile to define the input Zod validators - Create a new
/app/api/<page>/<route>/types.tsfile to define the input types (based on the Zod validators) and the output types used for the route and service(s) - Create a new
/app/api/<page>/<route>/service<Route>.tsfile with the service definition used to get all or part of the required data - Create a new
/app/_apiCallers/<page route>/apiCaller<PageRoute><ComponentName>.tsfile with the api call input validation and fetch call logic - Add the new component within the
page.tsxPageWrappercomponent based on the user role configPageConfig<Route>.show<Component>boolean
Deployment Steps
DEV Environment
Merge the branch into the
mainbranch via GitHub PROnce merged, the build pipeline will update the
Dev EnvironmentautomaticallyIf there are any migrations to run:
- Checkout
mainbranch and pull latest - Open Azure Portal and go to the
neu-dev-nhp-kvresource - In your
.envfile, update theDATABASE_URLto match the currentDATABASE-URLsecret value from the key vault - In your local terminal, run
npm run db:generate - In your local terminal, run
npm run db:migrate - Revert your .env file
DATABASE_URLback to your local DB connection string
- Checkout
STAGE Environment
Ensure any dependecies on Data-Api have been released to STAGE already
Checkout
mainbranch and pull latestCheckout
mainbranch of neu-k8s repo and pull latestCreate a new branch in the form of
\<your GitHub username>/\<current date in form YYYY.MM.DD>-update-staging-vX.XX.XXwherevX.XX.XXmatches the package.json versionUpdate
clusters/neu-stg-nhp-aks/portal-app/deployment.yamlline 49 to replace the last part of theimagevariable (:main-XXXXXXX) to the first 7 characters of the git commit SHA you want to release to stagingCreate a PR and once approved and merged the server will pick up and automatically deploy the new version on a 5min schedule
If there are any migrations to run:
- Checkout the exact commit hash from
mainbranch - Open Azure Portal and go to the
neu-stg-nhp-kvresource - In your
.envfile, update theDATABASE_URLto match the currentDATABASE-URLsecret value from the key vault - In your local terminal, run
npm run db:generate - In your local terminal, run
npm run db:migrate - Revert your .env file
DATABASE_URLback to your local DB connection string
- Checkout the exact commit hash from
PROD Environment
Ensure any dependecies on Data-Api have been released to PROD already
Checkout
mainbranch and pull latestCheckout
mainbranch of neu-k8s repo and pull latestCreate a new branch in the form of
\<your GitHub username>/\<current date in form YYYY.MM.DD>-update-prod-vX.XX.XXwherevX.XX.XXmatches the package.json versionUpdate
clusters/neu-prd-nhp-aks/portal-app/deployment.yamlline 49 to replace the last part of theimagevariable (:main-XXXXXXX) to the first 7 characters of the git commit SHA you want to release to prodCreate a PR and wait for an Andy or Daniel approval
Once approved, get explicit signoff again in Teams (to make sure everything else is ready and it's after 3pm CST, typically), then merge
Once merged, the server will pick up and automatically deploy the new version on a 5min schedule
If there are any migrations to run:
- Checkout the exact commit hash from
mainbranch - Open Azure Portal and go to the
neu-prd-nhp-kvresource - In your
.envfile, update theDATABASE_URLto match the currentDATABASE-URLsecret value from the key vault - In your local terminal, run
npm run db:generate - In your local terminal, run
npm run db:migrate - Revert your .env file
DATABASE_URLback to your local DB connection string
- Checkout the exact commit hash from
Manual Testing Steps
Update these steps as more pages/user types/components/etc. emerge
User Auth / Permissions
- Without logging in, route to public pages and ensure they show correctly:
- /
- /login/error
- ?error=NO_USER
- ?error=NO_ROLE
- ?error=NO_AUTH
- Without logging in, route to non-public pages and ensure they show nothing and route to /
- /dashboard
- /my-patients
- /user-profile
- From /, click login button in the header bar and ensure it keeps you on the / page
- From /, click the NeueHealth logo in the header bar and ensure it keeps you on the / page
- Click 'Employee Login', select your @neuehealth.com SSO login and get routed to /dashboard
- Once logged in:
- See that header bar nav buttons show based on user role config
- See that user card is populated based on user config
- Click the user card and see that the nav drawer opens with user card populated based on user config
- Click Profile and see that it routes to /user-profile with user info populated based on user config
- Go to /dashboard and ensure data loads correctly based on user roles
- Go to /my-patients and ensure the page loads properly based on user roles
- Click on a patient link and get routed to /my-patients/<patientId>
- Ensure page loads properly based on user roles
- Go to /user-profile and ensure the page loads properly
- In the nav drawer, click logout:
- Ensure it routes to /
- Ensure the header bar nav buttons disappear
- Ensure user card is replaced with login button
- From /, click 'Affiliate Login', login with invalid credentials, and see that it shows an error
- Click 'Affiliate Login', then 'Forgot your password?', then 'Cancel', and see that you're routed back to the start of the external login flow
- Click 'Affiliate Login', then 'Sign up now', then 'Cancel', and see that you're routed back to the start of the external login flow
- Click 'Affiliate Login', then sign in and see that you're routed to /dashboard
Troubleshooting common errors
- Check if there are any pending migrations and run them:
- run
npm run db:generate - run
npm run db:migrate:npandnpm run db:migrate:g
- run
- Check if any npm packages were added or versions changed:
- run
npm install
- run
- ApolloError – Error retrieving secret from key vault: This may occur if your Service Account (SA) requires a password change. If you've recently changed your password, try running the following command in your terminal to refresh your credentials: az login. In addition, try relogging into your Zscaler session.
- Linter misbehaving:
- restart VS Code
- run
npm run build
Documenting work / creating a PR
- Create or identify a notion task associted with your PR branch
- Copy the notion id so our github x notion integration links the task id to the branch
- Create a branch labeled with this convention:
convention: <YOUR_NAME>/<NOTION_ID>-<DESCRIPTION> example: josh/CP-646-README-updates - Complete your work and ensure your feature is code-complete and production-ready
- Aim for small digestible feature branches, split them by sub-feature if needed. See the stack PR section below if needed.
- Create your PR in github
- Follow all applicable steps of the PR template criteria
- Label appropriately and tag at least one dedicated reviewer
How to stack PRs
- If your feature is above 500 lines of code, consider stacking your branches by subfeature for easier reviewal. For instance if you have a branch with 1 page and 8 different components, you may consider 1 base branch, and several sub-branches containing the component-level work.
main <- josh/CP-111-some-big-page josh/CP-111-some-big-page <- josh/some-components-of-big-page josh/CP-111-some-big-page <- josh/some-other-components-of-big-page
Guide Sub-Project
Turn Guide on or off
Update the NeuePulseApplication table in the portal-app database to set the Decision Support Tool entry isActive to TRUE
Add user access to Guide
Add a record to the UserConfigApplicationAccess table in the portal-app database linking the UserConfig to the NueuPulseApplication for Guide
Merging protocol
A branch is merged into main
- Merge
mainintofeature/dstand push the branch- If there are any migrations added in main, move the migration from
prisma/migrationsfolder to the newdatabase/prisma-neue-pulse/migrationsfolder and include that in the merge commit or commit that change separately - Run the migrations against the dev branch:
- Run
npm run db:generate - Update your local .env file
DATABASE_URLentry to point to the Dev database (copy theDATABASE-URLsecret value fromneu-dev-nhp-kvkey vault in azure) - Run
npm run db:migrate:np - Revert your .env back to point to local db
- Run
- If there are any migrations added in main, move the migration from
- Run the portal-app_nhp-release pipeline against the
feature/dstbranch (this will automatically deploy the build output to dev and roll the pods)
Merging a branch into feature/dst
- Create a PR with your branch against
feature/dst - Ensure your local branch builds locally without errors
- Get at least one approval before merging
- Merge the PR
- Run the portal-app_nhp-release pipeline against the
feature/dstbranch (this will automatically deploy the build output to dev and roll the pods) - If there are any migrations added
- Run the migrations against the dev branch:
- Run
npm run db:generate - Update your local .env file
DATABASE_URLDATABASE_URL_GUIDE_APPandDATABASE_URL_GUIDE_CONFIGentries to point to the Dev database (copy theDATABASE-URL-APPandDATABASE-URL-CONFIGsecret values fromneu-dev-dst-kvkey vault in azure) - Run
npm run db:migrate:g:appand/ornpm run db:migrate:g:configbased on which folder the migration was added to - Revert your .env back to point to local db
- Run
- Run the migrations against the dev branch:
Update Guide database config schema from dev
- Update your local .env file
DATABASE_URL_GUIDE_CONFIGentry to point to the Dev database (copy theDATABASE-URL-CONFIGsecret values fromneu-dev-dst-kvkey vault in azure) - Run
npm run db:pull:g:config - Update the
database/config/schema.prismafile to map new table names from plural snake_case to singular PascalCase and column names from snake_case to camelCase - Create a new migration to sync the changes:
- Run
npm run db:migration:create:g:config - Input a migration name that loosely describes what tables are changing/being added
- If there are any check constraints on any of the new tables added (Prisma will not automatically handle those):
- Open pgAdmin and connect to the Dev Guide database
- Find the relevant new table(s) with constraints and expand them
- For each new constraint:
- Right click ->
CREATE Script - Copy the
ALTER TABLEstatement in the new window and paste it at the bottom of the newmigration.tsfile
- Right click ->
- Mark the migration as applied with
npm run db:migrate:g:config:resolve <migration name (the folder name containing the new migration.ts file)>
- Run
- Revert your .env back to point to local db
