Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
85d3d63
fix: put what to expect additional text behind feature flag (#5425)
ludtkemorgan Oct 14, 2025
74231d9
fix: redirect to an unauthorized page rather than show blank page for…
jaredcwhite Oct 15, 2025
e313645
fix: firefox not clearing unit errors (#5286)
millord Oct 15, 2025
9812d5d
fix: Adding missing autoprefixer dependency to partners site (#5436)
Oct 15, 2025
82f6537
feat: non regulated listings api layer updates (#5413)
matzduniuk Oct 16, 2025
837fe2e
feat: scripts to migrate msq data to refactor schema (#5428)
mcgarrye Oct 16, 2025
e0ebc60
docs: add note about api unit tests needing TIME_ZONE env var (#5465)
Oct 20, 2025
41d4103
fix: [Bug] Duplicate empty column in lottery export for household mem…
millord Oct 21, 2025
268d43a
fix: large array params must be converted from object format (#5313)
jaredcwhite Oct 21, 2025
69ddcb9
chore: upgrade testing-library-react (#4724)
emilyjablonski Oct 22, 2025
9f4f509
fix: add pii deletion population script (#5440)
ludtkemorgan Oct 22, 2025
62963ba
fix: add new address listings view (#5462)
ludtkemorgan Oct 22, 2025
bc2fe3b
5458/add new admin support role to 2 more emails (#5464)
millord Oct 23, 2025
10cbadf
feat: terraform code for managing the bloom-dev-deployer permission s…
Oct 27, 2025
ecfe1d6
5442/waitlist lotteries feature flag (#5501)
millord Oct 27, 2025
776b768
feat: redirect off of Common App if the listing/application isn't in …
jaredcwhite Oct 27, 2025
036c832
feat: add Dockerfiles and compose file to run locally (#5448)
Oct 28, 2025
3fd6a2f
fix: fixes package.json for windows setups (#5509)
YazeedLoonat Oct 28, 2025
6aba8ae
fix: hide redundant lottery section (#5492)
KrissDrawing Oct 29, 2025
4672281
feat: add github workflow for building docker images from main branch…
Oct 30, 2025
ea9f96d
feat: add new jurisdiction for seeded data (#5520)
KrissDrawing Nov 3, 2025
15230c1
feat: 5441/waitlist lotteries allow selection fcfs UI (#5510)
millord Nov 4, 2025
28a8785
chore(deps): bump dotenv to 17.2.3 (#5522)
ludtkemorgan Nov 4, 2025
71c3f09
feat: add feature flag for housing developer owner (#5549)
KrissDrawing Nov 5, 2025
c3f76c5
fix: neighborhood amenities remove sections (#5536)
KrissDrawing Nov 6, 2025
ca60911
fix: [5441]-waitlist-lotteries-allow-selection-fcfs-fixes (#5548)
millord Nov 6, 2025
1b9eb2e
fix: put support admin behind feature flag (#5521)
ludtkemorgan Nov 6, 2025
b761b62
fix: pass the jurisdiction id to edit unit form (#5555)
ludtkemorgan Nov 10, 2025
259b2b0
feat: add neighborhood amenities as dropdowns (#5553)
KrissDrawing Nov 12, 2025
3773f9a
test: listing intro test (#5550)
emilyjablonski Nov 12, 2025
4414cdf
feat: marketing to months feature flag (#5542)
emilyjablonski Nov 12, 2025
7f09746
fix: update applications to have is_newest (#5526)
ludtkemorgan Nov 12, 2025
71dbe84
feat: Waitlist Lottery - Adjust Doorway Listing Type Filter (#5559)
millord Nov 13, 2025
53eb953
fix: neighborhood amenities update partners and public site copy (#5568)
KrissDrawing Nov 14, 2025
aa10ada
fix: upgrade ui-seeds for drawer scroll (#5570)
ludtkemorgan Nov 14, 2025
4f1ce05
Merge remote-tracking branch 'core/main' into release/2025-11-14
ludtkemorgan Nov 14, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,6 @@ module.exports = {
"**/.eslintrc.js",
"sentry-example-page.js",
"sentry-example-api.js",
"*.csv",
],
}
60 changes: 60 additions & 0 deletions .github/workflows/docker_image_build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Docker Image Build

on:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read
packages: write

env:
image_base: ghcr.io/${{ github.repository }}

jobs:
build-image:
# Builds each image in a separate job in parallel.
strategy:
matrix:
# The docker/build-push-action uses the git repo as the docker build context instead of
# cloning the repo to the action runner disk and using the disk context. For the API image
# we need to set the context to just the api/ directory which the '{{defaultContext}}:api'
# syntax does: https://github.com/docker/build-push-action?tab=readme-ov-file#git-context.
include:
- container: api
docker_context: "{{defaultContext}}:api"
dockerfile: Dockerfile
- container: partners
docker_context: "{{defaultContext}}"
dockerfile: Dockerfile.sites.partners
- container: public
docker_context: "{{defaultContext}}"
dockerfile: Dockerfile.sites.public
runs-on: ubuntu-latest
steps:
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3.6.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Required to use image layer cache.
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3.11.1

- name: "Build and push image"
uses: docker/build-push-action@v6.18.0
with:
push: true
cache-to: type=registry,mode=max,ref=${{ env.image_base }}/${{ matrix.container }}/container-layer-cache:latest
cache-from: type=registry,ref=${{ env.image_base }}/${{ matrix.container }}/container-layer-cache:latest
context: ${{ matrix.docker_context }}
file: ${{ matrix.dockerfile }}
tags: |
${{ env.image_base }}/${{ matrix.container }}:latest
${{ env.image_base }}/${{ matrix.container }}:gitsha-${{ github.sha }}
# Connects the image to the repository: https://docs.github.com/en/packages/learn-github-packages/connecting-a-repository-to-a-package.
labels: org.opencontainers.image.source=https://github.com/${{ github.repository }}
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,6 @@ dump.rdb
# Development planning files
memory-bank/
.github/copilot-instructions.md

# Terraform providers
.terraform
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ ui-components/CHANGELOG.md
sites/public/CHANGELOG.md
sites/partners/CHANGELOG.md
shared-helpers/CHANGELOG.md
backend/core/CHANGELOG.md
*.csv
25 changes: 25 additions & 0 deletions Dockerfile.sites.partners
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Keep up to date with Active LTS: https://nodejs.org/en/about/previous-releases
FROM node:22@sha256:23c24e85395992be118734a39903e08c8f7d1abc73978c46b6bda90060091a49

# Create a non-root user to build and run (principle of least privilege).
WORKDIR /app
RUN groupadd --gid 2002 next && useradd --gid 2002 --uid 2002 --home /app next
RUN chown 2002:2002 /app
USER 2002:2002

# Copy package.json and yarn.lock in a separate layer from the source code and install the
# dependencies. This allows docker to cache this step if dependencies haven't changed from the last
# docker build, making build times a lot faster.
COPY --chown=2002:2002 package.json yarn.lock .
COPY --chown=2002:2002 shared-helpers ./shared-helpers
COPY --chown=2002:2002 sites/partners/package.json ./sites/partners/
WORKDIR /app/sites/partners
RUN yarn install --frozen-lockfile

# Copy in the source code. `next build` needs the tsconfig.json at repo root for type
# checking.
COPY --chown=2002:2002 tsconfig.json /app/tsconfig.json
COPY --chown=2002:2002 sites/partners .

ENV NEXT_TELEMETRY_DISABLED=1
CMD [ "/bin/bash", "-c", "yarn build && yarn start" ]
25 changes: 25 additions & 0 deletions Dockerfile.sites.public
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Keep up to date with Active LTS: https://nodejs.org/en/about/previous-releases
FROM node:22@sha256:23c24e85395992be118734a39903e08c8f7d1abc73978c46b6bda90060091a49

# Create a non-root user to build and run (principle of least privilege).
WORKDIR /app
RUN groupadd --gid 2002 next && useradd --gid 2002 --uid 2002 --home /app next
RUN chown 2002:2002 /app
USER 2002:2002

# Copy package.json and yarn.lock in a separate layer from the source code and install the
# dependencies. This allows docker to cache this step if dependencies haven't changed from the last
# docker build, making build times a lot faster.
COPY --chown=2002:2002 package.json yarn.lock .
COPY --chown=2002:2002 shared-helpers ./shared-helpers
COPY --chown=2002:2002 sites/public/package.json ./sites/public/
WORKDIR /app/sites/public
RUN yarn install --frozen-lockfile

# Copy in the source code. `next build` needs the tsconfig.json at repo root for type
# checking.
COPY --chown=2002:2002 tsconfig.json /app/tsconfig.json
COPY --chown=2002:2002 sites/public .

ENV NEXT_TELEMETRY_DISABLED=1
CMD [ "/bin/bash", "-c", "yarn build && yarn start" ]
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ You can also run each process individually from separate terminals with the foll

We have a number of default users seeded for local development, the most basic of which being (email: `admin@example.com`, password: `abcdef`) which will login to both the public and partners sites, but you can view other default seeded users and their permissions by checking out the user section of the [seed file](https://github.com/bloom-housing/bloom/blob/aed77bf06525be359ef9205044fabbea2ab2576d/api/prisma/seed-staging.ts#L67).

### Running locally in docker

Docker documentation is in [docker.md](./docker.md).

### Bloom UIC development

Because Bloom's ui-components package is a separate open source repository, developing in Bloom while concurrently iterating in ui-components requires linking the folders with the following steps:
Expand Down
2 changes: 2 additions & 0 deletions api/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ LOTTERY_PUBLISH_PROCESSING_CRON_STRING=58 23 * * *
LOTTERY_PROCESSING_CRON_STRING=0 * * * *
# how many days till lottery data expires
LOTTERY_DAYS_TILL_EXPIRY=45
# how many days until application PII data exists
APPLICATION_DAYS_TILL_EXPIRY=
# the list of allowed urls that can make requests to the api (strings must be exact matches)
CORS_ORIGINS=["http://localhost:3000", "http://localhost:3001"]
# spill over list of allowed urls that can make requests to the api (strings are turned into regex)
Expand Down
81 changes: 53 additions & 28 deletions api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,31 +1,56 @@

# Base image
FROM node:18

# Create working directory
WORKDIR /usr/src/api

# Copy package.json
COPY package.json ./

# Copy yarn.lcok
COPY yarn.lock ./

# run yarn install
RUN yarn install

# Copy source code into docker image
COPY . .

# Copy .env
COPY .env ./

# run build commands
# Keep up to date with Active LTS: https://nodejs.org/en/about/previous-releases
#
# IMPORTANT: keep the 'run' layer below in sync.
FROM node:22@sha256:23c24e85395992be118734a39903e08c8f7d1abc73978c46b6bda90060091a49 AS build


# Create a non-root user to build (principle of least privilege).
WORKDIR /build
RUN groupadd --gid 2002 build && useradd --gid 2002 --uid 2002 --home /build build
RUN chown 2002:2002 /build
USER 2002:2002

# Install only runtime dependencies into a separate directory. This will be copied into the runner
# image.
WORKDIR /build/runtime_dependencies
COPY --chown=2002:2002 package.json yarn.lock ./
RUN yarn install --frozen-lockfile --production

# Copy package.json and yarn.lock in a separate layer from the source code and install the
# dependencies. This allows docker to cache this step if package.json and yarn.lock haven't changed
# from the last docker build, making build times a lot faster.
WORKDIR /build
COPY --chown=2002:2002 package.json yarn.lock ./
RUN yarn install --frozen-lockfile

# Copy the source code and build.
COPY --chown=2002:2002 . .
RUN yarn prisma generate
RUN yarn build

# Expose port 3100 for api
EXPOSE 3100

# Start api
CMD ["yarn", "dev"]
# Start a new container filesystem and copy in just the runtime dependencies and the built
# application.
#
# IMPORTANT: keep the 'build' layer above in sync.
FROM node:22@sha256:23c24e85395992be118734a39903e08c8f7d1abc73978c46b6bda90060091a49 AS run
WORKDIR /run

# Copy over build artifacts.
COPY --from=build /build/runtime_dependencies/ .
COPY --from=build /build/dist ./dist

# Need to copy the prisma schema file and generated package from `yarn prisma generate`.
# TODO: be explicit about where the client package is generated:
# https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/generating-prisma-client
COPY --from=build /build/prisma/schema.prisma ./prisma/schema.prisma
COPY --from=build /build/prisma/migrations ./prisma/migrations
COPY --from=build /build/node_modules/.prisma ./node_modules/.prisma

# Create a non-root user to run (priciple of least priviledge).
WORKDIR /run
RUN groupadd --gid 2002 run && useradd --gid 2002 --uid 2002 --home /run run
RUN chown --recursive 2002:2002 /run
USER 2002:2002

# Run any DB migrations then start the server.
CMD [ "/bin/bash", "-c", "yarn db:migration:run && yarn start:prod" ]
21 changes: 21 additions & 0 deletions api/Dockerfile.dbseed
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Keep up to date with Active LTS: https://nodejs.org/en/about/previous-releases
FROM node:22 AS build

# Create a non-root user to build (priciple of least priviledge).
WORKDIR /dbseed
RUN groupadd --gid 2002 dbseed && useradd --gid 2002 --uid 2002 --home /dbseed dbseed
RUN chown 2002:2002 /dbseed
USER 2002:2002

# Copy package.json and yarn.lock in a separate layer from the source code and install the
# dependencies. This allows docker to cache this step if package.json and yarn.lock haven't changed
# from the last docker build, making build times a lot faster.
WORKDIR /build
COPY --chown=2002:2002 package.json yarn.lock ./
RUN yarn install --frozen-lockfile

# Copy the source code and generate the prisma client.
COPY --chown=2002:2002 . .
RUN yarn prisma generate

CMD [ "yarn", "db:seed:staging" ]
6 changes: 6 additions & 0 deletions api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ These tests will mock Prisma and therefore will not interface directly with the

#### How to run unit tests

The tests require the TIME_ZONE environment variable to be set. Create a `.env` file:

```bash
echo 'TIME_ZONE=America/Los_Angeles' > .env
```

Running the following will run all unit tests: `yarn test`

### Testing with code coverage
Expand Down
10 changes: 5 additions & 5 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
"test:cov": "yarn db:resetup && yarn db:migration:run && jest --config ./test/jest-with-coverage.config.js --logHeapUsage",
"test:cov-ci": "yarn db:migration:run && jest --config ./test/jest-with-coverage.config.js --runInBand --logHeapUsage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"db:resetup": "psql -c 'DROP DATABASE IF EXISTS bloom_prisma WITH (FORCE);' && psql -c 'CREATE DATABASE bloom_prisma;' && psql -d bloom_prisma -c 'CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\";'",
"db:resetup": "psql -c \"DROP DATABASE IF EXISTS bloom_prisma WITH (FORCE);\" && psql -c \"CREATE DATABASE bloom_prisma;\" && psql -d bloom_prisma -c \"CREATE EXTENSION IF NOT EXISTS \\\"uuid-ossp\\\";\"",
"db:migration:run": "yarn prisma migrate deploy",
"db:seed:production": "npx prisma db seed -- --environment production",
"db:seed:staging": "npx prisma db seed -- --environment staging",
"db:seed:staging": "npx prisma db seed -- --environment staging --jurisdictionName Bloomington",
"db:seed:development": "npx prisma db seed -- --environment development --jurisdictionName Bloomington",
"generate:client": "ts-node scripts/generate-axios-client.ts && prettier -w ../shared-helpers/src/types/backend-swagger.ts",
"test:e2e": "yarn db:resetup && yarn db:migration:run && jest --config ./test/jest-e2e.config.js",
Expand All @@ -48,7 +48,7 @@
"@nestjs/schedule": "^4.1.1",
"@nestjs/swagger": "^7.4.2",
"@nestjs/throttler": "^5.1.2",
"@prisma/client": "^5.0.0",
"@prisma/client": "^5.3.0",
"@sendgrid/helpers": "^8.0.0",
"@sendgrid/mail": "7.7.0",
"@turf/boolean-point-in-polygon": "6.5.0",
Expand All @@ -66,7 +66,7 @@
"cookie-parser": "~1.4.6",
"cron": "^3.1.7",
"dayjs": "~1.11.9",
"dotenv": "^16.4.5",
"dotenv": "^17.2.3",
"exceljs": "^4.4.0",
"express": "^4.21.1",
"handlebars": "~4.7.8",
Expand All @@ -76,7 +76,7 @@
"passport": "~0.6.0",
"passport-jwt": "~4.0.1",
"passport-local": "~1.0.0",
"prisma": "^5.0.0",
"prisma": "^5.3.0",
"qs": "~6.11.2",
"reflect-metadata": "~0.1.13",
"rimraf": "^3.0.2",
Expand Down
80 changes: 80 additions & 0 deletions api/prisma/migrations/34_msq_corrections/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
-- AlterEnum
BEGIN;
CREATE TYPE "multiselect_questions_status_enum_new" AS ENUM ('draft', 'visible', 'active', 'toRetire', 'retired');
ALTER TABLE "multiselect_questions" ALTER COLUMN "status" DROP DEFAULT;
ALTER TABLE "multiselect_questions" ALTER COLUMN "status" TYPE "multiselect_questions_status_enum_new" USING ("status"::text::"multiselect_questions_status_enum_new");
ALTER TYPE "multiselect_questions_status_enum" RENAME TO "multiselect_questions_status_enum_old";
ALTER TYPE "multiselect_questions_status_enum_new" RENAME TO "multiselect_questions_status_enum";
DROP TYPE "multiselect_questions_status_enum_old";
COMMIT;

-- AlterTable
ALTER TABLE "multiselect_questions" ALTER COLUMN "status" SET DEFAULT 'draft';

-- The following Drops have to do with mapping ApplicationSelections and ApplicationSelectionsOptions to snake_case naming

-- DropForeignKey
ALTER TABLE "ApplicationSelectionOptions" DROP CONSTRAINT "ApplicationSelectionOptions_address_holder_address_id_fkey";

-- DropForeignKey
ALTER TABLE "ApplicationSelectionOptions" DROP CONSTRAINT "ApplicationSelectionOptions_application_selection_id_fkey";

-- DropForeignKey
ALTER TABLE "ApplicationSelectionOptions" DROP CONSTRAINT "ApplicationSelectionOptions_multiselect_option_id_fkey";

-- DropForeignKey
ALTER TABLE "ApplicationSelections" DROP CONSTRAINT "ApplicationSelections_application_id_fkey";

-- DropForeignKey
ALTER TABLE "ApplicationSelections" DROP CONSTRAINT "ApplicationSelections_multiselect_question_id_fkey";

-- DropTable
DROP TABLE "ApplicationSelectionOptions";

-- DropTable
DROP TABLE "ApplicationSelections";

-- CreateTable
CREATE TABLE "application_selection_options" (
"id" UUID NOT NULL DEFAULT uuid_generate_v4(),
"created_at" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(6) NOT NULL,
"address_holder_address_id" UUID,
"address_holder_name" TEXT,
"address_holder_relationship" TEXT,
"application_selection_id" UUID NOT NULL,
"is_geocoding_verified" BOOLEAN,
"multiselect_option_id" UUID NOT NULL,

CONSTRAINT "application_selection_options_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "application_selections" (
"id" UUID NOT NULL DEFAULT uuid_generate_v4(),
"created_at" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" TIMESTAMP(6) NOT NULL,
"application_id" UUID NOT NULL,
"has_opted_out" BOOLEAN,
"multiselect_question_id" UUID NOT NULL,

CONSTRAINT "application_selections_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "application_selection_options_address_holder_address_id_key" ON "application_selection_options"("address_holder_address_id");

-- AddForeignKey
ALTER TABLE "application_selection_options" ADD CONSTRAINT "application_selection_options_address_holder_address_id_fkey" FOREIGN KEY ("address_holder_address_id") REFERENCES "address"("id") ON DELETE NO ACTION ON UPDATE NO ACTION;

-- AddForeignKey
ALTER TABLE "application_selection_options" ADD CONSTRAINT "application_selection_options_application_selection_id_fkey" FOREIGN KEY ("application_selection_id") REFERENCES "application_selections"("id") ON DELETE NO ACTION ON UPDATE NO ACTION;

-- AddForeignKey
ALTER TABLE "application_selection_options" ADD CONSTRAINT "application_selection_options_multiselect_option_id_fkey" FOREIGN KEY ("multiselect_option_id") REFERENCES "multiselect_options"("id") ON DELETE NO ACTION ON UPDATE NO ACTION;

-- AddForeignKey
ALTER TABLE "application_selections" ADD CONSTRAINT "application_selections_application_id_fkey" FOREIGN KEY ("application_id") REFERENCES "applications"("id") ON DELETE NO ACTION ON UPDATE NO ACTION;

-- AddForeignKey
ALTER TABLE "application_selections" ADD CONSTRAINT "application_selections_multiselect_question_id_fkey" FOREIGN KEY ("multiselect_question_id") REFERENCES "multiselect_questions"("id") ON DELETE NO ACTION ON UPDATE NO ACTION;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- AlterEnum
ALTER TYPE "listings_review_order_type_enum" ADD VALUE 'waitlistLottery';
Loading
Loading