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
25 changes: 22 additions & 3 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
<!--
PR title must follow Conventional Commits (enforced by CI, and it becomes
the changelog entry via release-please):

type(scope): short description

- type: feat | fix | docs | style | refactor | perf | test | build | ci | chore | revert
- scope: optional, e.g. the app or feature area you touched
- description: lowercase, imperative mood ("add PNG export", not "Added PNG export")

Examples:
feat(stats): add PNG export for charts
fix: correct datepicker padding in production build
-->

## Summary

<!-- What does this change and why? -->
<!-- What does this PR do and why? A few sentences is enough. -->

## How to test

<!-- Steps to verify the change. For UI changes, add a screenshot. -->

## Related issues
---

<!-- Closes #123, Refs #456 -->
<!-- Does this close any open issues? Use "Closes #123" if so. -->
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -420,3 +420,7 @@ CLAUDE.md
AGENTS.md
DESIGN.md
.claude/

# Lefthook local overrides (personal, not shared)
.lefthook-local.yml
lefthook-local.yml
43 changes: 43 additions & 0 deletions .lefthook.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Lefthook Git Hooks Configuration
min_version: 1.9.0
assert_lefthook_installed: true
colors: true
output:
- summary
- execution
- execution_out
- execution_info

pre-commit:
parallel: true
commands:
dotnet-fmt:
glob: "*.cs"
run: dotnet csharpier check .
fail_text: "C# formatting issues found! Run 'just format-dotnet' to fix them"

ts-lint:
root: "clients/typescript/"
glob: "*.{ts,tsx,js,jsx,json}"
run: deno task lint
fail_text: "Linting failed! Run 'cd clients/typescript && deno task lint' to see errors"

ts-fmt:
root: "clients/typescript/"
glob: "*.{ts,tsx,js,jsx,json}"
run: deno task fmt
fail_text: "Formatting issues found! Run 'just format-ts' to fix them"

pre-push:
parallel: true
commands:
dotnet-build:
glob: "*.{cs,csproj,sln}"
run: dotnet build JsonApiToolkit.sln --configuration Release
fail_text: "Build failed! Run 'dotnet build JsonApiToolkit.sln' to see errors"

ts-check:
root: "clients/typescript/"
glob: "*.{ts,tsx,js,jsx}"
run: deno task check
fail_text: "Type checking failed! Run 'cd clients/typescript && deno task check' to see errors"
28 changes: 24 additions & 4 deletions docs/contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,42 @@

## Prerequisites

- .NET 10 SDK
- .NET 10 SDK, [Deno](https://deno.com) 2.x, [just](https://github.com/casey/just), [lefthook](https://lefthook.dev)
(all pinned in `mise.toml`; run `mise install` if you use [mise](https://mise.jdx.dev))
- `uv` for the docs site (`brew install uv` or `mise use uv`)

## Setup

```bash
dotnet tool restore # csharpier + dotnet-api-docs
dotnet restore
just setup # dotnet tool restore, dotnet restore, lefthook install
```

This installs git hooks (lefthook) that format-check on commit and type-check
on push; see `.lefthook.yml`. CI (`ci-cd.yml`, `typescript-ci.yml`,
`contract-tests.yml`) is still the source of truth and runs the full suites.

## Daily Commands

Run `just` (no arguments) to list all recipes, or `just --list`.

```bash
just format # format .NET + TypeScript
just check # format-check + type-check everything, no fixes
just test # .NET tests + TypeScript unit tests, in parallel
just test-contract # build & run samples/ContractApi, run the Deno contract suite against it
just test-all # check + test + test-contract (what CI runs)
```

Narrower recipes (`format-dotnet`, `format-ts`, `test-dotnet`, `test-ts`,
`lint`, `clean`) are also available; see the `justfile`.

Equivalent plain commands, if you don't have `just`:

```bash
dotnet build --configuration Release
dotnet test --configuration Release
dotnet csharpier format .
dotnet csharpier format .
cd clients/typescript && deno task test
```

## Docs
Expand Down
134 changes: 134 additions & 0 deletions justfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
set dotenv-load := false

sample := "samples/ContractApi"
ts := "clients/typescript"

# List available recipes
default:
@just --list

# ---------------------------------------------------------------------------
# Setup
# ---------------------------------------------------------------------------

# Full bootstrap: dotnet tools/packages, git hooks
[group('setup')]
setup: tools restore hooks
@echo "Setup complete. Run 'just test' to verify everything works."

# Restore local dotnet tools (csharpier)
[group('setup')]
tools:
dotnet tool restore

# Restore NuGet packages
[group('setup')]
restore:
dotnet restore --locked-mode

# Install lefthook git hooks
[group('setup')]
hooks:
lefthook install

# ---------------------------------------------------------------------------
# Quality
# ---------------------------------------------------------------------------

# Format all code (.NET + TypeScript) in parallel
[group('quality')]
format:
#!/usr/bin/env bash
set -uo pipefail
pids=()
dotnet csharpier format . & pids+=($!)
(cd {{ts}} && deno task fmt:fix) & pids+=($!)
code=0
for pid in "${pids[@]}"; do wait "$pid" || code=1; done
exit $code

# Format .NET only (CSharpier)
[group('quality')]
format-dotnet:
dotnet csharpier format .

# Format the TypeScript client only (deno fmt)
[group('quality')]
format-ts:
cd {{ts}} && deno task fmt:fix

# Lint the TypeScript client (deno lint)
[group('quality')]
lint:
cd {{ts}} && deno task lint

# Type-check and format-check everything, no fixes (.NET + TypeScript) in parallel
[group('quality')]
check:
#!/usr/bin/env bash
set -uo pipefail
pids=()
dotnet csharpier check . & pids+=($!)
(cd {{ts}} && deno task check && deno task lint && deno task fmt) & pids+=($!)
code=0
for pid in "${pids[@]}"; do wait "$pid" || code=1; done
exit $code

# Run .NET + TypeScript unit tests in parallel (excludes the contract suite; see test-contract)
[group('quality')]
test:
#!/usr/bin/env bash
set -uo pipefail
pids=()
dotnet test --configuration Release & pids+=($!)
(cd {{ts}} && deno task test) & pids+=($!)
code=0
for pid in "${pids[@]}"; do wait "$pid" || code=1; done
exit $code

# .NET tests only (JsonApiToolkit.Tests)
[group('quality')]
test-dotnet:
dotnet test --configuration Release

# TypeScript client unit tests only
[group('quality')]
test-ts:
cd {{ts}} && deno task test

# Build & run ContractApi (default + all-strict-opt-ins), run the Deno contract suite, then stop the servers
[group('quality')]
test-contract:
#!/usr/bin/env bash
set -euo pipefail
dotnet build {{sample}} --configuration Release
ASPNETCORE_URLS=http://localhost:5198 \
dotnet run --project {{sample}} --configuration Release --no-build &
default_pid=$!
JSONAPI_STRICT=true ASPNETCORE_URLS=http://localhost:5199 \
dotnet run --project {{sample}} --configuration Release --no-build &
strict_pid=$!
trap 'kill $default_pid $strict_pid 2>/dev/null || true' EXIT

for url in http://localhost:5198/articles http://localhost:5199/articles; do
timeout 60 bash -c "until curl -sf -o /dev/null $url; do sleep 1; done"
done

cd {{ts}} && deno task test:contract

# Everything CI runs: format check, unit tests, and the contract suite
[group('quality')]
test-all: check test test-contract

# ---------------------------------------------------------------------------
# Clean
# ---------------------------------------------------------------------------

# Remove build artifacts (.NET bin/obj)
[group('clean')]
clean:
#!/usr/bin/env bash
set -uo pipefail
dotnet clean JsonApiToolkit.sln > /dev/null 2>&1 || true
find . -type d \( -name bin -o -name obj \) -prune -exec rm -rf {} +
echo "Cleaned build artifacts."
3 changes: 3 additions & 0 deletions mise.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
[tools]
dotnet = "10.0.201"
deno = "2.7.13"
just = "latest"
lefthook = "latest"
Loading