Skip to content
Open
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
33 changes: 33 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "NanoForge editor",
"image": "mcr.microsoft.com/devcontainers/base:bookworm",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "26"
},
"ghcr.io/devcontainers-extra/features/bun:1": {
"version": "1.3.14"
}
},
"postCreateCommand": "corepack enable && corepack prepare pnpm@12.0.0 --activate && pnpm install && pnpm --filter @nanoforge-dev/editor exec playwright install --with-deps chromium firefox && pnpm setup:check",
"forwardPorts": [5174, 4800],
"portsAttributes": {
"4800": {
"label": "Example (pnpm example)"
},
"5174": {
"label": "Editor (pnpm dev)"
}
},
"customizations": {
"vscode": {
"extensions": [
"svelte.svelte-vscode",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"vitest.explorer",
"ms-playwright.playwright"
]
}
}
}
98 changes: 67 additions & 31 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,34 +1,70 @@
# production | development
NODE_ENV=development
# The editor server reads these variables (Bun also loads a .env file of the folder it
# starts in). Copy this file to .env and uncomment what you change.
# Generated from packages/server-core/src/env/env.schema.ts: run
# `pnpm --filter @nanoforge-dev/editor-server-core generate:env` after changing it.

# OFFLINE: local projects on disk (binds to 127.0.0.1). ONLINE: hosted, projects synced with git gateways.
PUBLIC_MODE=OFFLINE
# production, development (more logs, dev tooling) or test.
# NODE_ENV=production

# Server. In OFFLINE mode HOST must be a loopback address (no sign-in, project code runs),
# unless ALLOW_REMOTE_OFFLINE=1 and something else restricts who can connect.
# HOST=127.0.0.1
# OFFLINE: local projects on disk. ONLINE: hosted, projects synced with git gateways.
# PUBLIC_MODE=OFFLINE

# Address the server listens on. In OFFLINE mode it must be a loopback address (no sign-in,
# project code runs), unless ALLOW_REMOTE_OFFLINE is set.
# HOST=

# Port the server listens on (0: any free port).
# PORT=3000

# Projects must live under this directory (defaults to the working directory).
# FS_ROOT=

# Editor data: recent projects, installed plugins… (defaults to ~/.nanoforge/editor).
# DATA_DIR=

# The NanoForge API.
# API_URL=https://api.nanoforge.eu

# The editor's key for the NanoForge API: required in ONLINE mode.
# API_KEY=

# The API features that are deployed, comma separated (settings,registry). None by default.
# API_FEATURES=

# The registry of plugins and packages, when it is not the API's (registry feature).
# REGISTRY_URL=

# A folder standing in for the registry (<dir>/@scope/name/<version>/): tests, offline work.
# REGISTRY_DIR=

# NanoForge projects website, where ONLINE users sign in.
# PUBLIC_PM_URL=https://projects.nanoforge.eu

# Signs the session cookies. Empty: a random one at each start (sessions end on restart).
# SESSION_SECRET=

# The NanoForge CLI, when nf is not in the PATH (a project's own CLI is tried first).
# NF_CLI_PATH=

# Git, when git is not in the PATH.
# GIT_PATH=

# Extra origins allowed to call the server (dev proxies).
# ALLOWED_ORIGINS=

# Host names the server answers to besides localhost (DNS rebinding guard), comma separated.
# A local editor reached by another name needs it; a hosted one checks it when it is set.
# ALLOWED_HOSTS=

# Directories of local plugins under development (their dist/ is served).
# DEV_PLUGINS=

# Directory of the plugins bundled with the editor build.
# BUNDLED_PLUGINS_DIR=

# Files of the tutorial's project (_Help › Tutorial_), when not next to the editor build.
# TUTORIAL_DIR=

# Lets a local (OFFLINE) editor listen on a non-loopback HOST. It has no sign-in and runs
# project code: only set it behind something that restricts who can connect.
# ALLOW_REMOTE_OFFLINE=
PORT=3000

# Projects must live under this directory (default: current directory)
FS_ROOT=
# Editor data (recent projects, installed plugins). Default: ~/.nanoforge/editor
DATA_DIR=

# NanoForge API (API_KEY required when PUBLIC_MODE=ONLINE)
API_URL=https://api.nanoforge.eu
API_KEY=
# Where ONLINE users sign in (the website sets the auth cookies)
PUBLIC_PM_URL=https://projects.nanoforge.eu

# Leave empty to generate a random secret at start (sessions are lost on restart)
SESSION_SECRET=

# Change if the binaries are not in the PATH (nf: the project's own node_modules/.bin is tried first)
NF_CLI_PATH=
GIT_PATH=

# Comma separated list of local plugin folders under development (their dist/ is served, hot reloaded)
DEV_PLUGINS=
# Extra origins allowed to call the server (reverse proxies)
ALLOWED_ORIGINS=
4 changes: 2 additions & 2 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ If you wish to contribute to the NanoForge project, fork the repository and subm
To get ready to work on the codebase, please do the following:

1. Fork & clone the repository, and make sure you're on the **main** branch
2. Run `pnpm install --frozen-lockfile` ([install](https://pnpm.io/installation))
3. Copy `.env.example` to `.env` and modify env variable as you wish
2. Run `pnpm install --frozen-lockfile` ([install](https://pnpm.io/installation)), then `pnpm setup:check`: it says what else is missing (Bun, Chrome, a built engine for the tests that play games: `pnpm setup:engine`)
3. Optionally, copy `.env.example` to `.env`: every variable is listed there, commented out with its default; uncomment what you change
4. Run the editor `pnpm run dev`
5. Make your changes
6. Run `pnpm format && pnpm build && pnpm test` to run ESLint/Prettier, build and tests
Expand Down
34 changes: 34 additions & 0 deletions .github/actions/playwright-install/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: 'Install Playwright browsers'
description: 'Install Playwright browsers, cached by Playwright version'
inputs:
browsers:
description: 'Browsers to install, separated by spaces'
default: 'chromium'
filter:
description: 'Workspace whose Playwright installs them'
default: '@nanoforge-dev/editor'
runs:
using: 'composite'
steps:
- name: Read the Playwright version
id: version
shell: bash
run: echo "version=$(pnpm --filter '${{ inputs.filter }}' exec playwright --version | awk '{print $2}')" >> "$GITHUB_OUTPUT"

- uses: actions/cache@v5
id: cache
name: Cache browsers
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-${{ steps.version.outputs.version }}-${{ inputs.browsers }}

- name: Install browsers
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
run: pnpm --filter '${{ inputs.filter }}' exec playwright install --with-deps ${{ inputs.browsers }}

# The browsers come from the cache; their system libraries do not.
- name: Install system libraries
if: steps.cache.outputs.cache-hit == 'true'
shell: bash
run: pnpm --filter '${{ inputs.filter }}' exec playwright install-deps ${{ inputs.browsers }}
10 changes: 10 additions & 0 deletions .github/actions/prepare/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ runs:
name: Install dependencies
uses: ./.github/actions/pnpm-install

# Turbo's local cache, shared by the jobs of a run and kept between runs of a branch.
- name: Cache turbo
uses: actions/cache@v5
with:
path: .turbo/cache
key: ${{ runner.os }}-turbo-${{ github.ref_name }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-turbo-${{ github.ref_name }}-
${{ runner.os }}-turbo-

- if: inputs.build == 'true'
name: Build packages
shell: bash
Expand Down
59 changes: 56 additions & 3 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ on:
permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
e2e:
runs-on: ubuntu-latest
Expand All @@ -32,34 +36,83 @@ jobs:
- name: Prepare
uses: ./.github/actions/prepare

# The engine and CLI the tests play and build with: scripts/pinned-refs.json, also read
# by pnpm setup:engine. Move them on purpose, after a run against the new commits passes.
- name: Read the pinned engine and CLI
shell: bash
run: |
echo "ENGINE_REF=$(jq -r .engine.ref scripts/pinned-refs.json)" >> "$GITHUB_ENV"
echo "CLI_REF=$(jq -r .cli.ref scripts/pinned-refs.json)" >> "$GITHUB_ENV"

# The tests that play a game (runtime, inspectors, scene…) need a built engine with the
# editor library; without NANOFORGE_ENGINE they are skipped.
# editor library, and the tutorial a built CLI. E2E_REQUIRE_ENGINE fails the run when
# one is missing instead of skipping them.
- name: Cache engine and CLI
id: cache
uses: actions/cache@v5
with:
path: |
engine
cli
key: ${{ runner.os }}-engine-${{ env.ENGINE_REF }}-cli-${{ env.CLI_REF }}

- name: Checkout engine
if: steps.cache.outputs.cache-hit != 'true'
uses: actions/checkout@v7
with:
repository: NanoForge-dev/Engine
ref: main
ref: ${{ env.ENGINE_REF }}
path: engine

- name: Install emsdk
if: steps.cache.outputs.cache-hit != 'true'
uses: ./engine/.github/actions/emsdk-install

- name: Install engine dependencies
if: steps.cache.outputs.cache-hit != 'true'
uses: ./.github/actions/pnpm-install
with:
path: engine

- name: Build engine
if: steps.cache.outputs.cache-hit != 'true'
run: pnpm run build
working-directory: engine

- name: Checkout CLI
if: steps.cache.outputs.cache-hit != 'true'
uses: actions/checkout@v7
with:
repository: NanoForge-dev/CLI
ref: ${{ env.CLI_REF }}
path: cli

- name: Install CLI dependencies
if: steps.cache.outputs.cache-hit != 'true'
uses: ./.github/actions/pnpm-install
with:
path: cli

- name: Build CLI
if: steps.cache.outputs.cache-hit != 'true'
run: |
pnpm --filter @nanoforge-dev/config build
pnpm --filter @nanoforge-dev/schematics build
pnpm build
working-directory: cli

- name: Install browsers
run: pnpm --filter @nanoforge-dev/editor exec playwright install --with-deps chromium firefox
uses: ./.github/actions/playwright-install
with:
browsers: firefox

- name: Run end-to-end tests
run: pnpm --filter @nanoforge-dev/editor test:e2e
env:
CHROME: /usr/bin/google-chrome
NANOFORGE_ENGINE: ${{ github.workspace }}/engine
NANOFORGE_CLI: ${{ github.workspace }}/cli
E2E_REQUIRE_ENGINE: '1'

- name: Upload traces
if: failure()
Expand Down
16 changes: 16 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,30 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v7
with:
fetch-depth: 0

# A pull request that changes no code (docs, CI, issue forms) publishes no beta.
- name: Check for code changes
id: changes
shell: bash
run: |
if git diff --name-only "${{ github.event.pull_request.merge_commit_sha }}^" "${{ github.event.pull_request.merge_commit_sha }}" \
| grep -qE '^(apps|packages|plugins|tooling)/|^(pnpm-lock|pnpm-workspace)\.yaml$|^turbo\.json$'; then
echo "code=true" >> "$GITHUB_OUTPUT"
else
echo "code=false" >> "$GITHUB_OUTPUT"
fi

- name: Prepare
if: steps.changes.outputs.code == 'true'
uses: ./.github/actions/prepare
env:
NODE_ENV: development
PUBLIC_MODE: OFFLINE

- name: Release beta
if: steps.changes.outputs.code == 'true'
uses: ./node_modules/@nanoforge-dev/actions/actions/release-dev
with:
package: '@nanoforge-dev/editor'
Expand Down
Loading
Loading