Skip to main content
Bloom uses GitHub Actions for CI. All workflows run on pull requests targeting main. Merging requires a passing CI run.

Workflows

The .github/workflows/ directory contains 15 workflow files:
Workflow fileNameTrigger
unit_tests_api.ymlBackend Unit TestsPR to main
integration_tests_api.ymlBackend IntegrationPR to main
unit_tests_sites_public.ymlPublic UnitPR to main
unit_tests_sites_partners.ymlPartners UnitPR to main
unit_tests_shared_helpers.ymlShared Helpers UnitPR to main
cypress_public.ymlPublic CypressPR to main
cypress_partners.ymlPartners CypressPR to main
cypress_partners_listingapproval.ymlPartners Cypress (LA)PR to main
lint.ymlLintPR to main
docker_compose_ci.ymlDocker Compose CIPush/PR to main
docker_image_build.ymlDocker Image BuildPush to main, manual
infra_ci.ymlInfra CIPush/PR to main (infra/)
gitleaks.ymlgitleaksEvery push
codeql.ymlCodeQLScheduled / PR
missing-translations.ymlMissing translationsPR to main
All application CI workflows (unit tests, integration tests, Cypress, lint) use paths-ignore: ['infra/**']. Infrastructure changes trigger the dedicated infra_ci.yml workflow instead.

Test workflows

API unit tests (unit_tests_api.yml)

Runs the NestJS unit test suite against the API.
  • Runner: ubuntu-latest, Node.js 22
  • No database required (mocked in unit tests)
  • Command: yarn test from ./api

API integration tests (integration_tests_api.yml)

Runs end-to-end API tests that exercise the full request/response cycle against a real PostgreSQL database.
  • Runner: ubuntu-latest, Node.js 22
  • Spins up a PostgreSQL service container
  • Command: yarn test:e2e from ./api
  • Key env vars: DATABASE_URL, TEST_DATABASE_URL, PORT=3100

Public site unit tests (unit_tests_sites_public.yml)

Runs the Jest unit test suite for sites/public.
  • Runner: ubuntu-latest, Node.js 22
  • Installs dependencies in root, sites/public
  • Command: yarn test:app:public:unit

Partners site unit tests (unit_tests_sites_partners.yml)

Runs the Jest unit test suite for sites/partners.
  • Runner: ubuntu-latest, Node.js 22
  • Installs dependencies in root, sites/public, sites/partners
  • Command: yarn test:app:partners:unit

Shared helpers unit tests (unit_tests_shared_helpers.yml)

Runs the unit tests for the shared-helpers package.
  • Runner: ubuntu-latest, Node.js 22
  • Command: yarn test:shared-helpers

Public site Cypress tests (cypress_public.yml)

Runs the full Cypress end-to-end test suite against the public site.
  • Runner: ubuntu-latest, Node.js 22
  • Starts a PostgreSQL service container, seeds the database
  • Builds the public site with yarn build, starts both the API and Next.js dev server
  • Waits for http://localhost:3100/jurisdictions before running tests
  • Uses cypress-io/github-action@v5

Partners site Cypress tests (cypress_partners.yml)

Runs the Cypress end-to-end suite for sites/partners covering the cypress/e2e/default/*.spec.ts test files.
  • Runner: ubuntu-latest, Node.js 22
  • Starts a PostgreSQL service container, seeds the database
  • Builds and starts the partners site and API
  • Waits for http://localhost:3100/

Partners Cypress — listing approval (cypress_partners_listingapproval.yml)

A separate Cypress job for the partners site that runs listing-approval-specific tests (cypress/e2e/listings-approval/*.spec.ts) with FEATURE_LISTINGS_APPROVAL=TRUE.

Linting

The lint.yml workflow runs ESLint and Prettier on every PR to main:
yarn install
yarn lint

Docker workflows

Docker Compose CI (docker_compose_ci.yml)

Runs on every push and PR to main. Validates the full Docker Compose stack by running several smoke tests in sequence:
  1. builddocker compose build --no-cache
  2. dbinitcheck — Runs dbinit twice to verify idempotency (the init script must succeed on both a fresh and an already-initialized database).
  3. api-smoke-test — Starts the API with docker compose up --wait api and checks it becomes healthy.
  4. dbreadonlycheck — Runs the readonly DB check using the ci Compose profile.
  5. sites-smoke-test — Starts the full stack and curls both http://127.0.0.1:3000 and http://127.0.0.1:3001 to confirm the sites are accessible.

Docker image build (docker_image_build.yml)

Runs on every push to main (and can be triggered manually). Builds and pushes all container images to the GitHub Container Registry (ghcr.io) in parallel using a build matrix:
ContainerDockerfilePlatforms
apiapi/Dockerfilelinux/amd64
dbseedapi/Dockerfile.dbseedlinux/amd64
dbinitapi/dbinit/Dockerfilelinux/amd64
partnersDockerfile.sites.partnerslinux/amd64
publicDockerfile.sites.publiclinux/amd64
infrainfra/Dockerfilelinux/amd64, linux/arm64
infra-devinfra/Dockerfile.devlinux/amd64, linux/arm64
Each image is tagged with both latest and gitsha-<sha>. Layer caching is stored in the registry to speed up subsequent builds.

Infrastructure CI (infra_ci.yml)

Runs on pushes to main and on PRs that modify infra/** or the workflow file itself. Verifies that all OpenTofu files are correctly formatted:
tofu fmt -check -diff -recursive
Runs via the ghcr.io/bloom-housing/bloom/infra-dev container image.

Secret scanning with GitLeaks

The gitleaks.yml workflow runs on every push (not just PRs) using GitLeaks. It scans the full git history (fetch-depth: 0) for accidentally committed secrets such as API keys, tokens, and passwords.
- name: run gitleaks scan
  uses: gitleaks/gitleaks-action@v2
GitLeaks requires a GITLEAKS_LICENSE secret to be configured in the repository for use beyond the free tier.

Dependency updates with Dependabot

Dependabot is configured in .github/dependabot.yml to scan npm dependencies weekly across all packages in the monorepo:
DirectoryDescription
/Root workspace dependencies
/apiAPI dependencies
/shared-helpersShared helpers package
/sites/publicPublic site dependencies
/sites/partnersPartners site dependencies

Update grouping

Dependabot groups minor and patch updates into a single weekly PR to reduce noise:
  • minor-versions group — All minor and patch version updates are combined into one PR per scan cycle.
  • minor-security group — Minor and patch security updates are similarly grouped.
  • Major version upgrades — Not grouped; each gets its own PR so the breaking change can be reviewed in isolation.

Cypress Cloud

Cypress test runs record to Cypress Cloud when enabled. Recording is disabled by default:
record: false # set this value to true to record videos in cypress cloud
             # for debugging purposes - skip passing tests
To enable recording for a run, set record: true in the relevant workflow file. The CYPRESS_RECORD_KEY for each site (PUBLIC_CYPRESS_RECORD_KEY, PARTNERS_CYPRESS_RECORD_KEY) must be configured as a repository secret.

Branch protection

The main branch is protected. Pull requests must have all required CI checks pass before merging. The following checks are effectively required by the workflow configuration:
  • Backend Unit Tests
  • Backend Integration
  • Public Unit / Partners Unit / Shared Helpers Unit
  • Public Cypress / Partners Cypress / Partners Cypress (LA)
  • Lint
  • Docker Compose CI
  • GitLeaks

Conventional commits

Commit messages are validated against the Conventional Commits specification via commitlint. This enforces a consistent commit history and enables automated changelog generation.

Build docs developers (and LLMs) love