Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
16 changes: 9 additions & 7 deletions .github/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# GitHub Actions and CI

This folder defines automation for the BC Digital Trust Showcase monorepo (`frontend` and `server` Yarn workspaces). All Node-based jobs use **Node.js 22**, matching `engines.node` in `package.json`.
This folder defines automation for the BC Digital Trust Showcase monorepo (`frontend` and `server` Yarn workspaces). All Node-based jobs use **Node.js 24.19.0**, matching the repository's supported Node 24.x LTS line.

## Composite action: `actions/setup-node`

**Path:** `.github/actions/setup-node/action.yml`

**Purpose:** Install Node and enable Yarn dependency caching in one step.
**Purpose:** Install Node, activate the repository's Yarn version through Corepack, and cache Yarn dependencies.

**Inputs:**

Expand All @@ -16,14 +16,16 @@ This folder defines automation for the BC Digital Trust Showcase monorepo (`fron

**Behaviour:**

- Runs [`actions/setup-node@v4`](https://github.com/actions/setup-node) with `cache: yarn` and `cache-dependency-path: yarn.lock` (repository root). No separate `actions/cache` step and no `yarn` invocation before Node is installed.
- Runs [`actions/setup-node@v4`](https://github.com/actions/setup-node) without Yarn caching so the runner's global Yarn version is not invoked during setup.
- Enables Corepack, installs and verifies Yarn `4.18.0`, then caches the Yarn cache directory with a key containing the OS, Node version, Yarn version, and `yarn.lock` hash.
- The cache key intentionally does not restore the previous `setup-node` Yarn cache; the old entry is left for GitHub's normal eviction policy.

**Usage:**

```yaml
- uses: ./.github/actions/setup-node
with:
node-version: 22
node-version: 24.19.0
```

---
Expand All @@ -41,8 +43,8 @@ This folder defines automation for the BC Digital Trust Showcase monorepo (`fron

| Job | What it does |
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Server Unit Tests** | `yarn install --frozen-lockfile`, then `yarn workspace server test` |
| **Frontend Unit Tests** | `yarn install --frozen-lockfile`, then `yarn workspace frontend test:unit` |
| **Server Unit Tests** | `yarn install --immutable`, then `yarn workspace server test` |
| **Frontend Unit Tests** | `yarn install --immutable`, then `yarn workspace frontend test:unit` |
| **Cypress E2E Tests** | Lint (`yarn lint`), Prettier check, `yarn check-types`, then Cypress with `yarn workspace frontend start` and `wait-on` for `http://localhost:3000` |

---
Expand Down Expand Up @@ -72,7 +74,7 @@ This folder defines automation for the BC Digital Trust Showcase monorepo (`fron

### Job graph

1. **`cypress-run`** (conditional) — Only when manual **`workflow_dispatch`** sets `run_cypress: true`. Checks out the repo, uses `setup-node` (Node 22), runs `yarn install --frozen-lockfile`, starts `yarn dev` in the background, waits with `wait-on` for `http://localhost:3000` and `http://localhost:5000`, short warm-up sleep, then runs **Cypress** (`cypress-io/github-action@v6`, `install: false`, optional Dashboard recording via `CYPRESS_RECORD_KEY`).
1. **`cypress-run`** (conditional) — Only when manual **`workflow_dispatch`** sets `run_cypress: true`. Checks out the repo, uses `setup-node`, runs `yarn install --immutable` followed by `yarn cypress install`, starts `yarn dev` in the background, waits with `wait-on` for `http://localhost:3000` and `http://localhost:5000`, short warm-up sleep, then runs **Cypress** (`cypress-io/github-action@v6`, optional Dashboard recording via `CYPRESS_RECORD_KEY`).

2. **`cypress-skipped`** — On **release** publish (E2E skipped) or manual dispatch with `run_cypress: false`. Satisfies `needs` for the image jobs without doing work.

Expand Down
21 changes: 18 additions & 3 deletions .github/actions/setup-node/action.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Setup NodeJS
description: Setup NodeJS with caching
description: Setup NodeJS with Corepack and Yarn caching
author: 'timo@animo.id'

inputs:
Expand All @@ -14,8 +14,23 @@ runs:
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ inputs.node-version }}
cache: yarn
cache-dependency-path: yarn.lock
- name: Enable Corepack
shell: bash
run: |
corepack enable
corepack install --global yarn@4.18.0
- name: Verify Yarn version
shell: bash
run: test "$(yarn --version)" = "4.18.0"
- name: Get Yarn cache directory
id: yarn-cache-dir
shell: bash
run: echo "dir=$(yarn config get cacheFolder)" >> "$GITHUB_OUTPUT"
- name: Cache Yarn dependencies
uses: actions/cache@v4
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: yarn-${{ runner.os }}-node-${{ inputs.node-version }}-yarn-4.18.0-${{ hashFiles('yarn.lock') }}

branding:
icon: scissors
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/build_packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ jobs:
- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
node-version: 22
node-version: 24.19.0

- name: Start App
run: |
yarn install --frozen-lockfile --network-timeout 600000
yarn install --immutable --network-timeout 600000
yarn cypress install
NODE_ENV=test VITE_HOST_BACKEND=http://localhost:5000 yarn dev &

- name: Wait for dev servers (HTTP)
Expand All @@ -57,7 +58,6 @@ jobs:
- name: Cypress run
uses: cypress-io/github-action@f790eee7a50d9505912f50c2095510be7de06aa7 # v6.10.9
with:
install: false
# Only record to Cypress Cloud when the repo/org secret is configured.
record: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
browser: chrome
Expand Down
20 changes: 11 additions & 9 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ jobs:
- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
node-version: 22
node-version: 24.19.0

- name: Install dependencies
run: yarn install --frozen-lockfile
run: yarn install --immutable

- name: Run server unit tests
run: yarn workspace server test
Expand All @@ -45,10 +45,10 @@ jobs:
- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
node-version: 22
node-version: 24.19.0

- name: Install dependencies
run: yarn install --frozen-lockfile
run: yarn install --immutable

- name: Run frontend unit tests
run: yarn workspace frontend test:unit
Expand All @@ -64,10 +64,10 @@ jobs:
- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
node-version: 22
node-version: 24.19.0

- name: Install dependencies
run: yarn install --frozen-lockfile
run: yarn install --immutable

- name: Linting
run: yarn lint
Expand All @@ -89,17 +89,19 @@ jobs:
- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
node-version: 22
node-version: 24.19.0

- name: Install dependencies
run: yarn install --frozen-lockfile
run: yarn install --immutable

- name: Install Cypress binary
run: yarn cypress install

# Cypress: only the Vite dev server is started. cypress.config.ts sets apiUrl to :5000 for
# specs that hit the API—if CI runs those, also start the server (e.g. concurrently) or align with build_packages.yml (yarn dev).
- name: Cypress run
uses: cypress-io/github-action@f790eee7a50d9505912f50c2095510be7de06aa7 # v6.10.9
with:
install: false
start: yarn workspace frontend start
wait-on: 'http://localhost:3000'
browser: chrome
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ typings/
# Yarn Integrity file
.yarn-integrity

# Yarn 4 install state
.yarn/

# dotenv environment variables file
.env
.env.test
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v22
v24.19.0
1 change: 1 addition & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
12 changes: 7 additions & 5 deletions DEVELOPER/BC Digital Trust Showcase.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ https://github.com/bcgov/BC-Wallet-Demo

The BC Digital Trust Showcase is an application used to issue demo credentials and proof requests. It consists of a React frontend and a TS-Node Backend. Additionally it needs to be connected to a traction agent.

The repository uses Yarn 4.18.0 through Corepack. Node.js 24.x LTS is required; local development is pinned to Node.js 24.19.0.

## Continuous integration

GitHub Actions run on pull requests (unit tests, lint, Cypress, Docker smoke builds) and on releases (optional Cypress, then publishing showcase images to GHCR). Node **22** is required in CI, matching the repo `engines` field. For workflow names, job graph, secrets used at Docker build time, and the reusable **setup-node** composite action, see **[.github/README.md](../.github/README.md)** in the repository.
GitHub Actions run on pull requests (unit tests, lint, Cypress, Docker smoke builds) and on releases (optional Cypress, then publishing showcase images to GHCR). Node **24.19.0** is used in CI, with Node **24.x** supported by the repo `engines` field. For workflow names, job graph, secrets used at Docker build time, and the reusable **setup-node** composite action, see **[.github/README.md](../.github/README.md)** in the repository.

## Setup: Local Development

Expand Down Expand Up @@ -60,7 +62,7 @@ VITE_BASE_ROUTE=/digital-trust/showcase
VITE_INSIGHTS_PROJECT_ID=
```

When adding environment variables for the **Vite** dev client, use the `VITE_` prefix (see `frontend/.env.example`). In production the app is static files behind Caddy; **Caddy** reads `VITE_BASE_ROUTE` (and related vars) at runtime from the same `frontend/.env` when using Docker Compose.
When adding environment variables for the **Vite** dev client, use the `VITE_` prefix (see `frontend/.env.example`). In production the app is static files behind Caddy. `VITE_BASE_ROUTE` is read by Caddy at container runtime from `frontend/.env`, while `VITE_HOST_BACKEND` and other Vite application values are embedded into the JavaScript bundle during the frontend image build. Changing those build-time values requires rebuilding the image.

Ensure that both the env files are named `.env` and that they're in the same folder as their respective `.env.example` files, otherwise they won't get loaded.

Expand Down Expand Up @@ -91,15 +93,15 @@ The structure is similar for the use case flow. Those screens are located at `fr
- StepInformation.tsx: like BasicSlide.tsx displays configured text and images to provide context for the proof.
- StepProof.tsx: issues the configured proof to the user's wallet

All of these steps are configurable via the JSON showcase files in `server/scripts/values` (`studentShowcase.json`, `lawyerShowcase.json`, `businessShowcase.json`), loaded by `server/src/content/Showcases.ts`
All of these steps are configurable via the JSON showcase files in `server/migrations/values` (`studentShowcase.json`, `lawyerShowcase.json`, `businessShowcase.json`), loaded by `server/src/content/Showcases.ts`.

### Server Structure:

For the most part the server acts as a sort of proxy to pass requests to the traction agent. There's some additional routes provided as well but for the most part it passes requests to the traction agent. The handlers for each route are all located in `server > src > controllers`.

### Server Config:

The showcase configurations live in `server/scripts/values/` as JSON files (`studentShowcase.json`, `lawyerShowcase.json`, `businessShowcase.json`). They are loaded by `server/src/content/Showcases.ts`. We'll walk through the structure and what the fields mean:
The showcase configurations live in `server/migrations/values/` as JSON files (`studentShowcase.json`, `lawyerShowcase.json`, `businessShowcase.json`). They are loaded by `server/src/content/Showcases.ts`. Credentials are defined in the same directory in `credentials.json`. We'll walk through the structure and what the fields mean:

#### Basic Character Info

Expand Down Expand Up @@ -195,7 +197,7 @@ The introduction sections follow a common structure. Key fields:
- `SETUP_START`: (required) second step — renders `SetupStart.tsx`
- `CHOOSE_WALLET`: (optional) renders `ChooseWallet.tsx`
- `CONNECT*`: creates a connection invitation and renders `SetupConnection.tsx`. `issuer_name` is the display name shown in the user's wallet.
- `ACCEPT*`: renders `AcceptCredential.tsx` and sends the credential offer. Must be preceded by a `CONNECT*` step. The `credentials` field is an array of credential IDs referencing entries in `server/config/credentials.json`. If the schema or cred def do not exist, the server requests Traction to create them.
- `ACCEPT*`: renders `AcceptCredential.tsx` and sends the credential offer. Must be preceded by a `CONNECT*` step. The `credentials` field is an array of credential IDs referencing entries in `server/migrations/values/credentials.json`. If the schema or cred def do not exist, the server requests Traction to create them.
- `SETUP_COMPLETED`: (required) last step — renders `SetupCompleted.tsx`
- `name`: the page title
- `text`: the main body text
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,14 @@ To also open the optional MongoDB web UI:
docker compose --profile dev --profile mongo-ui up --build
```

#### Native (Node.js 22+ and Yarn 1.x)
#### Native (Node.js 24.19.0 and Yarn 4.18.0)

Corepack is included with Node.js and manages the repository's pinned Yarn version. Enable it once before installing dependencies:

MongoDB must be running separately (e.g. `docker compose up mongodb`).

```bash
corepack enable
yarn install
yarn dev
```
Expand Down Expand Up @@ -90,7 +93,7 @@ docker build -f frontend/Dockerfile \
# Backend
docker build -f server/Dockerfile -t bc-wallet-demo-server:local .

# Production-like Compose stack (no Keycloak, no hot-reload)
# Production-like Compose stack (Keycloak included, no hot-reload)
docker compose --profile prod up --build
```

Expand Down
4 changes: 2 additions & 2 deletions dev.dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
FROM node:22-alpine AS base
FROM node:24.19.0-alpine AS base

WORKDIR /app
COPY . .
RUN yarn install
RUN corepack enable && yarn install --immutable


EXPOSE 5000
Expand Down
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,13 @@ services:
condition: service_healthy

seed:
image: node:22-alpine
image: node:24.19.0-alpine
profiles:
- dev
- prod
working_dir: /app
entrypoint: ['sh', '-c']
command: ['yarn install --frozen-lockfile --non-interactive && yarn workspace server seed']
command: ['corepack enable && yarn install --immutable && yarn workspace server seed']
restart: on-failure
volumes:
- ./:/app
Expand Down
2 changes: 1 addition & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export default tseslint.config(
},
},
{
files: ['frontend/vite.config.ts'],
files: ['frontend/vite.config.mts'],
rules: {
'import/no-unresolved': 'off',
'import/no-extraneous-dependencies': 'off',
Expand Down
14 changes: 7 additions & 7 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
# syntax=docker/dockerfile:1
ARG build_image=node:22-alpine
ARG build_image=node:24.19.0-alpine
ARG runtime_image=caddy:alpine

# build stage
FROM ${build_image} AS build-stage
WORKDIR /app
ENV HUSKY=0 \
YARN_NETWORK_CONCURRENCY=8
ENV HUSKY=0

# Install deps first so this layer stays cached unless a manifest/lockfile changes.
# The whole workspace is resolved against the root lockfile, so every member
# package.json must be present for `--frozen-lockfile` to succeed.
COPY package.json yarn.lock ./
# package.json must be present for `--immutable` to succeed.
COPY package.json yarn.lock .yarnrc.yml ./
COPY frontend/package.json ./frontend/
COPY server/package.json ./server/
RUN --mount=type=cache,target=/root/.cache/yarn \
yarn install --frozen-lockfile --network-timeout 600000 --non-interactive
RUN corepack enable
RUN --mount=type=cache,target=/root/.yarn/berry/cache \
yarn install --immutable --network-timeout 600000

# CI passes legacy secret names (REACT_APP_*). Map them to Vite env for `vite build`.
ARG REACT_APP_INSIGHTS_PROJECT_ID
Expand Down
8 changes: 3 additions & 5 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"license": "Apache-2.0",
"description": "BC Digital Trust Showcase - A showcase of how to use the BC Services Card app to prove things about yourself, in a way that's safe and secure.",
"engines": {
"node": ">=22"
"node": ">=24.0.0"
},
"dependencies": {
"@heroicons/react": "^2.2.0",
Expand Down Expand Up @@ -35,8 +35,8 @@
"socket.io-client": "^4.8.3"
},
"scripts": {
"start": "NODE_NO_WARNINGS=1 vite",
"build": "vite build",
"start": "NODE_NO_WARNINGS=1 vite --configLoader bundle",
"build": "vite build --configLoader bundle",
"preview": "vite preview",
"test": "vitest",
"test:unit": "vitest run",
Expand All @@ -50,8 +50,6 @@
"@types/lodash": "^4.17.25",
"@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0",
"@types/react-router": "^5.1.20",
"@types/react-router-dom": "^5.3.3",
"@vitejs/plugin-react": "^6.0.5",
"@vitest/coverage-v8": "^4.1.10",
"autoprefixer": "^10.5.4",
Expand Down
Loading
Loading