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
23 changes: 9 additions & 14 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
{
"name": "Redux .NET Dev Container",
"image": "mcr.microsoft.com/dotnet/sdk:10.0",
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {
"username": "vscode",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hate running stuff as root, even in a container, which is why this was in there.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am agnostic on this, we can switch it back.

"installZsh": false,
"upgradePackages": false
}
"image": "mcr.microsoft.com/devcontainers/dotnet:10.0",
"//appPort": "Publishes 27000 to the host via `docker -p`, so it works from a plain terminal (devcontainer CLI), not just VS Code forwarding. The API binds 0.0.0.0 (see the mise `run` task).",
"appPort": [27000],
"portsAttributes": {
"27000": { "label": "Redux API", "onAutoForward": "notify" }
},
"postCreateCommand": "bash .devcontainer/post-create.sh",
"remoteUser": "vscode",
"customizations": {
"vscode": {
"extensions": [
"ms-dotnettools.csharp"
]
"extensions": ["ms-dotnettools.csharp"]
}
},
"postStartCommand": "if [ \"$(stat -c %U /workspaces/Redux)\" != \"vscode\" ]; then sudo chown -R vscode:vscode /workspaces/Redux; fi",

@wrigjl wrigjl Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this was in there because of line 6.

"postCreateCommand": "dotnet --list-sdks"
}
}
}
21 changes: 21 additions & 0 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Post-create for the Redux devcontainer.
#
# The .NET 10 runtime comes from the base image. This script only layers in mise
# (the unified task runner) and restores NuGet packages so the container is ready
# to `mise run build|test|run`. See CLAUDE.md "Toolchain layering (DECIDED)".
set -euo pipefail

# 1. Install mise if the base image doesn't already provide it.
if ! command -v mise >/dev/null 2>&1; then
curl -fsSL https://mise.run | sh
fi
MISE="${HOME}/.local/bin/mise"

# 2. Activate mise for future interactive shells.
ACTIVATE="eval \"\$(${MISE} activate bash)\""
grep -qF "${ACTIVATE}" "${HOME}/.bashrc" 2>/dev/null || echo "${ACTIVATE}" >> "${HOME}/.bashrc"

# 3. Trust this repo's mise.toml, then warm the NuGet cache via the shared task.
"${MISE}" trust
"${MISE}" run restore
13 changes: 12 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@ By submitting a contribution (pull request, patch, or code submission), you conf

## How to Contribute

### Development environment

The easiest way to develop is the **dev container**: it provides the correct .NET 10 toolchain
and a shared `mise run <task>` command set, so you install nothing on your host and your
environment matches CI. Open the repo in VS Code (**Reopen in Container**) or run
`devcontainer up` from a terminal. See **Quick Start → Recommended: Dev Container** in the
[README](./Readme.md) for full setup.

Inside the container: `mise run run` starts the API on `http://localhost:27000`, and
`mise run test` runs the full test suite.

### 1. Fork the repository
Create your own fork of the project.

Expand All @@ -40,7 +51,7 @@ Use a descriptive branch name:

### 4. Test your changes
- Ensure the project builds successfully
- Run any existing tests
- Run any existing tests (`mise run test` in the dev container)
- Add tests if applicable

### 5. Submit a Pull Request (PR)
Expand Down
51 changes: 51 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,57 @@ The backend is designed to be adaptable and can work with different frontends. T

## Quick Start

The recommended path is the **dev container** (below): it needs only a container runtime and
gives everyone the same .NET 10 toolchain. Prefer to install toolchains on your host instead?
Skip to [Prerequisites](#prerequisites).

### Recommended: Dev Container

The dev container pins the .NET 10 SDK and a shared task runner ([mise](https://mise.jdx.dev/))
so VS Code, a plain terminal, and CI all build and test the same way. **No local .NET SDK or
Node.js is required for backend work** — the container provides them.

**Dependencies**

- [Docker](https://docs.docker.com/get-docker/) (or a compatible container runtime), and
- one of:
- **VS Code** + the [Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) (or a [GitHub Codespace](https://github.com/features/codespaces)), or
- the [`@devcontainers/cli`](https://github.com/devcontainers/cli) for terminal-based editors (neovim, etc.): `npm install -g @devcontainers/cli` (needs Node.js on your host).

**VS Code / Codespaces**

Open the repo and choose **Reopen in Container**. The first build restores packages
automatically; then use the tasks below from the integrated terminal.

**Terminal (devcontainer CLI)**

```bash
# create/start the container (first run pulls the image + restores packages)
devcontainer up --workspace-folder .

# run tasks inside it
devcontainer exec --workspace-folder . mise run test # restore -> build -> test
devcontainer exec --workspace-folder . mise run run # API on http://localhost:27000
```

**Tasks** — the same `mise run <task>` names work in VS Code, the terminal, and CI:

| Task | What it does |
|------|--------------|
| `mise run restore` | Restore NuGet packages |
| `mise run build` | Build the solution (Release) |
| `mise run test` | Restore → build → test (mirrors CI) |
| `mise run run` | Run the API on http://localhost:27000 (Swagger at `/swagger/index.html`) |
| `mise run watch` | Run the API with hot reload |

Port **27000** is published to your host, so a browser or the
[Redux_GUI](https://github.com/ReduxISU/Redux_GUI) frontend can reach the API at
`http://localhost:27000` while you develop.

> **Working on the GUI too (e.g. a reduction)?** Run this backend container, then start the
> frontend separately and point its `REDUX_BASE_URL` at `http://localhost:27000/`. The two are
> independent containers wired over HTTP — you do not need both in one container.

### Prerequisites

- [.NET 10 SDK](https://dotnet.microsoft.com/en-us/download)
Expand Down
35 changes: 35 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# mise — one task vocabulary across the Redux repos (`mise run build|test|run|watch`),
# so C#, Python, and JS repos share the same commands.
#
# There is intentionally NO [tools] section: the .NET 10 runtime is provided by the
# devcontainer base image, not mise. mise is the task layer only. See CLAUDE.md

@wrigjl wrigjl Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

your claude is showing...

# "Toolchain layering (DECIDED)".
#
# Every task names Redux.slnx explicitly — a bare `dotnet` at the repo root errors
# MSB1011 because API.csproj and Redux.slnx sit side by side (same reason CI does).

[tasks.restore]
description = "Restore NuGet packages"
run = "dotnet restore Redux.slnx"

[tasks.build]
description = "Build the solution (Release)"
depends = ["restore"]
run = "dotnet build Redux.slnx --no-restore --configuration Release"

[tasks.test]
description = "Run unit tests (restore -> build -> test, matching CI)"
depends = ["build"]
run = "dotnet test Redux.slnx --no-restore --no-build --configuration Release"

[tasks.run]
description = "Run the API on http://localhost:27000 (Development + Swagger)"
# Bind via ASPNETCORE_URLS, NOT `--urls`: `dotnet run` treats `--urls` as an unknown
# run option and exits before the app starts. 0.0.0.0 so the published port is reachable.
env = { ASPNETCORE_URLS = "http://0.0.0.0:27000" }

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably fine in a container, but we need to fix the use of 0.0.0.0 outside of containers so that folks aren't opening up dev stuff on their LAN.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this is all meant for container usage

run = "dotnet run --project API.csproj"

[tasks.watch]
description = "Run the API with hot reload on :27000"
env = { ASPNETCORE_URLS = "http://0.0.0.0:27000" }
run = "dotnet watch --project API.csproj run"