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
63 changes: 63 additions & 0 deletions .github/workflows/build-test-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Build, Test & Publish
permissions:
contents: write
packages: write

on:
push:
branches: [master]
pull_request:

jobs:
build:
name: Build, Test & Publish
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4.2.2
with:
fetch-depth: 0
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "10.x"
- name: Restore dependencies
run: dotnet restore Netler.sln
- name: Build
run: dotnet build Netler.sln --no-restore
- name: Test
run: dotnet test Netler.sln --no-build --verbosity normal
- name: Get version
if: github.ref_name == github.event.repository.default_branch
id: version
run: |
dotnet tool install --global nbgv
echo "version=$(nbgv get-version -v NuGetPackageVersion)" >> "$GITHUB_OUTPUT"
- name: Generate release notes
if: github.ref_name == github.event.repository.default_branch
id: release-notes
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
{
echo 'notes<<RELEASE_NOTES_EOF'
gh api repos/${{ github.repository }}/releases/generate-notes \
-f tag_name="v${{ steps.version.outputs.version }}" \
--jq .body
echo 'RELEASE_NOTES_EOF'
} >> "$GITHUB_OUTPUT"
- name: Pack
if: github.ref_name == github.event.repository.default_branch
env:
RELEASE_NOTES: ${{ steps.release-notes.outputs.notes }}
run: |
printf '%s' "$RELEASE_NOTES" > release-notes.txt
dotnet pack src/Netler/Netler.csproj -c Release -o .
- name: Publish
if: github.ref_name == github.event.repository.default_branch
run: dotnet nuget push Netler.NET.*.nupkg -k ${{ secrets.NUGET_KEY }} -s https://api.nuget.org/v3/index.json
- name: Create GitHub Release
if: github.ref_name == github.event.repository.default_branch
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release create "v${{ steps.version.outputs.version }}" --generate-notes --title "v${{ steps.version.outputs.version }}"
86 changes: 86 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# AGENTS.md

Guidelines for AI agents (Copilot, Claude, etc.) contributing to Netler.NET.

---

## Project Structure & Module Organization

```
Netler.sln — Solution root
mise.toml — Tool versions (dotnet 10)
version.json — Nerdbank.GitVersioning config (version 2.0, branch: master)
.github/workflows/
build-test-publish.yml — CI: build, test, pack, publish to NuGet, create GitHub release
src/
Netler/
Server.cs — TCP server with fluent builder API
Client/ — Client-side connection logic
Messages/ — MessagePack-serialized message types
Request.cs — Request model
Response.cs — Response model
StreamExtensions.cs — Stream helpers (4-byte length-prefixed framing)
tests/
UnitTests/
RequestTests.cs — Protocol parsing tests (isolated)
ResponseTests.cs — Protocol parsing tests (isolated)
IntegrationTests/
ServerTests.cs — Full server↔client TCP round-trip tests
sleep.sh / sleep.cmd — Helper scripts used by integration tests
DOCS.md — Hand-maintained API documentation
```

---

## Build, Test, and Development Commands

```sh
# Restore dependencies
dotnet restore Netler.sln

# Build entire solution
dotnet build Netler.sln

# Run all tests
dotnet test Netler.sln

# Run only unit tests
dotnet test tests/UnitTests/UnitTests.csproj

# Run only integration tests
dotnet test tests/IntegrationTests/IntegrationTests.csproj

# Pack NuGet package (Release configuration)
dotnet pack src/Netler/Netler.csproj -c Release
```

---

## Coding Style & Naming Conventions

- Follow standard C# conventions:
- PascalCase for public members, types, and namespaces
- camelCase for local variables and parameters
- Braces on their own lines (Allman style)
- All TCP message payloads are serialized with **MessagePack** — do not introduce other serialization formats
- The server API uses a fluent builder style: `Server.Create(config => ...)` — preserve this pattern
- Messages are length-prefixed with a **4-byte header** describing the content length — maintain this framing
- Avoid compiler warnings; fix or suppress with justification if unavoidable

---

## Testing Guidelines

- Both test projects use the **xUnit** framework
- **UnitTests**: test protocol logic (request/response parsing) in isolation — no network I/O
- **IntegrationTests**: test full server↔client TCP round-trips; rely on `sleep.sh`/`sleep.cmd` helpers
- Run `dotnet test Netler.sln` locally before opening a PR
- Name test methods using the pattern: `Scenario_UnderTest_ExpectedOutcome`

---

## Commit & PR Guidelines

- Use present-tense imperative voice: `Add route parameter validation`, `Fix null reference in response parser`
- Use `[skip ci]` in the commit message only for documentation-only commits (e.g. README/DOCS updates) — GitHub Actions respects this convention
- PR descriptions should explain the change and reference which tests cover it
Loading