Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
d3c3319
minor(modeling-commons): load zod async
omargfh Jun 2, 2026
482d90c
chore(modeling-commons): remove reka-ui, update yarn.lock
omargfh Jun 2, 2026
0aeaaba
chore(modeling-commons): fix all failing type checks
omargfh Jun 5, 2026
e58f2c9
chore(modeling-commons): clean up
omargfh Jun 5, 2026
d04b543
ci(modeling-commons): initial implementation of CI testing
omargfh Jun 8, 2026
e82a06d
minor(modeling-commons): remove (now) irrelevant ts-expect-error
omargfh Jun 8, 2026
7b2e13c
ci(modeling-commons): supply s3.json to seaweed for testing/developme…
omargfh Jun 8, 2026
2f86bf1
ci(modeling-commons): prevent pending work from failing CI
omargfh Jun 8, 2026
4236b9d
ci(modeling-commons): add caching to test CI, fix wrong health endpoint
omargfh Jun 8, 2026
8bf7058
ci(modeling-commons): cache node_modules
omargfh Jun 8, 2026
1883333
ci(modeling-commons): unblock e2e tests on frontend
omargfh Jun 8, 2026
99f64ef
ci(modeling-commons): install e2e browser in CI, reuse frontend build…
omargfh Jun 8, 2026
cac1996
ci(modeling-commons): Use cached Chromium over reinstalling
omargfh Jun 10, 2026
e10e813
Minor(modeling-commons): Add loading spinner to Author and Tag filters
omargfh Jun 10, 2026
6f44d3d
ci(modeling-commons): parameterize build with GitHub environments
omargfh Jun 10, 2026
2485ffe
ci(modeling-commons): cache node_modules in build workflow
omargfh Jun 11, 2026
aa12fea
ci(modeling-commons): run frontend e2e tests separately to avoid timeout
omargfh Jun 11, 2026
754cdd1
test(modeling-commons): fix flaky auth e2e by gating on hydration
omargfh Jun 12, 2026
fe70aed
ci(modeling-commons): use correct turbo cache
omargfh Jun 12, 2026
2407e24
chore: update yarn.lock
omargfh Jun 15, 2026
b572900
ci(modeling-commons): source env vars in frontend docker from ci
omargfh Jun 15, 2026
b848dc7
ci(modeling-commons): use a Debian image for frontend
omargfh Jun 15, 2026
f4cdadc
ci(modeling-commons): add Turbo cache to build workflow
omargfh Jun 15, 2026
d27804a
minor(modeling-commons): enable IPX as image provider
omargfh Jun 15, 2026
c112ac4
Bugfix(modeling-commons): fix sharp/IPX native binary in frontend image
omargfh Jun 15, 2026
c9ae5da
Minor(modeling-commons): use phrasing 'authored in' over 'written in'
omargfh Jun 17, 2026
ef0e465
Minor(modeling-commons): use consistent 'Log In' copy
omargfh Jun 17, 2026
9f446e4
Minor(modeling-commons): use warmer contact us copy for errors
omargfh Jun 17, 2026
ae4333f
Minor(modeling-commons): better copy for donate headline
omargfh Jun 17, 2026
ebc8ddb
Minor(modeling-commons): Add 'make a donation' button
omargfh Jun 17, 2026
74ceac4
Minor(modeling-commons): Use more informative error message for faile…
omargfh Jun 17, 2026
4434876
Chore(modeling-commons): Update cucumber test reports
omargfh Jun 17, 2026
3cc3509
ci(modeling-commons): Allow one (test and deploy) workflow run at a time
omargfh Jun 17, 2026
97d2515
Minor(modeling-commons): Make upload button more prominent
omargfh Jun 17, 2026
a71467b
Minor(modeling-commons): Remove public visibility badges from models
omargfh Jun 17, 2026
6fa8907
Minor(modeling-commons): Make logo larger in navigation bar
omargfh Jun 17, 2026
f76d593
Minor(modeling-commons): Grey out unimplemented version comparison bu…
omargfh Jun 17, 2026
71cb332
Minor(modeling-commons): Hide text scrollbar in Embed dialog
omargfh Jun 17, 2026
447a659
Minor(modeling-commons): Use h4 only for tags pages headers and add n…
omargfh Jun 17, 2026
601f949
Minor(modeling-commons): Remove iframe from Markdown embed code
omargfh Jun 17, 2026
4806488
Minor(modeling-commons): Add "clear" button to search fields selection
omargfh Jun 17, 2026
4554b8c
Minor(modeling-commons): Remove UUID prefix from filenames
omargfh Jun 18, 2026
4fc969b
Minor(modeling-commons): Use random avatar image names for privacy
omargfh Jun 18, 2026
1b880f5
Bugfix(modeling-commons): Disable scroll lock for action menu
omargfh Jun 18, 2026
4a9e39a
Minor(modeling-commons): Add "My Models" to Navbar
omargfh Jun 18, 2026
ccd1df0
Minor(modeling-commons): Remove unused 'Skip for Now' from onboarding
omargfh Jun 18, 2026
647680f
Feature(modeling-commons): Add back to top component
omargfh Jun 18, 2026
8749e6f
Feature(modeling-commons): Add back to top to model lists
omargfh Jun 18, 2026
8500baa
Bugfix(modeling-commons): remove passkey from plugin types on backend
omargfh Jun 18, 2026
32d6e7c
Bugfix(modeling-commons): treat legacy sign up as password reset
omargfh Jun 18, 2026
125fa46
ci(modeling-commons): add more comprehensive seed data
omargfh Jun 18, 2026
fecb71e
Bugfix(modeling-commons): Fix double file open dialog bug on upload
omargfh Jun 18, 2026
0453041
Bugfix(modeling-commons): Fix twitchy search bar in models page
omargfh Jun 18, 2026
ff75959
Bugfix(modeling-commons): Set profile avatars fetch dimensions
omargfh Jun 18, 2026
ad88d7f
Copy(modeling-commons): Show "Private Model" in social media preview …
omargfh Jun 18, 2026
e1cfab4
Bugfix(modeling-commons): use public ACL image previews for uploads
omargfh Jun 18, 2026
45b78f0
Bugfix(modeling-commons): Prevent 500 flash on sign-out from profile …
omargfh Jun 18, 2026
a7fbdd9
test(modeling-commons): Add Mailpit helper for e2e email retrieval
omargfh Jun 22, 2026
0990cbe
test(modeling-commons): Un-gate verified-user e2e journeys via Mailpit
omargfh Jun 22, 2026
0573562
Bugfix(modeling-commons): Flush pending draft autosave before leaving…
omargfh Jun 22, 2026
931d555
minor(modeling-commons): rem timeout in e2e tests
omargfh Jun 22, 2026
de98457
feat(modeling-commons): Add ModelFileKind and drop dead ModelVersionF…
omargfh Jun 22, 2026
bd7bc6c
feat(modeling-commons): Thread file kind through the model-additional…
omargfh Jun 22, 2026
948deb0
feat(modeling-commons): Patch current version on metadata-only draft …
omargfh Jun 22, 2026
99fe0ca
test(modeling-commons): Cover draft publish branching and kind/seeded…
omargfh Jun 22, 2026
7fa6d30
test(modeling-commons): Un-pend versioning e2e scenarios and assert f…
omargfh Jun 22, 2026
1893b8b
feat(modeling-commons): Route model-file vs additional uploads by role
omargfh Jun 22, 2026
7898dbc
test(modeling-commons): Add frontend kind-routing and model-edit e2e …
omargfh Jun 22, 2026
cbc0bca
test(modeling-commons): align seeded-draft publish e2e with metadata-…
omargfh Jun 22, 2026
73cd597
Bugfix(modeling-commons): Return 413 for oversized uploads instead of…
omargfh Jun 22, 2026
e58997b
test(modeling-commons): Add backend upload-validation, tags, and prev…
omargfh Jun 22, 2026
ab4de4b
test(modeling-commons): Add composable coverage for format gate, extr…
omargfh Jun 22, 2026
e35ff0d
docs(modeling-commons): Record draft-publish testing and prisma clien…
omargfh Jun 22, 2026
f1ffd1c
feat(modeling-commons): Group Files tab by kind with linked version b…
omargfh Jun 23, 2026
1d32722
Minor(modeling-commons): Update confirm dialog to better sizing
omargfh Jun 23, 2026
329f60f
chore(modeling-commons): update API types
omargfh Jun 23, 2026
9e38826
feat(modeling-commons): Seed only model files into drafts so addition…
omargfh Jun 23, 2026
d45f2ac
Bugfix(modeling-commons): Return displayName from the version-tags route
omargfh Jun 23, 2026
17e0991
feat(modeling-commons): Edit model files inline and lock additional f…
omargfh Jun 23, 2026
b0618db
feat(modeling-commons): Show only latest-version model files on the F…
omargfh Jun 23, 2026
59bb651
test(modeling-commons): Cover model-file editor upload and stabilize …
omargfh Jun 23, 2026
729be9d
Bugfix(modeling-commons): Filter Files tab model files to the viewed …
omargfh Jun 23, 2026
8ece9d0
Bugfix(modeling-commons): Gate the editor until the draft hydrates
omargfh Jun 23, 2026
5bcfdf8
lint(modeling-commons): Add missing type annotations
omargfh Jun 23, 2026
3157de8
lint(modeling-commons): resolve linter errors
omargfh Jun 23, 2026
93453c5
Bugfix(modeling-commons): Fix empty context menu via payload cache
omargfh Jun 23, 2026
a56b55e
Feat(commons): Add auto-converter script
omargfh Jun 24, 2026
05d4f92
ui(commons): Minor responsiveness changes
omargfh Jun 24, 2026
9deff6a
test(commons): Remove disabled pages from smoke test
omargfh Jun 24, 2026
60d7055
Bugfix(commons): Fix like button rendering twice on sm+ screens
omargfh Jun 25, 2026
d71a3ec
Bugfix(commons): Recompute action menu when permissions resolve
omargfh Jun 25, 2026
13e1cff
Bugfix(commons): Prevent double publish causing dual success/failure …
omargfh Jun 25, 2026
fb6ce08
Bugfix(commons): Remove duplicate password reset notification
omargfh Jun 25, 2026
eb2834b
Bugfix(commons): Fix tag search suggestions in model editor
omargfh Jun 25, 2026
42329ba
Feat(commons): Add delete model button gated by canDelete permission
omargfh Jun 25, 2026
eb9e532
Bugfix(commons): Match model error view CTAs to error type
omargfh Jun 25, 2026
00525e2
Bugfix(commons): Replace broken Go Back button on inaccessible profiles
omargfh Jun 25, 2026
e4d3292
Feat(commons): Hard-delete model drafts on model soft-delete
omargfh Jun 26, 2026
630dec0
Feat(commons): Warn that drafts are deleted in delete-model dialog
omargfh Jun 26, 2026
eca2082
Minor(commons): Enhance visual hierarchy of delete model dialog
omargfh Jun 26, 2026
d661917
Minor(commons): add changeSummary to ModelVersion table
omargfh Jun 26, 2026
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
71 changes: 53 additions & 18 deletions .github/workflows/build-and-push-modeling-commons.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,16 @@ on:
- 'yarn.lock'
- '.github/workflows/build-and-push-modeling-commons.yml'
workflow_dispatch:
workflow_call:
inputs:
environment:
required: true
type: string

jobs:
build-and-push:
runs-on: ubuntu-latest
environment: netlogo1
environment: ${{ inputs.environment || 'modeling-commons-production' }}
permissions:
contents: read
packages: write
Expand All @@ -39,31 +44,49 @@ jobs:
node-version: '24'
cache: yarn

- uses: actions/cache@v4
with:
path: .turbo
key: ${{ runner.os }}-turbo-${{ hashFiles('yarn.lock') }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-turbo-${{ hashFiles('yarn.lock') }}-
${{ runner.os }}-turbo-

- uses: actions/cache@v4
with:
path: |
node_modules
apps/*/node_modules
packages/*/node_modules
key: node-modules-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
restore-keys: |
node-modules-${{ runner.os }}-

- name: Install dependencies
run: yarn run init
env:
HELIO_SKIP_CHECKS: '1'
NUXT_TELEMETRY_DISABLED: '1'
HELIO_SKIP_CHECKS: ${{ vars.HELIO_SKIP_CHECKS }}
NUXT_TELEMETRY_DISABLED: ${{ vars.NUXT_TELEMETRY_DISABLED }}

- name: Build backend
run: yarn workspace modeling-commons-backend fastify:build
env:
HELIO_HEADLESS: 1
HELIO_HEADLESS: ${{ vars.HELIO_HEADLESS }}

- name: Build frontend
working-directory: apps/modeling-commons-frontend
run: yarn nuxt:build
env:
HELIO_HEADLESS: 1
NUXT_TELEMETRY_DISABLED: 1
NODE_OPTIONS: --max-old-space-size=4096
NUXT_PUBLIC_AUTH_BASE: 'https://beta.modelingcommons.org/api/auth'
NUXT_PUBLIC_API_BASE: 'https://beta.modelingcommons.org'
NUXT_PUBLIC_APP_URL: 'https://beta.modelingcommons.org'
NUXT_STORAGE_BASE_URL: 'https://cdn.modelingcommons.org'
NUXT_PUBLIC_CDN_URL: 'https://cdn.modelingcommons.org'
NUXT_PUBLIC_NETLOGO_WEB_URL: 'https://www.netlogoweb.org'
NUXT_PUBLIC_GA_TRACKING_ID: 'G-VJ4WPV2Q5B'
HELIO_HEADLESS: ${{ vars.HELIO_HEADLESS }}
NUXT_TELEMETRY_DISABLED: ${{ vars.NUXT_TELEMETRY_DISABLED }}
NODE_OPTIONS: ${{ vars.NODE_OPTIONS }}
NUXT_PUBLIC_AUTH_BASE: ${{ vars.NUXT_PUBLIC_AUTH_BASE }}
NUXT_PUBLIC_API_BASE: ${{ vars.NUXT_PUBLIC_API_BASE }}
NUXT_PUBLIC_APP_URL: ${{ vars.NUXT_PUBLIC_APP_URL }}
NUXT_STORAGE_BASE_URL: ${{ vars.NUXT_STORAGE_BASE_URL }}
NUXT_PUBLIC_CDN_URL: ${{ vars.NUXT_PUBLIC_CDN_URL }}
NUXT_PUBLIC_NETLOGO_WEB_URL: ${{ vars.NUXT_PUBLIC_NETLOGO_WEB_URL }}
NUXT_PUBLIC_GA_TRACKING_ID: ${{ vars.NUXT_PUBLIC_GA_TRACKING_ID }}

- uses: docker/setup-buildx-action@v3

Expand All @@ -89,7 +112,7 @@ jobs:
push: true
tags: |
${{ steps.repo_slug.outputs.result }}/modeling-commons-backend:${{ github.sha }}
${{ steps.repo_slug.outputs.result }}/modeling-commons-backend:latest
${{ steps.repo_slug.outputs.result }}/modeling-commons-backend:${{ vars.VARIANT_IMAGE_TAG }}
cache-from: type=gha
cache-to: type=gha,mode=max

Expand All @@ -101,15 +124,27 @@ jobs:
push: true
tags: |
${{ steps.repo_slug.outputs.result }}/modeling-commons-frontend:${{ github.sha }}
${{ steps.repo_slug.outputs.result }}/modeling-commons-frontend:latest
${{ steps.repo_slug.outputs.result }}/modeling-commons-frontend:${{ vars.VARIANT_IMAGE_TAG }}
build-args: |
NUXT_PUBLIC_API_BASE=${{ vars.NUXT_PUBLIC_API_BASE }}
NUXT_PUBLIC_AUTH_BASE=${{ vars.NUXT_PUBLIC_AUTH_BASE }}
NUXT_PUBLIC_APP_URL=${{ vars.NUXT_PUBLIC_APP_URL }}
NUXT_STORAGE_BASE_URL=${{ vars.NUXT_STORAGE_BASE_URL }}
NUXT_PUBLIC_CDN_URL=${{ vars.NUXT_PUBLIC_CDN_URL }}
NUXT_PUBLIC_NETLOGO_WEB_URL=${{ vars.NUXT_PUBLIC_NETLOGO_WEB_URL }}
NUXT_PUBLIC_GA_TRACKING_ID=${{ vars.NUXT_PUBLIC_GA_TRACKING_ID }}
cache-from: type=gha
cache-to: type=gha,mode=max

restart-deployments:
needs: build-and-push
runs-on: self-hosted
environment: ${{ inputs.environment || 'modeling-commons-production' }}

steps:
- name: Restart deployments
env:
KUBE_NAMESPACE: ${{ vars.KUBE_NAMESPACE }}
run: |
APISERVER=https://kubernetes.default.svc
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
Expand All @@ -123,5 +158,5 @@ jobs:
-H "Content-Type: application/strategic-merge-patch+json" \
-d "$PATCH" \
--cacert "$CA" \
"$APISERVER/apis/apps/v1/namespaces/modeling-commons/deployments/$DEPLOY"
done
"$APISERVER/apis/apps/v1/namespaces/$KUBE_NAMESPACE/deployments/$DEPLOY"
done
159 changes: 159 additions & 0 deletions .github/workflows/test-modeling-commons.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
name: Test Modeling Commons

on:
push:
branches: [main, staging/modeling-commons]
paths:
- 'apps/modeling-commons-backend/**'
- 'apps/modeling-commons-frontend/**'
- 'packages/modeling-commons-shared/**'
- 'packages/typescript-config/**'
- 'packages/tailwind-config/**'
- 'packages/nuxt-core/**'
- 'packages/vue-ui/**'
- 'packages/markdown/**'
- 'packages/eslint-config/**'
- 'packages/utils/**'
- 'packages/common-data/**'
- 'packages/template/**'
- 'packages/nuxt-content-assets/**'
- 'packages/netlogo-docs/**'
- 'packages/emails/**'
- 'yarn.lock'
- '.github/workflows/build-and-push-modeling-commons.yml'
- '.github/workflows/test-modeling-commons.yml'
workflow_dispatch:

concurrency:
group: modeling-commons-testing
cancel-in-progress: true

jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
environment: netlogo1
permissions:
contents: read
packages: read

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: '24'
cache: yarn

- uses: actions/cache@v4
with:
path: .turbo
key: ${{ runner.os }}-turbo-${{ hashFiles('yarn.lock') }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-turbo-${{ hashFiles('yarn.lock') }}-
${{ runner.os }}-turbo-

- uses: actions/cache@v4
with:
path: |
node_modules
apps/*/node_modules
packages/*/node_modules
key: node-modules-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
restore-keys: |
node-modules-${{ runner.os }}-

- name: Install dependencies
run: yarn run init
env:
HELIO_SKIP_CHECKS: '1'
NUXT_TELEMETRY_DISABLED: '1'

- name: Build backend
run: yarn workspace modeling-commons-backend fastify:build
env:
HELIO_HEADLESS: 1

- name: Run services
run: docker compose -f docker-compose.dev.yml up -d --wait
working-directory: apps/modeling-commons-backend

- name: Seed the services
run: yarn run db:migrate:dev && yarn run db:seed
working-directory: apps/modeling-commons-backend

- name: Run backend tests
run: yarn run test
working-directory: apps/modeling-commons-backend

- name: Run backend server
run: node dist/src/index.ts &
timeout 30 bash -c 'until curl -sf http://localhost:3000/api/health; do sleep 1; done'
working-directory: apps/modeling-commons-backend

- name: Get Playwright version
id: pw-version
run: echo "version=$(npx playwright --version)" >> "$GITHUB_OUTPUT"

- uses: actions/cache@v4
id: playwright
with:
path: ~/.cache/ms-playwright
key: playwright-${{ runner.os }}-${{ steps.pw-version.outputs.version }}

- name: Install Playwright browser
if: steps.playwright.outputs.cache-hit != 'true'
run: yarn run e2e:install-browser
working-directory: apps/modeling-commons-frontend

- name: Build frontend
run: yarn run nuxt:build
working-directory: apps/modeling-commons-frontend
env:
NUXT_TELEMETRY_DISABLED: '1'

- name: Run frontend server
run: node .output/server/index.mjs &
timeout 60 bash -c 'until curl -sf http://localhost:3005/ >/dev/null; do sleep 1; done'
working-directory: apps/modeling-commons-frontend
env:
PORT: '3005'
NODE_OPTIONS: --dns-result-order=ipv4first

# Split the suite so e2e doesn't share the runner's 2 cores with the other
# five in-process projects (plus Chromium).
# -- Omar Ibrahim, Jun 11 26
- name: Run in-process frontend tests
run: yarn run test:in-process
working-directory: apps/modeling-commons-frontend

# E2E runs against the already-built server (E2E_HOST), so the e2e project
# skips its per-file Nuxt build.
# -- Omar Ibrahim, Jun 11 26
- name: Run frontend e2e tests
run: yarn run test:e2e
working-directory: apps/modeling-commons-frontend
env:
E2E_HOST: http://localhost:3005
E2E_ARTIFACT_DIR: ${{ runner.temp }}/e2e-artifacts
MAILPIT_URL: http://localhost:8025

# Failure-only net: on a failed e2e run, upload the screenshot + HTML that
# dumpOnFailure captured at the point of failure.
- name: Upload e2e failure artifacts
if: failure()
uses: actions/upload-artifact@v4
with:
name: e2e-failure-artifacts
if-no-files-found: ignore
path: ${{ runner.temp }}/e2e-artifacts

- if: always()
run: docker compose -f docker-compose.dev.yml down -v
working-directory: apps/modeling-commons-backend

deploy-staging:
needs: test
uses: ./.github/workflows/build-and-push-modeling-commons.yml
with:
environment: modeling-commons-staging
4 changes: 3 additions & 1 deletion apps/modeling-commons-backend/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Reference modules: `src/modules/model/` (full shape), `src/modules/event/` (read
- Soft delete, don't hard delete: models/users carry `deletedAt`. Call `modelDomain.assertNotDeleted(entity)` before mutating.
- **Models are written through drafts**, not directly. Flow: `POST /v1/model-drafts` → `PATCH /v1/model-drafts/:id` → multipart upload to `/v1/model-drafts/:id/files` → `POST /v1/model-drafts/:id/publish`. There is no `POST /v1/models`. Publish auto-creates `v1`; a model never has zero versions.
- `POST /v1/models/:id/versions` is **multipart/form-data** (required `file` field), not JSON.
- Draft data persists as versioned JSON validated by compiled Typebox `Parse` (`model-draft/schemas/v1.ts`); its `Clean` step strips properties absent from the schema, so add any new draft field to the schema or it's silently dropped on the next read.

## Routes

Expand All @@ -49,7 +50,7 @@ Reference modules: `src/modules/model/` (full shape), `src/modules/event/` (read
Use path aliases, never relative `../../`:

- `#src/...` - app source
- `#prisma/index` - generated Prisma client (output is `generated/prisma`, not `@prisma/client`)
- `#prisma/index` - generated Prisma client (output is `generated/prisma`, not `@prisma/client`). It's committed — after editing `schema.prisma` run `yarn db:generate` and commit the regenerated client alongside the migration.

## Client/request context

Expand All @@ -72,6 +73,7 @@ Use path aliases, never relative `../../`:
## Testing

- `yarn run test:unit` (vitest) · `yarn run test:e2e` (cucumber, needs `yarn run svc` running for postgres/object-storage/mailpit/netlogo-services).
- `test:unit` is fully mocked (no DB); apply pending migrations before `test:e2e` (`yarn run db:migrate:dev`) — an unapplied migration makes the generated client mismatch the DB and 500s every affected route. Diagnose e2e failures from `reports/cucumber-report.json`.
- In vitest specs, import `beforeEach`/`afterEach` from `vitest`, never `node:test` — wrong import silently no-ops the hook.

## Config & limits
Expand Down
Loading
Loading